BSoM Cellular Connect when used with Epaper Display

Hi -

I am stuck and pretty sure I a being stupid and doing something quite obvious wrong. would appreciate some help :slight_smile:

void End_Point_Data() {

  if (Particle.connected() == false) {
            Serial.println("Modem is disconnected");
            digitalWrite(LDO_EN, HIGH);
            Serial.println("LDO Enabled");
            delay(10);
            Cellular.on();
            waitUntil(Cellular.isOn);
            Serial.println("Modem is ON");
            Particle.connect();
            waitUntil(Particle.connected);
            Serial.println("PArticle is Connected to Cloud"); 
  
  Particle.subscribe("hook-response/get_data", myHandler, MY_DEVICES);
  Particle.syncTime();                                                  //*sync to current time to the particle cloud*/
  delay(100);

  String data = String(10);                                             // Get some data
  Particle.publish("get_data", data, PRIVATE);                          // Trigger the integration
  Serial.println("Trigger webhook...");
  }

    delay(250);

    Particle.disconnect(CloudDisconnectOptions().graceful(true).timeout(5000));      // Use only in SEMI_AUTOMATIC mode
    waitUntil(Particle.disconnected);
    Cellular.off();
    waitUntil(Cellular.isOff);
    delay(10);
    digitalWrite(LDO_EN, LOW);
    Serial.print("LDO Disconnected");

    delay(1000);

    EPD();
}

Device starts in Semi_Automatic mode and Threads are enabled. I was expecting to devise to see it is not connect, then connect, do some stuff and then disconnect.

As it stands, it starts up, run the loop which is calling void End_Point_Data() which in turns updates an EPD display. After this, there is a 5min timer, after this expires the function runs again. This second time though, it gets to waitUntil(Cellular.isOn); but then stops there and status leds breaths dark blue.

Regards, Friedl.

Enable trace logging:

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

Remove the existing SerialLogHandler if you have one. This will log what the cellular modem is doing.

1 Like

Hi @rickkas7 -

Thanks, I will do this and see whether I can learn something.

Regards
Friedl

Hi @rickkas7 -

As I mentioned, the first connection works as planned... so below is the logs of the second attempt. I can clearly see where it stops, just don't know why.

07:18:49:862 -> 0000360012 [system.nm] TRACE: Request to power on the interface
07:18:49:863 -> 0000360013 [ncp.client] TRACE: Powering modem on, ncpId: 0x62
07:18:49:863 -> 0000360013 [net.pppncp] TRACE: NCP event 3
07:18:49:864 -> 0000360014 [net.pppncp] TRACE: NCP power state changed: IF_POWER_STATE_POWERING_UP
07:18:49:865 -> 0000360014 [system.nm] INFO: State changed: DISABLED -> IFACE_DOWN
07:19:00:913 -> 0000371058 [net.pppncp] TRACE: NCP event 3
07:19:00:913 -> 0000371059 [net.pppncp] TRACE: NCP power state changed: IF_POWER_STATE_UP
07:19:00:913 -> 0000371059 [system.nm] TRACE: Interface 4 power state changed: 2
07:19:00:914 -> 0000371060 [ncp.client] TRACE: Modem powered on
07:19:01:917 -> 0000372061 [ncp.at] TRACE: > AT
07:19:01:925 -> 0000372065 [ncp.at] TRACE: < OK
07:19:01:925 -> 0000372065 [ncp.client] TRACE: NCP ready to accept AT commands
07:19:01:925 -> 0000372066 [ncp.at] TRACE: > AT+CFUN=1,0
07:19:01:926 -> 0000372070 [ncp.at] TRACE: < OK
07:19:01:926 -> 0000372071 [ncp.at] TRACE: > AT+IFC=2,2
07:19:01:930 -> 0000372074 [ncp.at] TRACE: < OK
07:19:01:930 -> 0000372075 [ncp.at] TRACE: > AT
07:19:01:932 -> 0000372076 [ncp.at] TRACE: < OK
07:19:01:932 -> 0000372077 [ncp.at] TRACE: > AT+IPR=460800
07:19:01:936 -> 0000372080 [ncp.at] TRACE: < OK
07:19:02:938 -> 0000373081 [ncp.at] TRACE: > AT
07:19:02:941 -> 0000373084 [ncp.at] TRACE: < OK
07:19:02:941 -> 0000373085 [ncp.at] TRACE: > AT+CPIN?
07:19:02:944 -> 0000373087 [ncp.at] TRACE: < +CPIN: READY
07:19:02:946 -> 0000373087 [ncp.at] TRACE: < OK
07:19:02:946 -> 0000373089 [ncp.at] TRACE: > AT+CCID
07:19:02:946 -> 0000373090 [ncp.at] TRACE: < +CCID: 89314404000797529428
07:19:02:948 -> 0000373091 [ncp.at] TRACE: < OK
07:19:02:948 -> 0000373092 [ncp.at] TRACE: > AT+QDSIM=0
07:19:02:951 -> 0000373093 [ncp.at] TRACE: < OK
07:19:02:951 -> 0000373094 [ncp.at] TRACE: > AT+CMUX=0,0,7,1509,,,,,
07:19:02:953 -> 0000373096 [ncp.at] TRACE: < OK
07:19:02:953 -> 0000373097 [mux] INFO: Starting GSM07.10 muxer
07:19:02:955 -> 0000373098 [mux] INFO: Opening mux channel 0
07:19:02:957 -> 0000373099 [mux] INFO: GSM07.10 muxer thread started
07:19:03:059 -> 0000373201 [mux] INFO: Opening mux channel 1
07:19:03:110 -> 0000373254 [ncp.at] TRACE: > AT
07:19:03:112 -> 0000373254 [ncp.at] TRACE: < POWERED DOWN
07:19:03:112 -> 0000373256 [ncp.at] TRACE: < OK
07:19:03:112 -> 0000373256 [ncp.client] TRACE: NCP state changed: 1
07:19:03:113 -> 0373256 [net.pppncp] TRACE: NCP event 1
07:19:03:114 -> 0000373258 [ncp.at] TRACE: > AT+QCFG="cmux/urcport",1
07:19:03:119 -> 0000373262 [ncp.at] TRACE: < OK
07:19:03:119 -> 0000373263 [ncp.at] TRACE: > AT+CGEREP=1,0
07:19:03:123 -> 0000373266 [ncp.at] TRACE: < OK

