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

I understood the code. Do you mean that I can put my Sleep function inside this loop?

if (idx >= 38 && millis() - msPublish > 1000)
   {
     Spark.publish("Carpet1", szReceive, PRIVATE);
     msPublish = millis();
            idx = 0;
     frameStart = FALSE;
       if (millis() > 30000)
    Spark.sleep(D0,RISING);
    }

This is not quite what I meant, but if you want to send the Core to sleep after the first publish, but not earlier than 30sec after last wake, then yes, you can do that too.

1 Like

I might understand you wrong, but I though that you mean that:

and this can be done by doing this line:

And for this one:

For this, I can do:

Therefore, I'll try to think more deeper about doing that but not in the same loop as I though in my last post, because I want my code to stay connect to the cloud and publish the data whenever there is a data coming from Serial2 and not go to sleep unless there is no data from Serial2.


@ScruffR
Edit: Does this condition solve the issue?
while ( !Serial2.available() && idx >= 38 && millis() - msPublish > 1000)
{
Spark.sleep(D0,RISING);
}
Or I might just need to put the condition when Serial2 is not available?

Unfortunately, it didnā€™t work for me. :pensive:

And how is it with this code

// test for https://community.particle.io/t/the-core-didnt-connect-to-the-cloud-after-waking-up-from-a-pin-triggered-sleep/13907

//#include "application.h"
#include "Serial2/Serial2.h"


const int wakePin = D0;  // use Serial2 RX pin as wake pin

char szReceive[64] = { '\0' };
int idx = 0;
uint32_t ms;
uint32_t msPublish;
uint32_t msLastSerial;
bool frameStart = false;

void setup()
{
    pinMode(wakePin, INPUT_PULLDOWN);

    Serial.begin(115200);
    
    if(digitalRead(wakePin))  // if pin is held HIGH wait for OTA eternally
      while(true)
      {
        Spark.process();
        Serial.println("Waiting for OTA");
      }

    Serial2.begin(19200);
        
    msLastSerial = millis();
}

void loop()
{
    ms = millis();
    
    Serial2.flush();
    idx = 0;
    while (idx < 38 && millis() - ms < 1000 )
    {
        if(Serial2.available())
        {
            msLastSerial = millis();
            
            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;
    }
    else
        Serial.println(" Timed out");

    if (millis() - msLastSerial > 5000)   // stay awake 5sec after last serial byte
        Spark.sleep(wakePin, RISING);
}

And for this reason

You might consider using SEMI_AUTOMATIC to catch as much of your serial transmission as possible and only after you captured a full packet avtually connect and publish.
For this I'll let you investigate the system modes a bit :wink:

1 Like

Thanks @ScruffR
I flashed this code to my device and this what is happening for now:

1- At the beginning, the device is flashed successfully with your code, and it is connected to the cloud but it stayed online even with no input from Serial2.

2- After that, I press the RST button to see if this will happen each time or not. Fortunately, after the restart, the device waited for 5 second, and when there is no input from Serial2, it went to sleep.

3- Finally, I plug the Serial2 input (Pin D0) and the device woke up successfully from the sleep, connected to the cloud, and started working, but the core didnā€™t go to sleep again when I unplug the input from Serial2 !

Does this mean the code will not let the core go to sleep again until it receives the whole (38 byte) frame? Or the code should wait to check if there is no data from Serial2 , and go to sleep again?


Edit: One more update is that I couldnā€™t see any published data at the Particle Dashboard when I supplied the core from external power, but sometimes I do see published data when I supplied the core from USB.

Thanks in advance.
Ahmed

@ScruffR
Actually I noticed a weird behavior from the spark core. When Iā€™m using Serial1 instead of Serial2 and disable the Sleep part in the code, the core works perfectly and it is publish the data to the dashboard with the power from USB or from external power supply. Does this mean that the D0 pin for Serial2 is unstable? OR it means that the sleep function is not stable?


@ScruffR
Edit: I tried to work with the code to see which portion is causing the instability, and I discovered that when I comment this part the core start working normally without being unstable:

//if(digitalRead(wakePin))  // if pin is held HIGH wait for OTA eternally
      //while(true)
      //{
        //Spark.process();
        //Serial.println("Waiting for OTA");
      //}

Actually, the core started to go to sleep again if I unplug the D0 pin. All of this magic happened after I comment the above part of the code :open_mouth:
Thank you so much.

In this case youā€™d need to use a different pin for the OTA loop to make sure youā€™ll keep being able to flash OTA
e.g.

const int LED = D7;
const int otaPin = D6;  // pin to force code into an OTA loop
...
void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(otaPin, INPUT_PULLDOWN);
  ...
  if(digitalRead(otaPin))  // if pin is held HIGH wait for OTA eternally
  {
    while(true)
    {
      digitalWrite(LED, millis() & 0x0100);  // flip every 256ms
      Spark.process();
    }
  }
  ...
}

Did you understand what the previous version of this part did and why it caused the behaviour you saw?
It would be crucial to build up that kind of skill to read and understand the meaning of the code you use before youā€™ll be able to write your own working code.

1 Like

Thanks for this explanation @ScruffR
What I understood from this part of the code is Iā€™ll need a pin to enable me to flash the core when I have a modification on the code, so Iā€™ll not need to do a factory reset or download a tinker before flashing the modified code. But, how can the code give value to D6 to make it High (to enter to the OTA loop)?
Also for this reason, the core was not going to sleep again if I unplug the D0 pin, is that correct?
But Iā€™m not understanding is why the core could sometimes publish the data when it is on USB power, while it couldnā€™t publish when it was taking the power from the external source? Also, there was another weird behavior that I saw yesterday. When I could see the publish data (supply the core through the USB), the PC that Iā€™m using to supply the power was starting to be uncontrolled and the pages or the softwares that Iā€™m opening is pop up and pop down in a strange way. Therefore, I should unplug the power cable to stop that. Do you have an explanation for that? Iā€™ll try to updload the video for this strange behavior.
Thanks in advance.

Yes, I do have explanations for some of the things you see

The odd PC behaviour must have been while the Core got trapped in the tight OTA loop, permanently printing out the serial message - thatā€™s why I replaced it with an LED blink.
Some more info can be found in this forum - one of the topics
Issues using serial debugging (Mouse moving)

The reason for the Core sometimes going to sleep and other times not at all has to do with the OTA loop and the use od D0 as OTA trigger as well.
If the sender has sent a HIGH bit in the very moment the if pin was read to enter the loop the Core got trapped and never would go to sleep, otherwise the Core would just jump that part and carry on as usual.

To pull D6 high you donā€™t use code but hardware. Attach a button between D6 and 3V3. When you close the switch the Core will get trapped for OTA, if itā€™s open, the pull-down will ensure normal code flow.

For the other questions Iā€™d need more insight in your actual hardware setup (non USB power source, common ground, behaviour of your sender, ā€¦)

2 Likes

Thanks @ScruffR
Thatā€™s very clear now. I have another question about the D6 pin. Can I use a MODE button which is built on the core to control the core or in other word, does the MODE button is connected internally to one of the Pins inside the core?
I appreciated all of your help.

If you did a forum search, you might have found the answer to the mode button question yourself.
But the quick answer is NO, not easily.

1 Like

Thanks for responding to me. I probably search in the forum to find some answers to my question, but I asked you since you have a great experience with the core as I saw from your explanation.
Have a great day.
Thanks again.
Ahmed.

1 Like