Sketch to http post to thingspeak and what I have learned so far

Hmm, that probably means I have a bug somewhere. I am looking into it now.

I have abandoned turning off the modem to conserve battery. Once you get this modem registered on the network, you really want to keep it registered. Powering off the modem requires re-registration which can take a while in low signal and has a high battery cost.

Instead of turning off the modem, I have enabled Low Power Mode(UPSV) on the modem. It is best described here:
"If the power saving is enabled (+UPSV: 4), the UART interface is disabled after 6 s of inactivity and the module enters the idle mode automatically whenever possible"

I have added AT+UPSV=4 to the modemSetup() function.

From my crude tests, it reduces current draw by about 8mA between posts.

The modem still has to come out of UPSV to ping the tower, but this does not take too long.

To further reduce current consumption, I have integrated the "Arduino Low Power" library.

The bool mcuLowPower controls if this is used or not.

If used the MCU will go into sleep after each post. This should bring the standby current consumption down to about ~4 mA average if the "Power ON" LED is removed from the board.

After the first sleep, the serial terminal will stop working. The board will continue updating, but the serial USB is lost after sleep.

Also, you may have to double tap the reset to upload a new sketch if MCU is asleep.

I have increased the timeout from 30sec to 120sec here:

  if (stage == 11) {
    sendCommand("AT+USOCR=6", 120000, false);
  }

The AT manual does not list a response time for USOCR command. Usually, this means that the modem responds very fast. In this case though, I have seen it take some time.

Up to seven sockets can be created with this modem. They will not disappear until closed using UCOCL. With this in mind, it is very important to keep track of the sockets that are created and close them when finished.

With a timeout that is too short, the modem could create a socket without the MCU knowing. If this happens multiple(7) times, the modem will not be able to create any more sockets and will respond with a error to USOCR.

I am guessing with a 120sec timeout. Only time will tell if this is sufficient.

The last change I made failed to solve the intermittent issue I am having with the USOCR command. When I am having this issue, the modem will reply with an "Error, operation not allowed" to USOCR command. The only way around this is a soft reset of the modem. The following changes will soft reset the modem if a error is returned:

From this:

  if (stage == 11) {
    sendCommand("AT+USOCR=6", 120000, false);
  }
  if (stage == 12) {
    int positionID = strcspn(response, ":");
    socket = response[positionID + 2] - '0' ;
    int securitySetting = 0;
    if ( thingspeakPort == 443) {
      securitySetting = 1;
    }
    sprintf(formattedCommand, "AT+USOSEC=%i,%i", socket, securitySetting);
    stage++;
  }

To this:

  if (stage == 11) {
    sendCommand("AT+USOCR=6", 120000, true);
  }
  if (stage == 12) {
    if (responseError) {
      modemSetupFlag = false;
      modemSoftResetPending = true;
      stage = 0;
    }
    else {
      int positionID = strcspn(response, ":");
      socket = response[positionID + 2] - '0' ;
      int securitySetting = 0;
      if ( thingspeakPort == 443) {
        securitySetting = 1;
      }
      sprintf(formattedCommand, "AT+USOSEC=%i,%i", socket, securitySetting);
      stage++;
    }
  }

Hello zbelding
I don't know if you already implemented, as ublox wrote to their last firmware:
The +USORD AT command fails to read pending bytes when the socket is in closed state. To avoid the AT command interface hanging, it is recommended to use async socket close, e.g. AT+USOCL=0,1 (the +UUSOCL URC response will take 120 s in thiscase but will not block the AT interface).

So closing a socket with ,1 (in async mode) will not block the AT interface until the socket is closed

It helped me a LOT after i changed it in the MRKNB, because the modem was waiting in sync to close the old socket before creating a new one.
Hope to help you, best regards anyway!

Thanks @intstarep, yeah async close is a good trick. Been using it for a while:

This is also my experience. My strategy is to wait for a minum signal qualitiy of 13 (AT+CSQ) and then open the socket. After a socket error due to weak signal, i respond with a MODEM.send("AT+CPWROFF"); and restart the whole sh... Network conenction with a minumum signal quality of 9. Do you have other values to recommend after you observations?

