SparkFun will be closed on Tuesday, December 24th, and Wednesday, December 25th, in observance of the Christmas holiday. Any orders qualifying for same day shipping placed after 2:00 p.m. (MST) on Monday, December 23rd, will be processed on Thursday, December 26th, when we return to regular business hours. Wishing you a safe and happy holiday from all of us at SparkFun!
Please note - we will not be available for Local Pick up orders from December 24th-December 27th. If you place an order for Local Pick-Up we will have those ready on Monday, December 30th.
We write a lot of libraries for I2C based devices. And we try really hard to genericize the library so that you can use our library with Wire, but also with Wire1 or Wire2 if you've got a platform that has additional I2C hardware (such as the SparkFun SAMD21 boards or the Teensy). But what about SoftwareWire?
There's been some really great advancements with software, also known as bit-banged, I2C libraries. These work well but can we write a library that can inherit a TwoWire stream such as this:
mySensor.begin(Wire1);
and do the same for a SoftwareWire stream such as this:
mySensor.begin(myWire);
It turns out it's possible but not pretty. Please understand, I am not an advanced programmer. I know enough to write a library but when it comes to classes and C++ inheritance I am very much at a loss.
Here is my attempt at writing a genericized library for both hardware and software I2C. The .begin call is overloaded with TwoWire and SoftwareWire references. The low level I2C commands are selected based upon which .begin function was called. It compiles, and best of all, it works! The down side is that it uses duplicate code. It also requires the user to have the SoftwareWire library installed before any example sketch will compile. There's got to be a better way.
So here's a shout out to all you gurus: is there a way to pass a reference or pointer of a software-based I2C stream to a library in a more elegant way?
Short of a better solution, we'll be trying out the above implementation in some of our newer I2C libraries. You can see our first attempt in the SparkFun BME280 Library.
==============
Update!
Here's the new code. We've discovered a slightly better way to do this with templates. It makes it so the user doesn't have to have Software I2C library installed, and removes duplicate code, but it does add a slight complexity to the instantiation of the class. For hardware I2C it looks like this:
myClass <TwoWire> mySensor; //Use for hardware I2C
For software I2C it looks like this:
myClass <SoftwareWire> mySensor; //Use for software I2C
Not too bad!
Here's the main sketch:
//Use for hardware I2C
#include <Wire.h>
//Use for software I2C
//#include <SoftwareWire.h> //SoftwareWire by Testato. Installed from library manager.
//SoftwareWire myWire(6, 7); //SDA, SCL
#include "Generic_I2C_Library.h"
myClass <TwoWire> mySensor; //Use for hardware I2C
//myClass <SoftwareWire> mySensor; //Use for software I2C
void setup()
{
Serial.begin(9600);
Serial.println("Example using software I2C and hardware I2C");
byte result;
//Softwareware I2C
//myWire.begin();
//mySensor.begin(myWire);
//Hardware
Wire.begin();
mySensor.begin();
result = mySensor.readRegister(0xD0); //This reads the chip ID register of the BME280: https://www.sparkfun.com/products/14348
Serial.print("Result: 0x");
Serial.println(result, HEX);
}