The Core didn't connect to the cloud after waking up from a pin triggered sleep

Hey Folks
I have an issue with my core after I’ve used the pin triggered sleep. The core didn’t connect to the cloud, but it does connect to the wifi. When it tries to connect to the cloud (the RGB led trying to go to a breathing cyan), it turns to the white color and return back to the green led. Any suggestion please?
Here is my code that I’m using:
Many thanks for @ScruffR @peekay123 for helping me in this code:

#include "application.h"
#include "Serial2/Serial2.h"
char szReceive[64] = { '\0' };
int RxPin = D0;
int idx = 0;
uint32_t ms;
uint32_t msPublish;
bool frameStart = false;
void setup()
{
   Serial2.begin(19200);
   Serial.begin(19200);
   pinMode(RxPin, INPUT);
}
void loop()
{
   ms = millis();
   while (Serial2.available() && millis() - ms < 1000 && idx < 38)
   {
     Serial2.flush();
     char c = Serial2.read();
     Serial.write(c);
     if (c == 'S')
     { 
       frameStart = TRUE;
       idx = 0;
     }
     if (frameStart)
     {
       szReceive[idx++] = c;
       szReceive[idx] = '\0';
     }
     }
   Serial.println("Fallen out of while");
   if (idx >= 38 && millis() - msPublish > 1000)
   {
     Serial.println(szReceive);
     Spark.publish("Carpet1", szReceive, PRIVATE);
     msPublish = millis();
            idx = 0;
     frameStart = FALSE;
   }
   Serial.print(idx);
   Serial.print('\t');
   Serial.print(frameStart);
   Serial.println("-----------------------------------");
   Spark.sleep(D0,RISING);
}

I’m facing hard time in testing the code, since I should make a factory reset each time the core goes to the sleep mode to check the modified code. Actually, I don’t know how I can download the new code to the core while it is in the sleep mode.
Thanks in advance.
Ahmed.

Before I look at your code:
When testing code that “interferes” with the cloud connection you should consider flashing via USB (e.g. Particle CLI) or at least add a hardware button to force the Core into “OTA mode” (connect to cloud, and stick in a tight Spark.process() loop).


Don’t do this

   pinMode(RxPin, INPUT);

Serial2 takes care of D0 while your code is running and Spark.sleep(D0, RISING) does set the pin mode to INPUT_PULLDOWN.

If you want to have your remote device wake the Core you could do this (as long your other side doesn’t mind the pull-down resistor), but if not, you should put your wake button on a different pin.


The way you do use Serial2.flush() doesn’t look right there where you put it.

2 Likes

Hello @ScruffR
Starting with the suggestion that you told me about flashing via USB, right now I'm doing particle flash --usb tinker when my device is stuck in the sleep mode. Then, I re-flash it again with the modified code that I have to avoid the factory reset. Secondly, I removed pinMode(RxPin, INPUT); since it will set by the Serial2.h as you told me, and I didn't know that before. I don't know what you mean by saying:

And if there is a disadvantage if I'm using the pull-down resistor with my remote device?

For the:

I tried to follow your previous suggestion in other thread to use pre-flush in my code since you advised me to do it before the read:

At the end, I'm still couldn't make my device connect to the cloud after waking up from the triggered pin sleep.
Thanks.

As for the my previous flush suggestion:
Since your complete "read cycle" consists of multiple calls to Serial2.read() (38 byte), you shall not flush the whole buffer after each read byte, but only once before you enter your "read cycle" (meaning immediately before while()).
Then you drop all the bytes preceeding the first occurence of your start marker (S) and only then you actually start reading your content up to 38 byte (or end mark) - don't leave before you got a full set of bytes, unless you hit your timeout.

Now for flashing via USB you can even build via CLI, when you put your code file in a folder and run this batch file (on Windows, inside the same folder)

del *.bin
REM cmd /c "particle compile photon ."
cmd /c "particle compile core ."
ren *.bin firmware.bin
cmd /c "particle flash --usb firmware.bin"
pause

This way you won't need Tinker in between.

For the pull-down, it depends on your transmitting device.

And for

You might need to decouple the two sides - e.g. transistor or opto isolator.

1 Like

Thanks @ScruffR
When you said:

Did you mean this will happen if I put the Serial2.flush(); immediately before the While()).? Or I should change something else in the code to do that?

I still have concern about the cloud issue after the wake up. I read in other thread that said I should use something like:

if (WiFi.ready()) {
    Spark.connect();
  }
  if (Spark.connected()) {
    Spark.process();
  }

