The resulting Spark Core firmware works just fine (displaying humidity and temp on the OLED etc.) except when I completely power-up the core from scratch. In these situations, the core seems to enter an endless restart cycle sometime after calling display.begin(SSD1306_SWITCHCAPVCC, 0x3D). (I get multiple, identical Serial.println() outputs when I keep reconnecting the serial monitor.)
However, the above
does not happen after reflashing the firmware (no power cycle)
can be mitigated by pressing the reset button on the Spark (after power-up).
In both cases, the device resets just fine and works like a charm.
I am currently at a loss when it comes to understanding the fine differences of power-up vs. reset and would appreciate helpful pointers. Similarly, if you have hints on how to help the analysis of the above behavior, I’ll be happy to try. Thanks!
What would be a good place to post the code (apologies for asking, first time around for me)? It’s about 120 lines not including the lib code. Mostly a combination of sample code from the libs I’m using, so nothing special as far as I can tell.
More importantly, I took a shortcut and flashed a second one (yes, I’m using Spark Cores) myself, same result. Works after reset, but not after power-up.
#include "Adafruit_SSD1306.h"
#include "PietteTech_DHT.h"
//
// Don't require cloud connection / wifi
//
// SYSTEM_MODE(SEMI_AUTOMATIC);
//
// OLED DEFINES
//
#define OLED_RESET D4
Adafruit_SSD1306 display(OLED_RESET);
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
//
// DHT22 LIB DEFINES
//
#define DHTTYPE DHT22
#define DHTPIN 2
#define DHT_SAMPLE_INTERVAL 60000 // Sample every minute
//declaration
void dht_wrapper(); // must be declared before the lib initialization
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);
// globals
unsigned int DHTnextSampleTime; // Next time we want to start sample
bool bDHTstarted; // flag to indicate we started acquisition
int n; // counter
double humid;
double temp;
void setup() {
// initialize with the I2C addr 0x3D (for the 128x64)
display.begin(SSD1306_SWITCHCAPVCC, 0x3D);
// init done
display.setTextSize(1);
display.setTextColor(WHITE);
// set the time for next sample
DHTnextSampleTime = 0;
// Publish some variables
Particle.variable("h", humid);
Particle.variable("t", temp);
}
// This wrapper is in charge of calling
// must be defined like this for the lib work
void dht_wrapper() {
DHT.isrCallback();
}
void loop() {
// Check if we need to start the next sample
if (millis() > DHTnextSampleTime) {
if (!bDHTstarted) { // start the sample
DHT.acquire();
bDHTstarted = true;
}
if (!DHT.acquiring()) { // has sample completed?
// get DHT status
int result = DHT.getStatus();
switch (result) {
case DHTLIB_OK:
case DHTLIB_ERROR_CHECKSUM:
case DHTLIB_ERROR_ISR_TIMEOUT:
case DHTLIB_ERROR_RESPONSE_TIMEOUT:
case DHTLIB_ERROR_DATA_TIMEOUT:
case DHTLIB_ERROR_ACQUIRING:
case DHTLIB_ERROR_DELTA:
case DHTLIB_ERROR_NOTSTARTED:
default:
Particle.publish("err", "Unknown error");
break;
}
display.clearDisplay();
display.setCursor(0,0);
humid = DHT.getHumidity();
temp = DHT.getCelsius();
display.print("Humidity: ");
display.println(humid, 2);
display.print("Temperature: ");
display.println(temp, 2);
display.println();
display.print("Connected: ");
if (Particle.connected()) {
display.println("yes");
} else {
display.println("no");
}
display.display();
n++; // increment counter
bDHTstarted = false; // reset the sample flag so we can take another
DHTnextSampleTime = millis() + DHT_SAMPLE_INTERVAL; // set the time for next sample
}
}
}
I have had issues with the piette library on the Spark Core, not soo on the Photon. I did find the Adafruit_DHT library seemed more stable. I didnt spend anytime getting to the bottom of the issue.
You’d need to add a break; after case DHTLIB_OK: otherwise you’ll always get an “Unknown error” event published.
Do you by any chance remember if you ever applied a bootloader patch?
If not, you can download the patch and flash it via CLI particle flash --usb core-firmware.bin.
Thanks! That’s interesting. Ok, here’s to your points:
I’m using Particle Dev and / or CLI, not Web
thanks for the hint on the break (I scrubbed the code a bit before I posted it and overdid that)!
not sure where I2C vs. SPI makes a difference but worth a try, as indicated by your experience and … (see below)
yes, I applied a bootloader patch just yesterday because it was mentioned as a potential solution in a hang situation that seemed similar to mine (though using different sensors etc.) but it did not change the result.
EDIT
Grand reveal: maybe I should have thought of it before, but I finally tried to power the OLED and the DHT using Vin as opposed to 3.3V and that helped. This said, I modified the code to look like this […]
My apologies, but I need to retract my earlier statement and code, as I had wrongly wired the OLED - funny though because it actually worked
I went back to testing the DHT and SSD1306 libs separately and tracked the lock up situations down to my use of the SSD1306 lib. I’ll investigate further and also try the SPI route later and report back.
I didn’t realize you tried I2C (since the display is set for SPI by default and you didn’t mention any HW adaptions).
For I2C you’d need to solder a jumper on the flip side if the display.
My bad, I should have mentioned that (I’ll update the topic to reflect it).
Anyway, I had the jumpers soldered (remember, it worked except for the “cold” start scenario) for I2C and I now ‘opened’ them in order to facilitate the SPI variant.
To provide the background story on why I2C - originally, I worked with the display using Johnny Five (http://johnny-five.io) and OLED-JS (https://github.com/noopkat/oled-js). It did what it should, but just as the OLED-JS github page says, it is really slow with SPI… Hence I decided to switch to I2C.
When I then took the step to integrate the DHT22 and to use the two libs I mentioned in my first post, I did not reverse that decision.
Anyway, it’s working like a charm now with SPI, and since I finally had the opportunity for a chat with a friend I now believe to understand why I2C sometimes worked and sometimes not. Maybe I’ll give it another try some other time, but for now, all is well and I can continue with other parts of the project.