[SOLVED] Adafruit 32u4 FONA -> Ubidots

Hi all,

I’ve just bought the Adafruit 32u4 FONA in order to experiment with the GSM/Cellular network. Previously I have used ESP32 and Wifi with good experience using MQTT.

I have spend some time trying to understand why I haven’t been able to upload data with my new FONA device. I have tried different libraries without any succes. When I run the FONAtest examplae I can see that I do have a network with a prober signal strength, so my basic FONA settings works and I do have some network.

I have used this code since it’s the “official” Ubidots code. http://help.ubidots.com/connect-your-devices/connect-an-adafruit-feather-32u4-fona-to-ubidots-over-tcpudp

But it gives me the error code below. It fails during the function “sendToUbidots” and after sending the “AT+CIPSTART” command to FONA.

Do you have any suggestions? I have also tried the Ubidots FONA library but without succes.

Attempting to open comm with ATs
Response of FONA:

Error
Response of FONA:
AT
OK

Call Ready

SMS Ready

Response of FONA:
ATE0
OK

Response of FONA:
OK

AT
Response of FONA:
OK

+CREG:
Response of FONA:
+CREG: 0,1

OK

AT+CSQ
Response of FONA:
+CSQ: 27,0

OK

AT+CGATT?
Response of FONA:
+CGATT: 0

OK

AT+SAPBR=3,1,“CONTYPE”,“GPRS”
Response of FONA:
OK

AT+SAPBR=3,1,“APN”,"
apn
"
Response of FONA:
OK

AT+SAPBR=3,1,“USER”,"
user
"
Response of FONA:
OK

AT+SAPBR=3,1,“PWD”,"
pwd
"
Response of FONA:
OK

AT+SAPBR=1,1
Response of FONA:
OK

AT+SAPBR=2,1
Response of FONA:
+SAPBR: 1,1,“10.222.30.189”

OK

SendToUbidots function start:
AT+CIPMUX=0
Line 1
Response of FONA:
OK

Line 2
AT+CIPSTART=“TCP”,"
SERVER
“,”
PORT
"
Line 3
Response of FONA:
OK

STATE: PDP DEACT

CONNECT FAIL

Error with AT+CIPSTART

And here is my code (I have added some extra Serial.println)

 /********************************
 * Libraries included
 *******************************/
#include <SoftwareSerial.h>
#include <stdlib.h>
#include "Arduino.h"
 
/********************************
 * Constants and objects
 *******************************/
 
#define DEFAULT_BUFFER_SIZE      64

#define FONA_RX  9
#define FONA_TX  8
#define FONA_RST 4

#define SERVER "translate.ubidots.com"
#define PORT "9012"

#define APN "telenor"  // The APN of your operator
#define USER ""  // if your apn doesnt have username just leave it ""
#define PASS ""  // if your apn doesnt have password just leave it ""
#define TOKEN "XXXXXXXXXXXXXXXXXXXXX"  // Replace it with your Ubidots token
#define METHOD "POST"
#define USER_AGENT  "adafruit"
#define VERSION  "1.0"
#define DEVICE_LABEL  "feather-fona"
#define VARIABLE_LABEL  "temperature"

bool _debug = true; 
char buffer[DEFAULT_BUFFER_SIZE];
 
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);

/********************************
 * Main Functions
 *******************************/
void setup() {
Serial.begin(115200);
pinMode(A0, INPUT);
delay(2000);
while(!setApn(APN, USER, PASS));
}

void loop() {
char* request = (char *) malloc(sizeof(char) * 300);
char str_val[15];

float sensor_value = analogRead(A0);

dtostrf(sensor_value, 4, 2, str_val);
sprintf(request, "%s/%s|%s|%s|%s=>%s:%s|end", USER_AGENT, VERSION, METHOD, TOKEN, DEVICE_LABEL, VARIABLE_LABEL, str_val);
//sprintf(request, "%s|%s|%s","adafruit/1.0|POST", TOKEN, "fona=>test:17.00|end");
sendToUbidots(request);
free(request);
}

/********************************
 * Auxiliar Functions
 *******************************/
bool sendMessageAndwaitForOK(char* message, uint16_t timeout = 4000) {
fonaSS.println(message);
if (strstr(readData(timeout), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error"));
    }
        return false;
    }
return true;
}

bool setApn(char* apn, char* user, char* pwd) {
checkFona();

Serial.println("AT");
fonaSS.println(F("AT"));
if (strstr(readData(2000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT"));
    }
    return false;
}

Serial.println("+CREG:");
fonaSS.println(F("AT+CREG?"));
if (strstr(readData(2000), "+CREG:") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT"));
    }
    return false;
}

Serial.println("AT+CSQ");
fonaSS.println(F("AT+CSQ"));
if (strstr(readData(2000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+CSQ"));
    }
    return false;
}

Serial.println("AT+CGATT?");
fonaSS.println(F("AT+CGATT?"));
if (strstr(readData(10000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+CGATT"));
    }
    return false;
}

Serial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
fonaSS.println(F("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\""));
if (strstr(readData(10000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+SAPBR CONTYPE"));
    }
    return false;
}

Serial.println("AT+SAPBR=3,1,\"APN\",\"");
fonaSS.print(F("AT+SAPBR=3,1,\"APN\",\""));

Serial.println("apn");
fonaSS.print(apn);

Serial.println("\"");
fonaSS.println(F("\""));
if (strstr(readData(3000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+SAPBR APN"));
    }
    return false;
}

Serial.println("AT+SAPBR=3,1,\"USER\",\"");
fonaSS.print(F("AT+SAPBR=3,1,\"USER\",\""));

Serial.println("user");
fonaSS.print(user);

Serial.println("\"");
fonaSS.println(F("\""));
if (strstr(readData(10000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+SAPBR USER"));
    }
    return false;
}

Serial.println("AT+SAPBR=3,1,\"PWD\",\"");
fonaSS.print(F("AT+SAPBR=3,1,\"PWD\",\""));

Serial.println("pwd");
fonaSS.print(pwd);

Serial.println("\"");
fonaSS.println("\"");
if (strstr(readData(3000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+SAPBR PASSWORD"));
    }
    return false;
}

Serial.println("AT+SAPBR=1,1");
fonaSS.println(F("AT+SAPBR=1,1"));
if (strstr(readData(4000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+SAPBR=1,1 Connection ip"));
    }
    return false;
}

Serial.println("AT+SAPBR=2,1");
fonaSS.println(F("AT+SAPBR=2,1"));
if (strstr(readData(4000), "+SAPBR:") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+SAPBR=2,1 no IP to show"));
    }
    return false;
}
return true;
}

bool module_begin() {
pinMode(FONA_RST, OUTPUT);
digitalWrite(FONA_RST, HIGH);
delay(500);
digitalWrite(FONA_RST, LOW);
delay(500);
digitalWrite(FONA_RST, HIGH);
delay(500);
Serial.println(F("Attempting to open comm with ATs"));
int16_t timeout = 10000;
while (timeout > 0) {
    if (sendMessageAndwaitForOK("AT"))
        break;
    delay(500);
    timeout -= 500;
}
if (timeout <= 0) {
    Serial.println(F("Timeout: No response to AT... last ditch attempt."));
    sendMessageAndwaitForOK("AT");
    delay(100);
    sendMessageAndwaitForOK("AT");
    delay(100);
    sendMessageAndwaitForOK("AT");
    delay(100);
    return false;
}
sendMessageAndwaitForOK("ATE0");
delay(100);
return true;
}

bool sendToUbidots(char* request) {
Serial.println("SendToUbidots function start:");

Serial.println("AT+CIPMUX=0");
fonaSS.println(F("AT+CIPMUX=0"));

Serial.println("Line 1");

if (strstr(readData(4000), "OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+CIPMUX"));
    }
    return false;
}


Serial.println("Line 2");

Serial.println("AT+CIPSTART=\"TCP\",\"");
fonaSS.print(F("AT+CIPSTART=\"TCP\",\""));

Serial.println("SERVER");
fonaSS.print(SERVER);

Serial.println("\",\"");
fonaSS.print(F("\",\""));

Serial.println("PORT");
fonaSS.print(PORT);

Serial.println("\"");
fonaSS.println(F("\""));

Serial.println("Line 3");

if (strstr(readData(4000), "CONNECT OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+CIPSTART"));
    }
    return false;
}


Serial.println("Line 4");

Serial.println("AT+CIPSEND=");
fonaSS.print(F("AT+CIPSEND="));


Serial.println("Line 5");


fonaSS.println(dataLen(request));
if (strstr(readData(4000), ">") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+CIPSEND"));
    }
    return false;
}
fonaSS.write(request);
if (strstr(readData(4000), "SEND OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error sending variables"));
    }
    return false;
}
fonaSS.println(F("AT+CIPCLOSE"));
if (strstr(readData(4000), "CLOSE OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+CIPCLOSE"));
    }
    return false;
}
fonaSS.println(F("AT+CIPSHUT"));
if (strstr(readData(4000), "SHUT OK") == NULL) {
    if (_debug) {
        Serial.println(F("Error with AT+CIPSHUT"));
    }
    return false;
}
return true;
}