At one point, I was checking signal quality before trying to open sockets, but in the end I moved away from this. Reported signal given by AT+CSQ and AT+CESQ can vary wildly, and determining signal quality in a LTE network can be complicated. For these reasons I decided to let the modem decide if it has enough signal. This is why some of these socket commands can take up to 2 minutes. The modem is trying and waiting for the signal to improve enough to send data. It does this all on its own. If the signal is terrible(which it is at my location) the modem will respond with error after 2 mins of trying. The trick is to build a sketch that can handle this in a non-blocking way and retry as needed.

That's interesting.
If i get you right, you do +USCR and then halt your sketch until the modem answers (after 2 min)?

How do you control the timing with the modem when the AT command is executed sometimes in millis and the other day in minutes? Do you stay striclty synchronous?

How do you bring the modem to normal operation when the socket dies after a +USWR ( With a "CME Method not allowed" or simply "ERRROR" repsonse)? (I only found +CPWROFF reliable)

When there is no or weak signal, you try again and again? How do you prevent your sketch to trying open more then 6 sockets?

Which version of the SAMD Core lib do you use? (i went back to 1.6.21 for best stability)
You wrote your code is public, is that right?

Sorry to investigate you like that but it seems we are fighting the same war and our army is small.. THX anyway

There has always been a link to it in the second post of this thread. Try it out with a thingspeak account if you want.

I don't halt the sketch, but yes each AT command is sent to the modem with a timeout. The main loop of the sketch is still humming while waiting.

Nothing special is required here, just start the process over again. Sometimes it takes several tries.

My sketch does confirm the modem is attached and registered to the network before trying to open a socket. If it is, yes it will keep trying with socket commands until successful. I keep track of socket #'s and close them when done or after error. The modem will assign the next socket # automatically. But yes, if more than 6 sockets are open at once the modem will reply with error to USOCR. If this happens, I soft reset the modem with AT+CFUN=15.

I would have to check. I transitioned to a mega with a MIKROE R4 modem a while back, but I have been maintaining all of the changes for the MKRNB board.

I see. I tried. I like your stages concept. It's not connecting here. It made from +CEREG: 0,0 to 0,2 back to 0,0 instead to switch to 0,5. You set +UMNOPROF: 2. This does not work here in switzerland. With this setting not even AT+CSQ works anymore.
For other who find this post, to undo the settings after a tryout and bring the modem to "normal" mode, you need to: AT+UPSV=0, AT+UMNOPROF=0, AT+CFUN=15

Questions :

  • AT+USOCLCFG=1 and not 0? (The server will time out and the modem must not care for the socket anymore)
  • Why not USOCO also not synchronous (flag ,1)?

Thesis: serialSARA is a instance of MODEM. MODEM has a reproducable bug in communication (buffer handling), see:

and

Your functions and also the MKRNB are based on MODEM and CORE and thus affected both by this bug. Thanks for your answers.

Thanks. It was the best I could come up with to "multithread" and have the main loop do other work while waiting for a modem response. It does make it cumbersome to program, and I'm sure C++ experts would cringe.

You would need to set network profile and APN to match your network:

const char apn[] = "hologram";//"m2m64.com.attz";
const char simPIN[] = "1234";//If the sim card needs a PIN, this will be used.
const char networkProfile[] = "2";//Profile ID, see AT Manual. 2 = ATT.

I will have to look into this. I can't remember why I used this setting.

For my application, there isn't really anything else I need the modem to do while waiting for AT+USOCO. In my mind, I can either wait for a normal response or wait for a +UUSOCO urc(in the case of asyncronous).

You are so right! I think i have to rewrite my connection function, it's all so unstable.. I'll try to combine my started mqtt lib

together with something inspired by your sketch..
Question: Why do you use the http protocol? Thingspeak has also a mqtt broker.

It came down to versatility. There are a lot of Rest http api out there. With a few simple changes of the http body, I can use pretty much any of them. For example, I use a clickatell api to send reliable sms to my phone.

The other factor is guaranteeing delivery. ThingSpeak MQTT supports only QoS 0. With http I can read response from server to make sure data went through.

On the downside, it will use far more data. I have an unlimited plan for $30/year, so data usage is not a concern.