Hope you can shed some light on this. Time between connection attempts currently is set at 180s. I might also be worth nothing that when in this state, I am unable to local flash.


Another thing worth nothing is this only happens if I run the EPD functioning updating the display.

Regards,
Friedl

When reading the code, it struck me to move some lines to setup(). Particularly, Particle.subscribe(). Registering this subscription more than once may be the issue. Try that first. The other changes may not be necessary. Hope this helps.

char data[10] = "some data";//default data

void setup() {
    Particle.subscribe("hook-response/get_data", myHandler, MY_DEVICES);
    Particle.setDisconnectOptions(CloudDisconnectOptions().graceful(true).timeout(5s));
    ...
}

void End_Point_Data() {

    if (Particle.connected() == false) {
        Serial.println("Modem is disconnected");
        digitalWrite(LDO_EN, HIGH);
        Serial.println("LDO Enabled");
        delay(10);
        Cellular.on();
        waitUntil(Cellular.isOn);
        Serial.println("Modem is ON");
        Particle.connect();
        waitUntil(Particle.connected);
        Serial.println("PArticle is Connected to Cloud"); 
    
        //Particle.subscribe("hook-response/get_data", myHandler, MY_DEVICES);// moved to setup()
        
        //Particle.syncTime();//Time auto synched on .connect()=true          //*sync to current time to the particle cloud*/
        //delay(100);

        //String data = String(10);//defined differently above                // Get some data
        Particle.publish("get_data", data, PRIVATE);                          // Trigger the integration
        Serial.println("Trigger webhook...");
    }

    delay(250);
    //below line changed and moved to setup()
    //Particle.disconnect(CloudDisconnectOptions().graceful(true).timeout(5000));      // Use only in SEMI_AUTOMATIC mode
    Particle.disconnect();//modified above line
    waitUntil(Particle.disconnected);
    Cellular.off();
    waitUntil(Cellular.isOff);
    delay(10);
    digitalWrite(LDO_EN, LOW);
    Serial.print("LDO Disconnected");

    delay(1000);

    EPD();// don't know what this does but maybe it does not matter
}
1 Like

Hi @robc -

Thank you for the feedback, this has been driving me insane! I will make the changes as per your suggestion and revert back shortly!

Quick question. I need to wait for the webhook response before disconnecting the modem. Is best practice to simply add a delay is the a better way to do this? The EPD(); function is the Epaper display. It gets updates after each call to the webhook.

Regards
Friedl

