Skip to content

Instantly share code, notes, and snippets.

@MrTrick
Last active January 2, 2016 02:18
Show Gist options
  • Save MrTrick/8235855 to your computer and use it in GitHub Desktop.
Save MrTrick/8235855 to your computer and use it in GitHub Desktop.
Workaround for getting **both** a V2 motor shield and a LED backpack working from the same Arduino. tl;dr; Create a **separate** bitbanged i2c bus on regular IO pins. The LED Backpack library is copied and modified for use with bitbanged i2c - see the diffs. Instructions; 1. Copy the cpp and h file into your project directory. 2. Depends on the …
21,28c21,27
< //#ifdef __AVR_ATtiny85__
< // #include <TinyWireM.h>
< // #define Wire TinyWireM
< //#else
< // #include <Wire.h>
< //#endif
< #include <SoftI2CMaster.h>
< #include "Mindbleach_LEDBackpack.h"
---
> #ifdef __AVR_ATtiny85__
> #include <TinyWireM.h>
> #define Wire TinyWireM
> #else
> #include <Wire.h>
> #endif
> #include "Adafruit_LEDBackpack.h"
52,54c51,53
< wire.beginTransmission(i2c_addr);
< wire.send(0xE0 | b);
< wire.endTransmission();
---
> Wire.beginTransmission(i2c_addr);
> Wire.write(0xE0 | b);
> Wire.endTransmission();
58c57
< wire.beginTransmission(i2c_addr);
---
> Wire.beginTransmission(i2c_addr);
61,62c60,61
< wire.send(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
< wire.endTransmission();
---
> Wire.write(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
> Wire.endTransmission();
68c67
< void Adafruit_LEDBackpack::begin(const byte sdapin, const byte sclpin, uint8_t _addr = 0x70) {
---
> void Adafruit_LEDBackpack::begin(uint8_t _addr = 0x70) {
71c70
< wire = SoftI2CMaster(sdapin, sclpin);
---
> Wire.begin();
73,75c72,74
< wire.beginTransmission(i2c_addr);
< wire.send(0x21); // turn on oscillator
< wire.endTransmission();
---
> Wire.beginTransmission(i2c_addr);
> Wire.write(0x21); // turn on oscillator
> Wire.endTransmission();
82,83c81,82
< wire.beginTransmission(i2c_addr);
< wire.send((uint8_t)0x00); // start at address $00
---
> Wire.beginTransmission(i2c_addr);
> Wire.write((uint8_t)0x00); // start at address $00
86,87c85,86
< wire.send((uint8_t)(displaybuffer[i] & 0xFF));
< wire.send((uint8_t)(displaybuffer[i] >> 8));
---
> Wire.write(displaybuffer[i] & 0xFF);
> Wire.write(displaybuffer[i] >> 8);
89c88
< wire.endTransmission();
---
> Wire.endTransmission();
355d353
<
27,32c27,31
< //#ifdef __AVR_ATtiny85__
< // #include <TinyWireM.h>
< //#else
< // #include <Wire.h>
< //#endif
< #include <SoftI2CMaster.h>
---
> #ifdef __AVR_ATtiny85__
> #include <TinyWireM.h>
> #else
> #include <Wire.h>
> #endif
60c59
< void begin(const byte sdapin, const byte sclpin, uint8_t _addr);
---
> void begin(uint8_t _addr);
71,72d69
< SoftI2CMaster wire;
<
131d127
<
/***************************************************
* THIS FILE HAS BEEN MINIMALLY MODIFIED TO USE
* SOFTWARE i2c ALL FEATURES OF THE LIBRARY REMAIN THE SAME,
* EXCEPT THAT begin() has signature;
* Adafruit_LEDBackpack::begin(const byte sdapin, const byte sclpin, uint8_t _addr = 0x70)
***************************************************
This is a library for our I2C LED Backpacks
Designed specifically to work with the Adafruit LED Matrix backpacks
----> http://www.adafruit.com/products/
----> http://www.adafruit.com/products/
These displays use I2C to communicate, 2 pins are required to
interface. There are multiple selectable I2C addresses. For backpacks
with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
with 3 Address Select pins: 0x70 thru 0x77
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
//#ifdef __AVR_ATtiny85__
// #include <TinyWireM.h>
// #define Wire TinyWireM
//#else
// #include <Wire.h>
//#endif
#include <SoftI2CMaster.h>
#include "Mindbleach_LEDBackpack.h"
#include "Adafruit_GFX.h"
static const uint8_t numbertable[] = {
0x3F, /* 0 */
0x06, /* 1 */
0x5B, /* 2 */
0x4F, /* 3 */
0x66, /* 4 */
0x6D, /* 5 */
0x7D, /* 6 */
0x07, /* 7 */
0x7F, /* 8 */
0x6F, /* 9 */
0x77, /* a */
0x7C, /* b */
0x39, /* C */
0x5E, /* d */
0x79, /* E */
0x71, /* F */
};
void Adafruit_LEDBackpack::setBrightness(uint8_t b) {
if (b > 15) b = 15;
wire.beginTransmission(i2c_addr);
wire.send(0xE0 | b);
wire.endTransmission();
}
void Adafruit_LEDBackpack::blinkRate(uint8_t b) {
wire.beginTransmission(i2c_addr);
if (b > 3) b = 0; // turn off if not sure
wire.send(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
wire.endTransmission();
}
Adafruit_LEDBackpack::Adafruit_LEDBackpack(void) {
}
void Adafruit_LEDBackpack::begin(const byte sdapin, const byte sclpin, uint8_t _addr = 0x70) {
i2c_addr = _addr;
wire = SoftI2CMaster(sdapin, sclpin);
wire.beginTransmission(i2c_addr);
wire.send(0x21); // turn on oscillator
wire.endTransmission();
blinkRate(HT16K33_BLINK_OFF);
setBrightness(15); // max brightness
}
void Adafruit_LEDBackpack::writeDisplay(void) {
wire.beginTransmission(i2c_addr);
wire.send((uint8_t)0x00); // start at address $00
for (uint8_t i=0; i<8; i++) {
wire.send((uint8_t)(displaybuffer[i] & 0xFF));
wire.send((uint8_t)(displaybuffer[i] >> 8));
}
wire.endTransmission();
}
void Adafruit_LEDBackpack::clear(void) {
for (uint8_t i=0; i<8; i++) {
displaybuffer[i] = 0;
}
}
Adafruit_8x8matrix::Adafruit_8x8matrix(void) : Adafruit_GFX(8, 8) {
}
void Adafruit_8x8matrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
if ((y < 0) || (y >= 8)) return;
if ((x < 0) || (x >= 8)) return;
// check rotation, move pixel around if necessary
switch (getRotation()) {
case 1:
swap(x, y);
x = 8 - x - 1;
break;
case 2:
x = 8 - x - 1;
y = 8 - y - 1;
break;
case 3:
swap(x, y);
y = 8 - y - 1;
break;
}
// wrap around the x
x += 7;
x %= 8;
if (color) {
displaybuffer[y] |= 1 << x;
} else {
displaybuffer[y] &= ~(1 << x);
}
}
Adafruit_BicolorMatrix::Adafruit_BicolorMatrix(void) : Adafruit_GFX(8, 8) {
}
void Adafruit_BicolorMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
if ((y < 0) || (y >= 8)) return;
if ((x < 0) || (x >= 8)) return;
switch (getRotation()) {
case 1:
swap(x, y);
x = 8 - x - 1;
break;
case 2:
x = 8 - x - 1;
y = 8 - y - 1;
break;
case 3:
swap(x, y);
y = 8 - y - 1;
break;
}
if (color == LED_GREEN) {
displaybuffer[y] |= 1 << x;
} else if (color == LED_RED) {
displaybuffer[y] |= 1 << (x+8);
} else if (color == LED_YELLOW) {
displaybuffer[y] |= (1 << (x+8)) | (1 << x);
} else if (color == LED_OFF) {
displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8));
}
}
Adafruit_7segment::Adafruit_7segment(void) {
position = 0;
}
void Adafruit_7segment::print(unsigned long n, int base)
{
if (base == 0) write(n);
else printNumber(n, base);
}
void Adafruit_7segment::print(char c, int base)
{
print((long) c, base);
}
void Adafruit_7segment::print(unsigned char b, int base)
{
print((unsigned long) b, base);
}
void Adafruit_7segment::print(int n, int base)
{
print((long) n, base);
}
void Adafruit_7segment::print(unsigned int n, int base)
{
print((unsigned long) n, base);
}
void Adafruit_7segment::println(void) {
position = 0;
}
void Adafruit_7segment::println(char c, int base)
{
print(c, base);
println();
}
void Adafruit_7segment::println(unsigned char b, int base)
{
print(b, base);
println();
}
void Adafruit_7segment::println(int n, int base)
{
print(n, base);
println();
}
void Adafruit_7segment::println(unsigned int n, int base)
{
print(n, base);
println();
}
void Adafruit_7segment::println(long n, int base)
{
print(n, base);
println();
}
void Adafruit_7segment::println(unsigned long n, int base)
{
print(n, base);
println();
}
void Adafruit_7segment::println(double n, int digits)
{
print(n, digits);
println();
}
void Adafruit_7segment::print(double n, int digits)
{
printFloat(n, digits);
}
size_t Adafruit_7segment::write(uint8_t c) {
uint8_t r = 0;
if (c == '\n') position = 0;
if (c == '\r') position = 0;
if ((c >= '0') && (c <= '9')) {
writeDigitNum(position, c-'0');
r = 1;
}
position++;
if (position == 2) position++;
return r;
}
void Adafruit_7segment::writeDigitRaw(uint8_t d, uint8_t bitmask) {
if (d > 4) return;
displaybuffer[d] = bitmask;
}
void Adafruit_7segment::drawColon(boolean state) {
if (state)
displaybuffer[2] = 0xFF;
else
displaybuffer[2] = 0;
}
void Adafruit_7segment::writeDigitNum(uint8_t d, uint8_t num, boolean dot) {
if (d > 4) return;
writeDigitRaw(d, numbertable[num] | (dot << 7));
}
void Adafruit_7segment::print(long n, int base)
{
printNumber(n, base);
}
void Adafruit_7segment::printNumber(long n, uint8_t base)
{
printFloat(n, 0, base);
}
void Adafruit_7segment::printFloat(double n, uint8_t fracDigits, uint8_t base)
{
uint8_t numericDigits = 4; // available digits on display
boolean isNegative = false; // true if the number is negative
// is the number negative?
if(n < 0) {
isNegative = true; // need to draw sign later
--numericDigits; // the sign will take up one digit
n *= -1; // pretend the number is positive
}
// calculate the factor required to shift all fractional digits
// into the integer part of the number
double toIntFactor = 1.0;
for(int i = 0; i < fracDigits; ++i) toIntFactor *= base;
// create integer containing digits to display by applying
// shifting factor and rounding adjustment
uint32_t displayNumber = n * toIntFactor + 0.5;
// calculate upper bound on displayNumber given
// available digits on display
uint32_t tooBig = 1;
for(int i = 0; i < numericDigits; ++i) tooBig *= base;
// if displayNumber is too large, try fewer fractional digits
while(displayNumber >= tooBig) {
--fracDigits;
toIntFactor /= base;
displayNumber = n * toIntFactor + 0.5;
}
// did toIntFactor shift the decimal off the display?
if (toIntFactor < 1) {
printError();
} else {
// otherwise, display the number
int8_t displayPos = 4;
for(uint8_t i = 0; displayNumber; ++i) {
boolean displayDecimal = (fracDigits != 0 && i == fracDigits);
writeDigitNum(displayPos--, displayNumber % base, displayDecimal);
if(displayPos == 2) writeDigitRaw(displayPos--, 0x00);
displayNumber /= base;
}
// display negative sign if negative
if(isNegative) writeDigitRaw(displayPos--, 0x40);
// clear remaining display positions
while(displayPos >= 0) writeDigitRaw(displayPos--, 0x00);
}
}
void Adafruit_7segment::printError(void) {
for(uint8_t i = 0; i < SEVENSEG_DIGITS; ++i) {
writeDigitRaw(i, (i == 2 ? 0x00 : 0x40));
}
}
/***************************************************
* THIS FILE HAS BEEN MINIMALLY MODIFIED TO USE
* SOFTWARE i2c ALL FEATURES OF THE LIBRARY REMAIN THE SAME,
* EXCEPT THAT begin() has signature;
* Adafruit_LEDBackpack::begin(const byte sdapin, const byte sclpin, uint8_t _addr = 0x70)
***************************************************
This is a library for our I2C LED Backpacks
Designed specifically to work with the Adafruit LED Matrix backpacks
----> http://www.adafruit.com/products/
----> http://www.adafruit.com/products/
These displays use I2C to communicate, 2 pins are required to
interface. There are multiple selectable I2C addresses. For backpacks
with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
with 3 Address Select pins: 0x70 thru 0x77
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
//#ifdef __AVR_ATtiny85__
// #include <TinyWireM.h>
//#else
// #include <Wire.h>
//#endif
#include <SoftI2CMaster.h>
#include "Adafruit_GFX.h"
#define LED_ON 1
#define LED_OFF 0
#define LED_RED 1
#define LED_YELLOW 2
#define LED_GREEN 3
#define HT16K33_BLINK_CMD 0x80
#define HT16K33_BLINK_DISPLAYON 0x01
#define HT16K33_BLINK_OFF 0
#define HT16K33_BLINK_2HZ 1
#define HT16K33_BLINK_1HZ 2
#define HT16K33_BLINK_HALFHZ 3
#define HT16K33_CMD_BRIGHTNESS 0x0E
#define SEVENSEG_DIGITS 5
// this is the raw HT16K33 controller
class Adafruit_LEDBackpack {
public:
Adafruit_LEDBackpack(void);
void begin(const byte sdapin, const byte sclpin, uint8_t _addr);
void setBrightness(uint8_t b);
void blinkRate(uint8_t b);
void writeDisplay(void);
void clear(void);
uint16_t displaybuffer[8];
void init(uint8_t a);
private:
uint8_t i2c_addr;
SoftI2CMaster wire;
};
class Adafruit_8x8matrix : public Adafruit_LEDBackpack, public Adafruit_GFX {
public:
Adafruit_8x8matrix(void);
void drawPixel(int16_t x, int16_t y, uint16_t color);
private:
};
class Adafruit_BicolorMatrix : public Adafruit_LEDBackpack, public Adafruit_GFX {
public:
Adafruit_BicolorMatrix(void);
void drawPixel(int16_t x, int16_t y, uint16_t color);
private:
};
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0
class Adafruit_7segment : public Adafruit_LEDBackpack {
public:
Adafruit_7segment(void);
size_t write(uint8_t c);
void print(char, int = BYTE);
void print(unsigned char, int = BYTE);
void print(int, int = DEC);
void print(unsigned int, int = DEC);
void print(long, int = DEC);
void print(unsigned long, int = DEC);
void print(double, int = 2);
void println(char, int = BYTE);
void println(unsigned char, int = BYTE);
void println(int, int = DEC);
void println(unsigned int, int = DEC);
void println(long, int = DEC);
void println(unsigned long, int = DEC);
void println(double, int = 2);
void println(void);
void writeDigitRaw(uint8_t x, uint8_t bitmask);
void writeDigitNum(uint8_t x, uint8_t num, boolean dot = false);
void drawColon(boolean state);
void printNumber(long, uint8_t = 2);
void printFloat(double, uint8_t = 2, uint8_t = DEC);
void printError(void);
private:
uint8_t position;
};
#include <SoftI2CMaster.h>
#include "Mindbleach_LEDBackpack.h"
#include <Adafruit_GFX.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
// Configuration
#define AUGER_OUT 1 //M1 on Adafruit V2 motor shield
#define SEG7_SDA 9
#define SEG7_SCL 13
// Variables and Setup
Adafruit_7segment time_display = Adafruit_7segment();
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *auger = AFMS.getMotor(AUGER_OUT);
// Core Functions
void setup() {
//Motors
AFMS.begin(); //Uses 0x60
auger->run(BACKWARD);
auger->setSpeed(0);
//Comms
time_display.begin(SEG7_SDA, SEG7_SCL, 0x70);
}
boolean x;
void loop() {
auger->setSpeed(100);
delay(3000);
auger->setSpeed(0);
delay(3000);
x = !x;
time_display.print(x?0xDEAD:0xBEEF, HEX);
time_display.writeDisplay();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment