Instead of starting with the library which is kind of hard to find! I started with the code you posted. Unfortunately it’s not the right code, and not complete. Don’t worry about it! We’ll get this working soon enough.
I updated my gist with the right code, but it’s not compiling yet. They tried to speed up the I2C with low level port writes and stuff, so I’m going to have to hack that all back to something that just uses the Wire() commands. I’m also a little confused about some parts at the moment because it seems like their new LiquidCrystal lib should be using the MCP23008 library for the I2C writes, but it’s not from what I can tell. I’ll keep at it, as I get some time here… and update this thread when I get it compiling!
So, just so I understand… if I ignore the Adafruit lib (and other code) and just try and use the Wire() stuff to get simple responses from the backpack, it should wok to prove I am communicating - then I could build up to real control?
Yes you could, but you’d have to figure out how the MCP23008 works… there is a library for it, but it will take a bunch of hacking just to start with that. I’ll be working on this more tonight so if you are around stay tuned.
There is a problem after a while - sometimes after 3 seconds, sometimes after 300. A memory leak rears it’s ugly head and kills the app. I think it is in the library code.
Hmm, that almost looks like a cool movie prop now!
LCD’s a finicky if you don’t send them the right timing on things… but the difference is we have a I2C to I/O expander in between… so it could be something like the I2C getting corrupted for just one special byte and then the LCD is out of wack until you re-sync it.
We could easily set up a way to re-init the LCD after it goes wacky by setting D0 input low. Would take a little code, but would be worth it. Just debounce the input with a hard delay and a second if statement for speed.
pinMode(D0, INPUT_PULLUP); // in setup()
if(digitalRead(D0) == LOW) { // in loop()
delay(100);
if(digitalRead(D0) == LOW) {
lcd.begin(16,2); // this also clears the display
}
}
@BDub - what would be a way to try and resolve that issue? Can I slow down the I2C somehow … or make it more resilient?
Embedded items like this are for naught if they aren’t reliable for hours / days / weeks - it is their whole point in a way. The reset is a good idea, though I suspect still a memory glitch.
it doesn’t always freak out the same way
when it happens, the spark sometimes stops “breathing”
I wish the Spark still had the serial monitor functionality (but it doesn’t seem to?) - I could track the memory and status independent of the LCD.
So if I add a lcd.clear() before my updates, it fails much less often, though it did happen once (unless that was a transient). Unfortunately that is a 2000 microsecond delay each time I have to do it (I will be expanding on this update division triggering code later - i feel a class coming on) though fortunately that isn’t every loop() cycle.
Anyway, I cannot accept this delay forever - but that it works may give us more of a hint. It is in updateLcdTickStart() for those playing at home.
@Soulhuntre definitely not related to the 7-bit / 8-bit thing… if it works at all, then the addressing is good.
Did you try the re-init thing after it gets corrupted?
Can you tell if the core is even running after it gets corrupted? (You mentioned it stops breathing cyan, does your log stop?)
Do you have access to an oscilloscope? It would be good to compare the I2C speed of the Arduino vs. the Core.
Doesn’t seem to be an exposed way to slow down the Core’s Wire() I2C transmission speed.
I had a thought that maybe the CC3000 is interrupting the I2C and causing clock stretching or other glitches that may be affecting the LCD synchronization.
Try adding __disable_irq(); and __enable_irq(); around the Wire.endTransmission(); in 3 places in the library:
This is frustrating enough I went ut to pick up a Beal Board Black and a Arduino Yun today. Wound up with neither, the Spark still seems like the right answer - but these sorts of issues are a source of concern.
@BDub Using this code (below) yeah, hitting the button I have on D6 will bring back the LCD after it freaks out. The IRQ disable code would kill the LCD, the Serial and the Cloud connection eventually, so it is disabled here.
Sometimes this dies in a way that lets the serial log keep going, but SOMETIMES rarely it does die in a way that kills the log it seems, when that happens, the LCD reset button on D6 has no effect. Odd. I tried this on my backup Spark, same thing.
Good to know the reset stuff is working at least. Maybe when it won’t work, try cycling power on just the LCD first, then hit the D6 reset. It really sounds like the data is getting corrupted, or clock stretched, or incompatible timing.
It’s pretty hard to debug sometimes without physical hardware and a scope/logic analyzer.
Maybe someone with a logic analyzer and I2C LCD’s like @timb can chime in here and offer some suggestions.
@bdub - thanks for all your help, I really appreciate the time you spent on this.
For now, I guess I’ll do some ordering and see if I can grab a more serial oriented LCD for use with the Spark. What I am more concerned with is how fragile I2C seems to be on the Spark… if it was just this backpack, or some Adafruit weirdness that would be OK, but without absolutely robust I2C the Spark becomes less attractive for some things.
Agreed! Which is why I want to get to the bottom of this If I could buy one of everything, I would. It really helps to have stuff in hand to test. I do have a serial backpack LCD I could try along with you. Kind of a different animal though since the serial is not directly controlling I/O like the MCP23008.
Maybe it would be wise to try your SPI out on that backpack. I’m not sure the library for the I2C / SPI is the most effecient for SPI use only. It just so happens today I converted a library to work with just the LiquidCrystal library and SPI. It’s not verified yet, but it looks like it will be easy to hook up to your LCD backpack: