Demo code SODAQ SARA R4 to Ubidots

Below the demo code for:

  • Sending battery data using HTTP POST
  • Shaking the device triggers an HTTP GET
  • Onboard LED turns on/off based on the button state in the Ubidots platform

To make this work:

  • Create a Ubidots account
  • Add the device named iotdevice
  • Add a variable, named button
  • Add your Ubidots token to the sketch below
  • Flash the sketch to the SODAQ SARA R412M

Example of how it may look:

Arduino sketch

#include <Sodaq_R4X.h>
#include <Arduino.h>
#include <Sodaq_LSM303AGR.h>

Sodaq_LSM303AGR AccMeter;

#define CONSOLE_STREAM   SerialUSB
#define MODEM_STREAM     Serial1
#define CONSOLE_BAUDRATE 115200
#define MODEM_BAUDRATE   115200

#define CURRENT_APN      "data.mono"
#define CURRENT_OPERATOR SODAQ_R4X_AUTOMATIC_OPERATOR
#define CURRENT_URAT     SODAQ_R4X_LTEM_URAT
#define CURRENT_MNO_PROFILE MNOProfile::STANDARD_EUROPE

#define HTTP_HOST        "industrial.api.ubidots.com"
#define HTTP_PORT        80
#define UbidotsToken     "BBFF-xxx"
#define HTTP_QUERY       "/api/v1.6/devices/iotdevice/button/lv/?token="UbidotsToken

#define ADC_AREF 3.3f
#define BATVOLT_R1 4.7f
#define BATVOLT_R2 10.0f
#define BATVOLT_PIN BAT_VOLT

// The interrupt pin for the Accelerometer is attached to D5
#define ACC_INT_PIN ACCEL_INT1

// Threshold for interrupt trigger
double threshold = -0.8;
int now = millis();
int interrupt = 0;

static Sodaq_R4X r4x;
static Sodaq_SARA_R4XX_OnOff saraR4xxOnOff;
static bool isReady;

void setup()
{
    CONSOLE_STREAM.begin(CONSOLE_BAUDRATE);
    
    while ((!CONSOLE_STREAM) && (millis() < 10000)){
        // Wait max 10 sec for the CONSOLE_STREAM to open
    }
     
    pinMode(LED_RED, OUTPUT);
    
    // Start the I2C bus
    Wire.begin();

    AccMeter.rebootAccelerometer();    
    delay(1000);
    
    // Enable the Accelerometer
    AccMeter.enableAccelerometer();

    // Attach interrupt event fot the Accelerometer
    pinMode(ACC_INT_PIN, INPUT);
    attachInterrupt(ACC_INT_PIN, interrupt_event, RISING);

    // Enable interrupts on the SAMD
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_EIC) |
        GCLK_CLKCTRL_GEN_GCLK1 |
        GCLK_CLKCTRL_CLKEN;

    // If Z goes below threshold the interrupt is triggered
    AccMeter.enableInterrupt1(AccMeter.ZLow, threshold, 0, AccMeter.PositionRecognition);


    r4x.setDiag(CONSOLE_STREAM);
    r4x.init(&saraR4xxOnOff, MODEM_STREAM, MODEM_BAUDRATE);
    delay(1000);
    isReady = r4x.connect(CURRENT_APN, CURRENT_URAT, CURRENT_MNO_PROFILE, CURRENT_OPERATOR, BAND_MASK_UNCHANGED);
    CONSOLE_STREAM.println(isReady ? "Network connected" : "Network connection failed");

    CONSOLE_STREAM.println("Setup done");
}

void loop()
{
    if (CONSOLE_STREAM.available()) {
        int i = CONSOLE_STREAM.read();
        CONSOLE_STREAM.write(i);
        MODEM_STREAM.write(i);
    }

    if (MODEM_STREAM.available()) {
        CONSOLE_STREAM.write(MODEM_STREAM.read());
    }
    
    // Send sensor readings every 20 second
    if ((now + 20000) < millis())
    {
        now = millis();
        postHTTP();
    }

    if (interrupt == 1) {
      CONSOLE_STREAM.println("Interrupt HIGH!");
      getData();
      interrupt = 0;
    }
}

void postHTTP()
{
  CONSOLE_STREAM.println("start postHTTP");

  // getBatteryVoltage
  uint16_t voltage = (uint16_t)((ADC_AREF / 1.023) * (BATVOLT_R1 + BATVOLT_R2) / BATVOLT_R2 * (float)analogRead(BATVOLT_PIN));
  SerialUSB.println(voltage);

  r4x.execCommand("AT+UHTTP=0,1,\""HTTP_HOST"\"");
  r4x.execCommand("AT+UHTTP=0,9,\"0:X-Auth-Token:"UbidotsToken"\"");
  r4x.execCommand("AT+UHTTP=0,9,\"1:Content-Type:application/json\"");

  char message[1024];
  sprintf(message, "AT+UHTTPC=0,5,\"/api/v1.6/devices/iotdevice/voltage/values\",\"data.txt\",\"%d%s", voltage, "\",4");
  r4x.execCommand(message);

  delay(5000);
}

void getData()
{
    CONSOLE_STREAM.println("start getHTTP");

    char buffer[2048];
    uint32_t i = r4x.httpGet(HTTP_HOST, HTTP_PORT, HTTP_QUERY, buffer, sizeof(buffer));

    CONSOLE_STREAM.print("Read bytes: ");
    CONSOLE_STREAM.println(i);

    if (i > 0) {
        buffer[i] = 0;
        CONSOLE_STREAM.print("Button state: ");
        CONSOLE_STREAM.println(buffer);

        float button = atof(buffer); // change char to float
        
        if (button == 1.0){
          digitalWrite(LED_RED, LOW);
          CONSOLE_STREAM.println("LED ON");
        }
        else {
          digitalWrite(LED_RED, HIGH);
          CONSOLE_STREAM.println("LED OFF");
        }
    }
}

void interrupt_event()
{
    // Do not print in an interrupt event when sleep is enabled.
    CONSOLE_STREAM.println("Alert");

    interrupt = 1;
}

In addition, I’ve also published a generic UDP and HTTP tutorial on sending data from an IoT modem to Ubidots.

See: Ubidots - Docs