Hi @robc

Unfortunately the problem persists. First connection and download from the end point is successful. The second attempt leaves the LED breathing Dark Blue and Workbench is unable to put the device into DFU mode to flash.

In order to flash I need to reset the device.

Regards
Friedl.

This is a very good question. FSM (Finite State Machine) comes to mind. In the scope of your code (application thread), we should try to keep it non-blocking. The

Particle.publish("get_data", data, PRIVATE);

call can be thread blocking. It will take some variable amount of time to actually get the data sent from the cloud before your webhook can respond. I would recommend using the library: PublishQueuePosixRK to execute a similar call on a different worker thread. I must say, however, I have not tried it with your device type.

If you introduce FSM into your code, you could make a certain state exist, like "Webhook_Trigger_Attempted", and start a timer in case of "no response from webhook" before your subroutine(s) exit back to loop(). There, in loop(), when the triggered webhook response arrives, it will be processed by "myHandler" code. There you change the state, let's say to: "Webhook_Triggered_OK". On exit, back to loop(), when "Webhook_Triggered_OK" is detected have your code then start shutting down the cellular modem. If "Webhook_Trigger_Attempted" state exists and timer expired then set state to something descriptive and detect this state in loop() to process accordingly.

Also, in regards to "myHandler" check this out:
https://docs.particle.io/reference/device-os/api/cloud-functions/particle-publish/
NOTE 2: Particle.publish() and the Particle.subscribe() handler(s) share the same buffer. As such, calling Particle.publish() within a Particle.subscribe() handler will overwrite the subscribe buffer, corrupting the data! In these cases, copying the subscribe buffer's content to a separate char buffer prior to calling Particle.publish() is recommended.

Another good reason to use PublishQueuePosixRK library.

3 Likes

Hi @robc -

Oh boy!! Wow!

And there I was thinking this was something trivial :smile: In theory I suppose it is...

  1. Connect and Get Stuff

  2. Wait for stuff and send to screen

  3. do the same again....

I would not have thought in a million years you would need a library for this. I will look into it first thing in the morning.

Another thing maybe worth mentioning - if I comment out the E-Paper function, the problem does not occur. It seems there is some correlation between running the E-Paper and the device freezing up when trying to connect again.

If I run the device in Automatic Mode, the first attempt works fine (same as Semi_Auto mode) and when the second attempt is made, it fails, blinks red then restarts and continues with the 'first' data retrieval and screen update again. For reference, this is the panel I am using - Waveshare 4.2"

Regards,
Friedl

HI @robc -

Here is my handler function. I added the disconnect routine here in an attempt to only disconnect the modem once the data has been received and parsed.

void myHandler(const char *event, const char *data) {

// Split the string from API
    strcpy(testval, (const char *)data);
    int i = 0;
    char *p = strtok (( char *)testval, "|");

    while (p != NULL)
        {
            array[i++] = p;
            p = strtok (NULL, "|");
        }
    
    ApiParser_event1();
    Serial.print("\n"); 
    Serial.print("\n"); 
    ApiParser_event2();
    RealTime();
    memset(testval, '\0', sizeof(testval));
    delay(50);

    new_end_point_STATE = 2;

    Particle.disconnect();                                                 // Use only in SEMI_AUTOMATIC mode
    waitUntil(Particle.disconnected);
    Cellular.off();
    waitUntil(Cellular.isOff);
    delay(10);
    digitalWrite(LDO_EN, LOW);
    Serial.print("LDO Disconnected");
}

Ha Ha! No, I am sorry. You don't need a special library to fix this. Use what you are comfortable with. I am glad you included more code, by the way. I wondered what "myHandler" was doing.

Hi @robc -

Ah ok. I try to stay away form libraries as much as possible, even though they are needed more often than not :slight_smile:

I am stuck here though, no matter what I do, I cannot get this to work. I have reached out to WaveShare support as well to see whether there is something they can suggest, but so far no luck. Unfortunately I on not able to remove power from the screen without also resetting the B524 at this stage and I would prefer not to do another HW revision.

Regards,
Friedl.

Hi Friedl,

I believe @chipmc may have some code to share since his product is doing what you want (connect, send data, disconnect).
Let's ask him and see if he can comment.
Thanks Chip!

1 Like

Hi @gusgonnet , @chipmc -

I have been struggling with this more today, hating theses EPD's even more now :smile:

More notes: The culprit seems to be the code below.

  if (epd.Init() != 0) { 
    Serial.print("Failed to initialize display");
    return;
    }

