So I finally got my I2C LCD working and it’s great!
However I’ve written a simple program to count seconds and display and after 600+ seconds the photon freezes. I’ve seen similar issues on the forum, but I have a slight difference. Here are the details:
I’m running firmware 0.4.5
I’m using this LCD from adafruit
When it freezes:
Freezing means that the code on the Photon does not fire at all. No setup code, no loop. However the device still breaths cyan LED. It looks like it’s working normally.
Hitting the reset button on the photon, it resets but it’s still locked up
I can flash new code on the photon (but it’s still locked up)
The setup method does not run
The loop does not run
No events are fired from the photon or received by the photon.
Pulling the power on the whole setup (photon) will fix the issue till in reoccurs.
Pulling the power from the LCD and pressing the reset button on the Photon also fixes the issue (allows code to continue running on the photon till it reoccurs and locks up).
Code running looks like this:
#include "Adafruit_RGBLCDShield/Adafruit_RGBLCDShield.h"
// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
// These #defines make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7
void setup() {
// pinMode(D0, INPUT_PULLUP);
// Debugging output
Serial.begin(9600);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD. We track how long it takes since
// this library has been optimized a bit and we're proud of it :)
int time = millis();
lcd.print("Hello, world!");
time = millis() - time;
Serial.print("Took "); Serial.print(time); Serial.println(" ms");
lcd.setBacklight(WHITE);
}
void loop() {
lcd.clear();
lcd.print(millis()/1000);
}
I’m trying to build something that will run for days/weeks but with this issue it’s not feasible to use the photon.
The Adafruit RGBLCDShield uses a MCP23017 I2C I/O Expander. You will find others have had problems with this chip with the current Photon firmware if you search the forums for MCP23017. It is almost certainly caused by a timing bug in the HAL_I2c.c driver that causes an ACK instead of an NACK to be sent to the device at the end of an I2C read sequence. The only way to resolve this is to reset the MCP23017 or send it a dummy NACK sequence by generating your owns 9 clock cycles on SCL with SDA pulled high. I see in github issues that a wire.Reset() function will be in the next firmware cycle to do exactly that, although I would rather see Particle fix the real problem. I have sent @bdub some information on what I think the issue is and how I feel it can be resolved. I can send you the same doc if you PM me with your email address.
From my understanding its an issue with the hardware.
Currently there are only work arounds to this problem.
I’ve dump my project that uses the MCP23017 and am currently in the process of rebuilding it with a Shift Register. Unfortunate but I couldn’t find a way to reliably find when the i2c died and then reset it.
You’ll need the local toolchain to build, although I’m happy to provide binaries for anyone that wants to test this that doesn’t have access to the local toolchain.
Discourse doesn’t support uploading binaries, so I renamed it to .gif. To flash, right-click the small square, choose “download image”, download and rename the file to system-part2-i2c-fix.bin the file then run
dfu-util -d 2b04:d006 -a 0 -s 0x8060000 -D system-part2-i2c-fix.bin
You should already have system firmware 0.4.5 on your device.
I’ve been using the fix on 2 MCP23017 for 24 hours and they are still running strong.
My test code would usually freeze the i2c bus within 10-30 mins and zero issues so far. I’ll keep testing and report back after it runs for a couple days.
Is this a fix to i2c rather than a library for the MCP? I’m currently using a spark core and find if I include the PCA9685 library in my code the system crashes constantly. Just wondering if this is a likely fix for that too?
It addresses a suspected timing issue when changing from ACK to NACK responses doing reads within the I2C driver. It seems unlikely that it would fix your problem. The binary that MDMA posted is only applicable to the Photon at this point.
I’ve seen mention of problems with no i2c device connected though, and I am also seeing this, and also saw the same issue with the bus being held low. I suspect it is the same issue. I have a couple of Photons on the way to me so will be interesting to try it out when they arrive.
If this indeed fixes the I2C problem then I’m sure Particle will also apply it to the Core as well, as the I2C driver implementation is? (was) similar and both the STM device’s I2C interfaces are also similar. The difference of course is the clock speed and the STM32F20X therefore executes code much faster. Therefore timing related problems will manifest themselves differently, I’m sure.