Dragos Iosub
Published

Taste the NB-IoT (BC95G) Flavor - Episode 2

NB-IoT data transmission how to use BC95G modem based shields - NB-IoT upload sensor data to cloud using UDP and JSON.

IntermediateProtip15 minutes346
Taste the NB-IoT (BC95G) Flavor - Episode 2

Things used in this project

Hardware components

xyz-mIoT by itbrainpower.net [ARM0 + BC95G (NB IoT modem), no embedded sensors]
xyz-mIoT by itbrainpower.net [ARM0 + BC95G (NB IoT modem), no embedded sensors]
×1
GSM antenna with uFL connector
×1
capacitor 1000-2200uF/6.3V low ESR
×1
nano SIM card from your NB IoT provider
×1

Software apps and online services

AllThingsTalk Maker IoT Platform
Arduino IDE
Arduino IDE
version >=1.8.5

Story

Read more

Schematics

xyz-mIoT shield pinout, port map and more

xyz-mIoT board - ARM0 + sensors + modem compact shield - pinout, port map and more info

xyz-mIoT shield bottom - sensors and interfaces placement

details for shield interfacing

Code

xyz_mIoT_NBIoT_Class_example_AllThingsTalk.ino

Arduino
Arduino code for NB IoT data upload to AllThingsTalk CLOUD. Written for itbrainpower.net shields equipped with Quectel BC95G modem.
/*
xyz_mIoT_NBIoT_Class_example_AllThingsTalk.ino v 0.1/20181016 - upload data [json packed] to AllThingsTalk cloud using UDP service
COPYRIGHT (c) 2015-2018 Dragos Iosub / R&D Software Solutions srl

You are legaly entitled to use this SOFTWARE ONLY IN CONJUNCTION WITH xyz-mIoT by itbrainpower.net or u-GSM by itbrainpower.net DEVICES USAGE. Modifications, 
derivates and redistribution of this software must include unmodified this COPYRIGHT NOTICE. You can redistribute this SOFTWARE and/or modify it under the 
terms of this COPYRIGHT NOTICE. Any other usage may be permited only after written notice of Dragos Iosub / R&D Software Solutions srl.

This SOFTWARE is distributed is provide "AS IS" in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Dragos Iosub, Bucharest 2018.
https://itbrainpower.net
*/
/*IMPORTANT NOTICE 0: 
	- goto https://maker.allthingstalk.com 
	- Create one acount, then create one new device [select "your own device"], name it, then add two assets [both sensors, type number] called Vbat and Vin. 
	- From DEVICES\how_you_named_your_device\SETTINGS\Authentication copy the valus for: "Device ID" and "Device Tokens". 
	- Use those values in code bellow, to update DEVICE_ID and DEVICE_TOKEN.
	
	- Use the same hardware setup as described in: https://itbrainpower.net/a-gsm/BC95G-NBIoT-data-transmission-how-to
	- if xyz-mIoT shield is used, real voltage sampled data are uploaded to cloud.
	- if u-GSM shield is used, dummy data will be uploaded to cloud [.. see in code bellow Vbat and Vraw data sampling in readVoltages()]
*/
/*IMPORTANT NOTICE 1: check itbpGSMdefinition.h for line 60&61 and set "__itbpModem__    xyzmIoT" or "__itbpModem__    uGSM"*/
/*IMPORTANT NOTICE 2: check itbpGSMdefinition.h for line 64&65 and set "__Qmodule__    BC95G" or "__Qmodule__    BG96"*/
/*IMPORTANT NOTICE 3: in itbpGPRSIPdefinition.h update your NB IoT "APN", "LTE_BAND" [Eg. Vodafone RO use LTE BAND 20] and "numeric network id code" [Eg. Vodafone RO  ==> 22601]*/
/*IMPORTANT NOTICE 4: in itbpGPRSIPdefinition.h  set "SERVER_ADDRESS" with value "40.68.172.187" and "SERVER_PORT" with value "8891"- AllThingsTalk UDP server address and port*/
/*IMPORTANT NOTICE 5: in itbpGSMdefinition.h "MAX_BUFFER_SIZE", "itbpGSMClassDebug" and "atDebug" may help you....*/

#include <String.h>

String message = "";
#define DEVICE_ID       "ltOgAaRCSeGuOfVBxtUwO"                          //AllThingsTalk Device Id, replace it with your id
#define DEVICE_TOKEN    "maker:4NLwOkA7zeQSm0lqFv10pUgDIvDxWmVyzKsPy"    //AllThingsTalk Device Token, replace it with your tocken id


int samplingPeriod = 120;							                    //interval in seconds between transmissions... keep it > 60 sec [600 second to test some NB IoT signaling]

float Vbat = 0, Vraw = 0;

char IMEI [16];		

#include <itbpNBIoTClass_v0_2.h>

#define DEBUG(x)    {__itbpDebugPort__.print(millis());__itbpDebugPort__.print(" - ");__itbpDebugPort__.println(x);}
#define DEBUGP(x,y) {__itbpDebugPort__.print(millis());__itbpDebugPort__.print(" - ");__itbpDebugPort__.print(x);__itbpDebugPort__.println(y);}