int dataLen(char* variable) {
  uint8_t dataLen = 0;
  for (int i = 0; i <= 250; i++) {
if (variable[i] != '\0') {
  dataLen++;
} else {
  break;
}
  }
  return dataLen;
}

bool checkFona() {
fonaSS.begin(4800);
delay(2000);
module_begin();
if (!sendMessageAndwaitForOK("ATE0", 6000)) {
    Serial.print("Couldn't find FONA");
    while (1) {
        Serial.println("ERROR");
    }
    return false;
}
return true;
}

char* readData(uint16_t timeout) {
uint16_t replyidx = 0;
char replybuffer[254];
int secconds = 0;
while (!fonaSS.available() && secconds < timeout) {
    secconds++;
}
while (timeout--) {
    if (replyidx >= 254) {
        break;
    }
    while (fonaSS.available()) {
        char c =  fonaSS.read();
        if (c == '\r') continue;
        if (c == 0xA) {
            if (replyidx == 0)   // the first 0x0A is ignored
                continue;
        }
        replybuffer[replyidx] = c;
        replyidx++;
    }
    while (!fonaSS.available() && timeout > 0) {
        timeout--;
        delay(1);
    }

    if (timeout == 0) {
        if (fonaSS.available()) {
            timeout = 1000;
        } else {
            break;
        }
    }
}
replybuffer[replyidx] = '\0';  // null term
if (_debug) {
    Serial.println("Response of FONA:");
    Serial.println(replybuffer);
}
return replybuffer;
}

Greetings, accordingly to the troubleshooting & FAQs from this guide, If the message received in the serial monitor is “PDP DEACT - error” Your service provider may be blocking some ports. You should call your service provider or try with another SIM card with an active data plan.

Typically, errors with AT+CIPSTART command are related with GPRS service providers issues with the FONA hardware and unfortunately are out of our scope. Have you tried to make a simple POST to another website like ww.example.com?

Thanks for the advice. I did try a different SIM card with the same result. But now I found another solution with MQTT instead (port 1883 was open). It was a little tricky to use the PubSubClient as often used for Ethernet/Wifi connections. But thanks to the TinyGSM library I found a very nice solution using a bit of my old code. The TinyGSM support many “modems” including the 8xx series used in many of the boards out there. There is also an diagnostic function that can be used to verify a prober GPRS connection etc.

Anyways this is my code that works with the Adafruit Feather 32u4 Fona and Ubidots.
The code uploads 3 variables from the GSM module: Battery voltage, battery level (%) and signal quality.

// Select your modem:
#define TINY_GSM_MODEM_SIM800

#include <TinyGsmClient.h>
#include <PubSubClient.h>

// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial

// or Software Serial on Uno, Nano
#include <SoftwareSerial.h>
SoftwareSerial SerialAT(8, 9); // TX, RX