in the loop() to make sure the core will connect to the cloud after wake up from the sleep, but it didn't work. I also noticed some people put these small code in the setup(), and I tried that without success. I did a bootloader patch and a CC3000 update, but the issue still there. Any suggestion will be appreciated.

This is what I meant.
The flush just drops any bytes already in the buffer, which might be holding corrupted data, due to wrapping round the ring buffer.
After that you'll be receiving new bytes, which will most likely be just the finishing bytes of an incomplete 38 byte packet.
So you need to consciously drop all these while carefully waiting for start mark to arrive. In other words, you'll have to look at each of the new bytes dropping any that are not "S".
Only after you've received "S", you'll start storing the bytes, till you got a full 38 byte packet.

I'm only explaining this verbally and don't provide the code not to be awkward but to do help you building up your own imagination and coding skills.


Since your are still using the default SYSTEM_MODE(AUTOMATIC), I don't think you'd need to bother with the connection code you've seen elsewhere.
After a wake on interrupt, the Core will go through the normal startup procedure and setup().

But I think I have to flash some test code on one of my Cores to see if this is a common issue, or you are seeing something unusual.
If the former, than I guess I'll be able to find a way around, if it's the latter, you might have to have a look at your side (hardware, WiFi, sending device, ...).

1 Like

Any suggestion please? @Dave
Thanks in advance.

I’ve figured it out :wink:

Don’t need to bother Dave tho’, since it’s not that the Core does not connect to the cloud, but it just stays connected too short, due to your own code.

So if you look close enough, you might find the issue yourself :+1:

2 Likes

Thanks @ScruffR
Actually, I’m trying to find the issue for many days, but I couldn’t. I’ll try to take a closer look to find out what is the part of my code that prevent the spark from connecting to the cloud for longer time.

Are you on Windows?
If so, you’ll have the “Device connected” sound as soon your code performs Serial.begin(). This only happens after you got connected to the cloud (in AUTOMATIC mode this is).
So if you look at your code what could be cutting the connection and when does it happen?

1 Like

Yes, I’m using Win 8.1. I’ll try to open the serial console as you suggest to see at which place I’m loosing the connection with the cloud😉.
Thanks in advance.

I don’t think you’ll see a lot, due to the same reason as the cloud drops out. Just listen to the sound and look at the RGB LED at the same time.

1 Like

@ScruffR
I couldn’t even connect the console to the device, since the device didn’t show up on the serial console.
I think this means the device code didn’t execute the setup portion.
:disappointed:

Exactly what I'm trying to point you to.

Don't try to read from the console, since your Core is not online long enough. If you did

You would have noticed, that the "Device connected" sound is played and in the very same moment the RGB LED goes out, doesn't it?

And no it's not what you think here

1 Like

Actually, there is no sound coming from the PC to tell me that the serial is activated or not, while there was a serial activated sound when I worked on another code yesterday.

OK, I give in :wink:

The fact is, that once you got connected, your code will rush through setup() and loop() where the last instruction in loop() is Spark.sleep(D0,RISING);, which immediatley kills your serial and cloud connection again.

If you just do something like

  if (millis() > 30000)
    Spark.sleep(D0, RISING);

you’ll let your Core stay awake a bit longer to allow it to show it actually does connect.

2 Likes

So, does this part of the delay will let the device connect to the cloud for just 3 seconds, or it will let the device connect to the cloud and stay connected if there is a data coming to the Serial2?

This code will make your Core stay awake at least 30 seconds after it woke up - no matter what the rest of your code does (unless you send it to sleep somewhere else :sunglasses:) .

1 Like

Yes, it does let the code stay connected to the cloud for 30 seconds, but after that it cut the connection and connect again even with the existing data coming from Serial2. I mean what I need is to make the device on sleep when there is no data on Serial2, and make it stay connected to the cloud when there is a data on Serial2. Otherwise, I’ll lose the data when it is disconnecting and trying to connect again to the cloud.

Serial2 Data = Cloud Connected --> Publish the data to the Cloud.
No Serial2 Data = Sleep for unlimited amount of time.

For this you need to do something similar as I’ve already shown you with the 1sec delay between Spark.publish() calls by use of msPublish.

Abstract:
When your last byte received via Serial2 was more than X seconds ago, then go to sleep and wait for an interrupt on the RX line.

The code for that is simple enough, if you understand what the code, you’re already using actually does.


But with sending the Core to sleep you will inevitably lose some serial data, since the Core needs time to wake and reconnect. So if your sender only pushes out a short burst of data, the sleep you’re using will not work after all.

1 Like