Issues with wakeup interrupt on SparkCore

Hello,

I’m trying to develop a super simple dash button app using the SparkCore. I want to boot the core, connect to the wifi and send an MQTT message. Then, go to sleep until the button is pressed. For some reason, the sleep/wake loop is not working, and the core wakes up on his own without pushing the button. I’m using the internal pull-up resistor, maybe I need a higher value?

Physical setup is easy: Button connected to 3.3 rail and D1. Code below. Any hints? Thanks!

#include "MQTT.h"

void callback(char* topic, byte* payload, unsigned int length);

byte server[] = { 192,168,1,47 };
MQTT client(server, 1883, callback);

void callback(char* topic, byte* payload, unsigned int length) {
    delay(1000);
}

int button = D1;

void setup() {
    pinMode(button, INPUT_PULLDOWN);
    
    client.connect("sparkclient");

    if (client.isConnected()) {
        client.publish("topic/mytopic","ON");
    }

    System.sleep(button, RISING);
}

void loop() {
    //we should never reach this!
}

Adding more info: The Core is waking up every 15 seconds. Maybe it’s a firmware issue?

@iverona, how long are the wires going to your button? Also, since you are doing a RISING edge, you should be using a PULL_DOWN, not PULL_UP.

Tried even without wires… Same behavior. Any hint on Why is it rebooting every 15 seconds?

@iverona, few things:

  1. An external pull-down may be necessary. I suggest a 4.7K ohm resistor.
  2. You don’t leave any time between the publish and the sleep for the DeviceOS to complete the transaction I suspect. You may want to add a millis() delay within which you call Particle.process() to empty the TCP/UPD buffer.
    uint32_t waitOnPub = millis();
    // Call Particle.process() for 1 sec or whatever time you believe is suitable
    // to allow DeviceOS to complete the transmission.
    while(millis() - waitOnPub < 1000) Particle.process();
  1. You seem to be using SYSTEM_MODE(AUTOMATIC) which will not run the user code until a cloud connection is obtained. Is this your intended approach or did you want to use SYSTEM_MODE(SEMI_AUTOMATIC) and connect to WiFi manually?

You may want to add debugging Serial.print() statements to see if it actually goes to sleep or if it rebooting due to some issue with the MQTT stuff.

1 Like

thanks @peekay123, I changed to SYSTEM_MODE(MANUAL), it’s good to save some seconds. I don’t have a 4.7K resistor at hand now, but will try with different values. What looks strange is that if I just debug with Serial.println the button press, it works with no issues, detecting low and high.

According to the documentation it might be required to update the boot loader?

It is mandatory to update the bootloader (https://github.com/particle-iot/device-os/tree/bootloader-patch-update) for proper functioning of this mode.

I used doctor to recover the device before, so don’t know if that should have updated the boot loader or I do still need to do that manually? How can I check if I have the right version?

Code now looks like this. I assume that if I’m not using any cloud feature I don’t need to call Particle.process()? By the way, the MQTT message is reaching the broker, but the core keeps waking up every 15 seconds. If I press the button before, it wakes up as well.

#include "MQTT.h"

void callback(char* topic, byte* payload, unsigned int length);

byte server[] = { 192,168,1,47 };
MQTT client(server, 1883, callback);

void callback(char* topic, byte* payload, unsigned int length) {
    delay(1000);
}

int button = D1;
int buttonState = 0;

SYSTEM_MODE(MANUAL);

void setup() {
    Serial.begin(9600);
    Serial.println("Start");
    
    pinMode(button, INPUT_PULLDOWN);
    
    WiFi.on();
    WiFi.connect();
    while(!WiFi.ready()) {
        ;
    }
    
    client.connect("sparkclient");

    if (client.isConnected()) {
        client.publish("topic/mytopic","CORE");
    }
}

void loop() {    
    System.sleep(button, RISING, 60);
}

Ok, now it’s working. I had to update the boot loader as stated by the docs. As a reference, find below the steps I followed:

Grab the boot loader image: link
Flash it to the core via:

dfu-util -d 1d50:607f -a 0 -s 0x08005000:leave -D core-firmware.bin

Flash your application again.

Thanks @peekay123 for your help! much appreciated.

2 Likes

@iverona, you should make the following adjustment in your code for the WiFi.ready() part:

    while(!WiFi.ready()) {
        Particle.process();
    }

:wink:

Thanks! What’s exactly Particle.process() doing? Even after reading the docs it’s still not clear to me.

@iverona, Particle.process() allows the system firmware to do its work. It is also called transparently whenever loop() finishes. If the user application prevents the firmware from running for too long (10s), the cloud connection will be lost. On other Particle devices, the firmware takes advantage of FreeRTOS to run independently of the user application.

Understood. One more question: now it takes ~8 seconds from deep sleep to mqtt message being sent. Is there any way to further reduce this time? I’m already using fixed IP for the wifi.