// Your GPRS credentials
// Leave empty, if missing user or pass
const char apn[]  = "internet";
const char user[] = "";
const char pass[] = "";

// MQTT details
const char* broker = "things.ubidots.com";
const char* token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; 
const char * VARIABLE_LABEL_1 = "battlevel"; // Assing the variable label
const char * VARIABLE_LABEL_2 = "battvoltage"; // Assing the variable label
const char * VARIABLE_LABEL_3 = "signalq"; // Assing the variable label
const char * DEVICE_LABEL = "skovfonatest"; // Assig the device label

/* Space to store the request */
char payload[300];
char topic[150];

/* Space to store values to send */
char str_battlevel[10];
char str_battvoltage[10];
char str_signalq[10];

TinyGsm modem(SerialAT);
TinyGsmClient client(modem);
PubSubClient mqtt(client);

long lastReconnectAttempt = 0;

void setup() {
  // Set console baud rate
  SerialMon.begin(115200);
  delay(10);

  // Set GSM module baud rate
  SerialAT.begin(4800);
  delay(3000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();

  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem: ");
  SerialMon.println(modemInfo);

  // Unlock your SIM card with a PIN
  //modem.simUnlock("1234");

  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    while (true);
  }
  SerialMon.println(" OK");

  SerialMon.print("Connecting to ");
  SerialMon.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    SerialMon.println(" fail");
    while (true);
  }
  SerialMon.println(" OK");

  // MQTT Broker setup
  mqtt.setServer(broker, 1883);
  mqtt.setCallback(mqttCallback);
}

boolean mqttConnect() {
  SerialMon.print("Connecting to ");
  SerialMon.print(broker);

  // Or, if you want to authenticate MQTT:
  boolean status = mqtt.connect("DTIDOSK", token, token);

  if (status == false) {
    SerialMon.println(" fail");
    return false;
  }
  SerialMon.println(" OK");
  return mqtt.connected();
}

void loop() {
  if (!mqtt.connected()) {
    SerialMon.println("=== MQTT NOT CONNECTED ===");
    // Reconnect every 10 seconds
    unsigned long t = millis();
    if (t - lastReconnectAttempt > 10000L) {
      lastReconnectAttempt = t;
      if (mqttConnect()) {
        lastReconnectAttempt = 0;
      }
    }
    return;
  }

  /* Reading temperature and humidity */
  float battlevel = modem.getBattPercent();
  float battvoltage = modem.getBattVoltage() / 1000.0F;
  float signalq = modem.getSignalQuality();

  /* 4 is mininum width, 2 is precision; float value is copied onto str_sensor*/
  dtostrf(battlevel, 3, 0, str_battlevel);
  dtostrf(battvoltage, 4, 2, str_battvoltage);
  dtostrf(signalq, 3, 0, str_signalq);
  
  /* Building the Ubidots request */
  sprintf(topic, "%s%s", "/v1.6/devices/", DEVICE_LABEL);
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\": %s,", VARIABLE_LABEL_1, str_battlevel); // Adds the variable label
  sprintf(payload, "%s\"%s\": %s,", payload, VARIABLE_LABEL_2, str_battvoltage); // Adds the variable label
  sprintf(payload, "%s\"%s\": %s}", payload, VARIABLE_LABEL_3, str_signalq); // Adds the variable label
  
  Serial.println("Publishing data to Ubidots Cloud");
  mqtt.publish(topic, payload);
  mqtt.loop();
  
  delay(1000);
}

void mqttCallback(char* topic, byte* payload, unsigned int len) {
  SerialMon.print("Message arrived [");
  SerialMon.print(topic);
  SerialMon.print("]: ");
  SerialMon.write(payload, len);
  SerialMon.println();
}

Thank you very much for sharing your problem fix with us! If you are an educational user, let me know your username and I will charge your account with some free credits as a courtesy.

All the best

No problem :slight_smile:
Yes, until now I’m an educational user - but this could definitely change in the future. I have a lot of ideas…
My username is “soerenskov88” just as my community user.

We have charged your account with free credits.

Thanks for your contribution.

All the best