The moment this has been called, the modem fails to reconnect. I have tried just about everything (which maybe is not a lot given my programming skills) but cannot for the life of me, think of anything else to try.

I have used states to try and manipulate when what runs etc. but the problems comes back to this. Once the EPD has been initialized, you can forget about reconnecting the modem. I added some serial prints see where it stops. See below:

if (Particle.connected() == false) {
      Serial.println("IF Statement executing");
      delay(1000);
      digitalWrite(LDO_EN, HIGH);
      delay(50);
      Cellular.on();
      Serial.print("test1");
      waitUntil(Cellular.isOn);
      Serial.print("test2");
      Particle.connect();
      Serial.print("test3");
      waitUntil(Particle.connected);
      Serial.print("test4");
      }

It prints up to TEST3 and then stops.

More info: If the modem remains on (connected to Particle Cloud or not) it will loop through the code ±3 times, then SOS and restarts. I have tried disabling SPI
SPI.end(); but it had no effect. I also tried putting the screen in deep sleep mode but also had no effect.

easy question from my side:

could it be the display is consuming a lot of power and there is not enough for the device to connect with what the display is leaving (of power)?

Hi @gusgonnet -

Hhmmm... fair question. I doubt it though because if I leave the device in SYSTEM_MODE(AUTOMATIC); it does work a couple of times before giving me the dreaded red SOS codes.

I have tried to monitor voltages while all of the is happening, as far as I can tell (with my bench MM which might be too slow), the supply voltage to the GSM modem is steady 3.73V.

I have two separate regulators powering the unit delivering up to 2A each. The supply to these comes from the LiPO charger which has the capability to activate an
internal mosfet connecting the battery directly to the system in case of higher current demands.

1 Like

@friedl_1977 ,

Not sure if I can help here but thought of a couple questions:

  • Can you specify what SOS code you are getting?
  • What ePaper library are you using?

  • Finally, what pins are you using to connect to the display?

I am actually interested in this issue as I plan to build some ePaper displays in the coming months. It has been a while since I have used them but would love to see you succeed and learn with you.

Chip

1 Like

Hi @chipmc -

This issue has been an extremely frustrating experience, would be great to get any inputs.

WaveShare 4.2"

Pins: 48, 52, 54, 68, 70, 72. (and 3V3 + GND)

Here is where I am at, sorry this might be a bit lengthy:

The sequence of events is as follow:

  • Device starts, Modem connects and gets data from client end point.

  • Modem disconnects after Webhook response has been received and data has been parsed and stored in variables

  • EPD initializes and display is updated with relevant info. Display is put in sleep mode (or not, does not have any effect.)

After a period of time I need to reconnect the modem to send data or check for new data. This is where the problem starts. Modem is turned and a remains in breathing dark blue state. It has no intention of calling Particle.connect(); and then remains in this state. I changed the code to use WaitFor(Particle.connect, 60000); instead of WaitUntill, which allows the code to proceed after the 60s period but the connection to Particle Cloud is never established.

I have tried to remove power from the screen in the hope it would reset something, but to no avail. I tried SPI.end(); but the did not work either. In a last ditch effort to eliminated a mistake on my custom PCB, I connected a Waveshare module to the B5SoM evaluation board. Same results.

I even removed all the wires connecting the two devices (except for the CLK line) and the screen actually passes initializing :face_with_open_eyes_and_hand_over_mouth: If I remove the CLK line, the screen does not initialize. Once you have called the code below, you are stuck!!!

The only way I have found to reconnect the modem, is to restart the uC. The other option is to keep the mode alive... BUT when the ePaper code runs again, it presents the SOS error and restarts. I took a video clip of the error, is there a way to post it here?

My last resort is to keep the modem on to send data. When it is time to receive new data and update the screen, I will need to force a reset. Less than ideal.... :worried:

@friedl_1977 ,

Thank you for your response it is all very helpful information. I am looking for one more data point:

When the Boron starts flasing, SOS, it follows the Morse code with some flashes which provide more insight into what is the issue. If you watch the sequence carefully, you can discern the message. How many flashes do you see between SOSes?

Thanks,

Chip

1 Like

Hi Chip -

I my word... I must have watched this a million times, each time more confused that the previous time. Please see if you can access the link below, it is a video from the error code:

Just not this error ONLY occurs if I keep the modem connected and then try to run the EPD code for a second time within the same connection period.

Regards
Friedl