Problems when exiting form standby mode, possible bug

Hello,

I’m experiencing very off behavior on my Photon after it wakes from standby mode. There are 2 issues:

  • it insists on connecting to the cloud, despite being run in MANUAL mode. This seems like a bug
  • OneWire communication is dead. You must be doing something in pre-startup that kills it after exiting from standby. As an ugly workaround I’m calling NVIC_SystemReset(); to force a full restart when the last restart was caused by exiting from standby. It works, but I don’t like it.

So my 2 questions are:

  • how can I prevent photon from connecting to the cloud after exiting from standby (SLEEP_MODE_DEEP)?
  • is there anything I can do to make OneWire work ofter Photon wakes up from standby?

Some additional info:

  • other sleep modes are out of the question as they consume too much power, it has to be standby mode.
  • everything works ok in other sleep modes (ie stop mode), so I assume it has to do specifically with code Photon executes after existing from standby
  • I’m using PA0 GPIO to for OneWire communication. It is possible something is done to this particular GPIO, as it is also connected to WKP as well according to photon docs.

Could we have a minimal example sketch that demonstrates the issue and allows us to reproduce it?

You need to state the system version you are running on your device too.

One thing that most likely happens with deep sleep (but isn’t explicitly documented) is that an internal pull-down will be attached to ensure a successful sensing of a rising edge.

1 Like

I’m using newest available system (v. 8 rc2)

Unfortunately, I have no way to test sample code at present, since the photon is running currently in a different location. I’ll be there during the weekend. But what should work as reproducible example, is simply

#if defined(ARDUINO)
  SYSTEM_MODE(MANUAL);
  STARTUP(System.enableFeature(FEATURE_RESET_INFO));
#endif

uint32_t start;

void setup(){
    if (System.resetReason() == 30){
        NVIC_SystemReset();
    }
}

void loop(){
    if (!WiFi.ready()) {
        connectWiFi();
    }

    // on first run allow 30s to reprogram the device via Particle cloud
    if (System.resetReason() == 40) {
        Particle.connect();
        start = millis();
        while (millis() - start < 30000UL) Particle.process();
    }
   delay(10000); 
   System.sleep(SLEEP_MODE_DEEP, 10);
    
}

just replace connectWiFi(); with whatever you use to connect to wifi (in my case I scan network around in search one of defined SSIDs and connect to it)

What above example does:

  • gives you some time to flash on the first run
  • restarts the device after deep sleep (my workaround fro OneWire not working)
  • waits 10s, sleeps 10s

For OneWire problem:
I’m currently using https://github.com/winlinvip/SimpleDHT lib to connect to DHT22.
I’ve got it defined as

#define DHTPIN A7   
SimpleDHT22 dht22;

So then you can add Wire.begin(); to setup and in loop add

float temperature = 0;
float humidity = 0;
int err = SimpleDHTErrSuccess;
if ((err = dht22.read2(DHTPIN, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
  if(PARTICLE_CLOUD) Particle.publish("Read DHT22 failed, err=", String(err));
  // return;
}

You’ll need DHT22 sensor though…

I'm testing now, but I'd point out some things I'd do differently

First I'm not a fan of using anonymous numeric literals when there are enums available instead.
What are System.resetReason() == 30 & System.resetReason() == 40?
Also what if Particle - for some reason - decides to change the values, which would be perfectly acceptable since the docs do not state these values but the enums?

Instead of

 start = millis();
 while (millis() - start < 30000UL) Particle.process();

I'd use

  if (!waitFor(Particle.connected, 30000)) {
    Particle.disconnect();
    WiFi.off();
  }

As we can't see what your connectWiFi() looks like, I'd just do this as the minimal approach

bool connectWiFi() {
  WiFi.on();
  WiFi.connect();
  return waitFor(WiFi.ready, 60000);
}

Additionally I'd - by default - go with SYSTEM_THREAD(ENABLED) unless I have some particular reason to not do so.

As of your problem

Since the code you have shared above does not terminate the ongoing connetion attempt after 30 seconds and the reset initiated via deep sleep does not reset the WiFi module your system may be left in some kind of limbo state which may well give rise to some problems - so it is good practice to terminate the connection when it's not needed (e.g. for SLEEP_NETWORK_STANDBY).

But your actual problem is this

#if defined(ARDUINO)
  SYSTEM_MODE(MANUAL);
  STARTUP(System.enableFeature(FEATURE_RESET_INFO));
#endif

Since you are not including Arduino.h ARDUINO is not defined and hence you never set SYSTEM_MODE(MANUAL) - or did you intend to write #if !defined(ARDUINO)?
However one might say: "So why does then System.resetReason() work without being enabled?"
Granted, this is a bit misleading as the docs suggest this should be needed, but I think this is just one of these cases where the docs lag behind development :wink: AFAICT it's enabled by default for quite some time now (as it is also used for the status event created by the system).

For your DHT issue I'd rather go with the libraries I already know PietteTech_DHT

But the bug causing your problem with A7 was already reported a while ago (without being confirmed by Particle so far)
https://github.com/particle-iot/firmware/issues/1447
(I've added this thread to the references there)