#if defined (__AVR_ATmega328P__)
  int freeRam () {
    extern int __heap_start, *__brkval; 
    int v; 
    return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
  }
#endif

// initialize the library instance
aGsmClient client;



unsigned long startTime = 0;

bool ledState = 0;


void setup(){
#if (__itbpModem__ == xyzmIoT)
	delay(10000);
#endif

  __itbpDebugPort__.begin(115200);			//start debug port connection
  //configure led
	pinMode(LED_BUILTIN, OUTPUT);			            //embedded LED status indicator  
	digitalWrite(LED_BUILTIN, LOW);			
  ledState = 0;

#if defined (__AVR_ATmega328P__)
  DEBUGP(F("Free RAM: "), freeRam());
#endif

__itbpDebugPort__.println(F("AllThingTalk cloud NBIoT UDP data upload ...let's rock"));
__itbpDebugPort__.flush();
	
	client.begin();

	client.enableClockUpdate(1); //update available at next modem boot

	client.getIMEI();	//IMEI value in client.resp
	memset(IMEI,0x00, sizeof(IMEI));
	strcpy(IMEI,client.resp);
	DEBUGP(F("IMEI: "), IMEI);

	client.attachGPRS();

  //let's verify the module date&time function
  delay(1000);
  client.getRTC();
  DEBUGP(F("time and date: "), client.resp);

	__itbpDebugPort__.println("connecting...");
	
	//client.readServerDatagramReply();

  startTime = millis() + (unsigned long)samplingPeriod*1000;//force send on the spot
}

void readVoltages(){
  //read voltage
  Vbat=analogRead(VbatPin)*0.0065344650650891/*0.0063636363636364*/;      //8bit read, value in volts
  Vraw=analogRead(VrawPin)*0.0102016129032258;      //8bit read, value in volts  
    __itbpDebugPort__.print(F("Vbat: "));
    __itbpDebugPort__.println(Vbat);
    __itbpDebugPort__.print(F("Vraw: "));
    __itbpDebugPort__.println(Vraw);
}
void buildJsonPayload(){ //get sensor data and pack data in JSON
    
    readVoltages();
    
    message="";
    message += String(DEVICE_ID);
    message += "\n";
    message += String(DEVICE_TOKEN);
    message += "\n{";
    message += "\"Vin\":{\"value\":"+ String(Vraw)+"}"; //first sensor
    message += ",";//separator
    message += "\"Vbat\":{\"value\":"+ String(Vbat)+"}"; //second sensor
    message += "}";
    //__itbpDebugPort__.print(F("datagram formated: "));
    //__itbpDebugPort__.println(message);
}



void loop(){
  int res=0;
  if (millis() - startTime < (unsigned long)samplingPeriod*1000){//waiting period  
    ledState = ! ledState;
    if(ledState != 0)
      digitalWrite(LED_BUILTIN, HIGH);  
    else
      digitalWrite(LED_BUILTIN, LOW); 
    delay(500);
    
  }else{//start transmission
    startTime = millis();
    digitalWrite(LED_BUILTIN, HIGH);      //show sampling + uploadto cloud

    if (client.connected() || client.connect()){
      __itbpDebugPort__.println(F("send datagram"));
      //res = client.sendDatagram(DATAGRAMTOSEND);
      buildJsonPayload(); 
      res = client.sendDatagram(message); 
      
      if(res == 1){
        __itbpDebugPort__.println(F("data was sent"));

        //not really need to wait for server reply. At this time the AllThinksTalk UDP cloud interface does not have datagram reply implemented.
        /*
        //here waiting for server reply and for network signaling        
        __itbpDebugPort__.println(F("wait 4 server reply..."));
        unsigned long startlisten = millis();
        res = client.listenForNetworkSignaling(samplingPeriod, 1);//wait until receive server reply (samplingPeriod); //wait for server reply; res
        if(res>0){ 
            __itbpDebugPort__.println("");
            __itbpDebugPort__.print(F("reply received>>"));
            __itbpDebugPort__.print(client.resp);    //server replied data in resp
            __itbpDebugPort__.println(F("<<"));
            //here wait for network signaling
            res = client.listenForNetworkSignaling(samplingPeriod -(int)((millis()-startlisten)/1000), 4);//wait until enter PSM mode        
            //res = client.listenForNetworkSignaling(samplingPeriod -(int)((millis()-startlisten)/1000), 2);//wait until enter IDLE mode        
        }
        */
        
        /*
        //other variant to listen for server reply
        res = client.listenForDatagramServerReply(samplingPeriod); //wait for server reply; res
        if(res>0){ 
            __itbpDebugPort__.println("");
            __itbpDebugPort__.print(F("reply received>>"));
            __itbpDebugPort__.print(client.resp);    //server replied data in resp
            __itbpDebugPort__.println(F("<<"));
            //here wait for network signaling
            //res = client.listenForNetworkSignaling(samplingPeriod - res, 4);//wait until ender PSM mode
        }
        */
      }else{//send datagram command report ERROR
        __itbpDebugPort__.println(F("connectivity error...")); 
      }
    }//end connect()
  }//end tranmission 
  
}

Credits

Dragos Iosub

Dragos Iosub

23 projects • 4 followers
Electronics & software, electronics & software, ...

Comments