NORVI GSM with Thingsboard – Analog Input
Introduction
The NORVI-GSM, powered by the ESP32-WROOM32 microcontroller and equipped with a Quectel EC25 GSM module, connects to the ThingsBoard IoT platform using cellular data via the MQTT protocol. It reads analog inputs and securely transmits this data to ThingsBoard, allowing users to monitor real-time values through customizable dashboards. This setup enables reliable remote access to sensor data, ensuring continuous monitoring and management without requiring physical interaction with the device.
System Architecture
The system architecture of the NORVI-GSM device integrated with ThingsBoard is designed to provide continuous, real-time monitoring of analog inputs using secure cellular communication. The core components and data flow are as follows:
- NORVI-GSM Device
At the core of the system is the NORVI-GSM device, equipped with the ESP32-WROOM32 microcontroller and the Quectel EC25 GSM module. The device continuously reads analog signals from connected sensors or inputs. - Cellular Connectivity
The EC25 GSM module establishes a mobile data connection through the cellular network, providing internet access without the need for Wi-Fi, making it ideal for remote locations. - MQTT Communication Protocol
Using the lightweight MQTT protocol, the NORVI-GSM device publishes the analog data as telemetry messages to the ThingsBoard MQTT broker. MQTT ensures reliable, low-latency, and bandwidth-efficient data transfer over the cellular network. - ThingsBoard IoT Platform
ThingsBoard acts as the cloud-based platform for device management, data ingestion, processing, and visualization. It receives MQTT messages, stores telemetry data, and displays analog voltage readings on customizable dashboards. - User Interface
End users can access the ThingsBoard web interface or mobile app to monitor live sensor data, configure alerts, and review historical voltage measurements from anywhere with internet connectivity.
ThingsBoard Setup
To successfully visualize analog input data from the NORVI-GSM device, the ThingsBoard platform must be properly configured. This section outlines the key steps to set up ThingsBoard for device management and data visualization.
1. Create a ThingsBoard Account and Log In
- Register for a ThingsBoard cloud account at https://thingsboard.io or install a local ThingsBoard server.
- Log in to your ThingsBoard dashboard using your credentials.
2. Add a New Device
- Navigate to Devices and click + Add new device.
- Provide a meaningful name for your NORVI-GSM device (e.g., “NORVI GSM – Analog inputs”).
- Save the device; this generates a unique Access Token used for MQTT authentication.

3. Configure Device Credentials
- Open the newly created device and go to the Manage credentials tab.
- Copy the Access Token; this token will be used in the ESP32 MQTT client to authenticate the device.

4. Set Up Telemetry Data
- ThingsBoard automatically accepts telemetry data sent via MQTT.
- Your device will publish analog voltage readings as telemetry using JSON format (e.g., {“A0”: 3.3}).
- No additional configuration is needed for telemetry reception.

5. Create a Dashboard for Visualization
- Go to the Dashboards section and click + Add new dashboard.
- Design a dashboard by adding widgets such as charts, gauges, or numeric displays.
- Link widgets to the NORVI-GSM device telemetry keys (e.g., A0) to visualize real-time analog input data.



6. Optional: Set Alerts and Rules
- Configure rules to trigger alerts or actions based on input thresholds or device status.
- Use ThingsBoard’s rule engine to automate notifications or device commands.
With ThingsBoard configured, the NORVI-GSM device can securely send analog voltage data over MQTT, enabling real-time monitoring and analysis through intuitive dashboards.
Software Setup
A. Install the ESP32 board in Arduino IDE:
- Go to File > Preferences.
- Go to Tools > Boards > Boards Manager, search for “ESP32”, and install.
- NORVI-with-ThingsBoard (https://github.com/IndustrialArduino/NORVI-with-ThingsBoard/tree/main/NORVI-GSM_EC25_-Anlog_Inputs)
B. Install Required Libraries (Arduino):
Go to Sketch > Include Library > Manage Libraries and install:
- Wire.h
- Adafruit_ADS1X15.h
C. Configure the code:
- Open the code provided in your Arduino IDE.
- Replace the GPRS credentials (apn) with your SIM card provider details.
- Replace device token of your ThingsBoard device.
Code Explanation
1. Library Inclusions and Definitions
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_ADS1X15.h>
#define SerialMon Serial
#define SerialAT Serial1
#define MODEM_TX 32
#define MODEM_RX 33
#define GSM_RESET 21
#define UART_BAUD 115200
#define SDA 16
#define SCL 17
· Wire.h: For I2C communication with the ADS1115 analog-to-digital converter.
· Adafruit_ADS1X15.h: Library to interact with the ADS1115 ADC.
· SerialMon – USB serial for debugging.
· SerialAT – UART connected to Quectel EC25 (AT command interface).
· MODEM_TX / MODEM_RX – ESP32 pins wired to EC25 UART.
· GSM_RESET – hardware reset control for the modem.
· SDA and SCL pins are defined for I2C communication.
2. GPRS and ThingsBoard Credentials
const char apn[] = “dialogbb”;
const char* mqttServer = “mqtt.thingsboard.cloud”;
const int mqttPort = 1883;
const char* accessToken = “qRHmLcB7gHkW1hZTv1dp”;
· apn must match the SIM operator.
· ThingsBoard server details, port (default MQTT port 1883), and the device token authenticate the device on ThingsBoard.
3. Objects and Variables Initialization
Adafruit_ADS1115 ads1;
#define VOLTAGE_DIVIDER_RATIO 0.2065
unsigned long lastSend = 0;
· ads1: ADC object to read analog voltages from ADS1115.
· VOLTAGE_DIVIDER_RATIO: Used to calculate actual input voltage considering hardware voltage divider.
· lastSend stores timestamp to control telemetry send interval.
4. Initilizing the modem and connect to network
void InitModem() {
delay(3000);
gsm_send_serial("AT+CFUN=1", 2000);
gsm_send_serial("AT+CPIN?", 1000);
gsm_send_serial("AT+CSQ", 1000);
gsm_send_serial("AT+CREG?", 1000);
gsm_send_serial("AT+CGATT?", 1000);
gsm_send_serial("AT+COPS?", 1000);
gsm_send_serial("AT+CPSI?", 1000);
gsm_send_serial("AT+QIFGCNT=0", 500);
gsm_send_serial("AT+QICSGP=1,1,\"" + String(apn) + "\",\"\",\"\",1", 1000);
}
void connectToGPRS() {
gsm_send_serial("AT+QIDEACT=1", 1000);
gsm_send_serial("AT+QIACT=1", 2000);
gsm_send_serial("AT+QIACT?", 1000);
}
void connectToMQTT() {
gsm_send_serial("AT+QMTCFG=\"recv/mode\",0,0,1", 1000);
gsm_send_serial("AT+QMTOPEN=0,\"" + String(mqttServer) + "\"," + String(mqttPort), 3000);
delay(3000); // Wait for +QMTOPEN: 0,0
gsm_send_serial("AT+QMTCONN=0,\"esp32client\",\"" + String(accessToken) + "\"", 3000);
}
· InitModem() issues basic AT checks and sets PDP settings (AT+QICSGP) with the APN.
· connectToGPRS() deactivates/activates data session (AT+QIDEACT, AT+QIACT) and checks status.
· connectToMQTT() configures MQTT receive mode, opens connection (AT+QMTOPEN) and then connects (AT+QMTCONN) using the client ID and ThingsBoard access token.
5. MQTT Publish Function
void publishMQTTMessage(String topic, String message) {
int msgLen = message.length();
String cmd = "AT+QMTPUBEX=0,0,0,0,\"" + topic + "\"," + String(msgLen);
gsm_send_serial(cmd, 1000);
gsm_send_serial(message + "\x1A", 3000); // End with Ctrl+Z
}
· Uses Quectel’s AT+QMTPUBEX to publish. The code sends the command with the message length, then the message terminated by Ctrl+Z (0x1A) to indicate end-of-data.
6. Sending Telemetry Data
void sendTelemetry() {
int16_t adc0 = ads.readADC_SingleEnded(0);
int16_t adc1 = ads.readADC_SingleEnded(1);
int16_t adc2 = ads.readADC_SingleEnded(2);
int16_t adc3 = ads.readADC_SingleEnded(3);
float current0 = adc0 * mA_Factor;
float current1 = adc1 * mA_Factor;
float current2 = adc2 * mA_Factor;
float current3 = adc3 * mA_Factor;
String payload = "{\"A0\":";
payload += current0;
payload += ",\"A1\":";
payload += current1;
payload += ",\"A2\":";
payload += current2;
payload += ",\"A3\":";
payload += current3;
payload += "}";
publishMQTTMessage("v1/devices/me/telemetry", payload);
}
· Reads raw ADC values from all four ADS1115 channels.
· Converts raw readings to actual voltage values considering ADC resolution and voltage divider.
· Prints voltages to serial monitor for debugging.
· Constructs a JSON string payload with voltage values (A0 to A3).
· Publishes telemetry data to ThingsBoard MQTT topic “v1/devices/me/telemetry”.
7. Setup Function
void setup() {
SerialMon.begin(115200);
delay(1000);
SerialAT.begin(UART_BAUD, SERIAL_8N1, MODEM_RX, MODEM_TX);
pinMode(GSM_RESET, OUTPUT);
digitalWrite(GSM_RESET, HIGH);
Wire.begin(SDA, SCL);
if (!ads.begin(0x48)) {
Serial.println("ADS1115 (0x48) initialization failed");
while (1);
}
ads.setGain(GAIN_ONE);
InitModem();
connectToGPRS();
connectToMQTT();
}
· Initializes serial communication for debug output, and modem UARTs, sets reset pin.
· Calls sequential functions to initialize the modem, bring up GPRS, then connect MQTT (via AT commands).
· Initializes I2C communication on defined pins.
· Initializes ADS1115 ADC; halts if initialization fails.
8. Main Loop
void loop() {
if (millis() - lastSend > 10000) {
lastSend = millis();
sendTelemetry();
}
}
· Sends telemetry every 10 seconds.
Testing Setup
1.Upload the Firmware
Compile and upload the firmware to the ESP32 and check the serial monitor output and verify that device is connected to the GPRS and ThingsBoard MQTT.
2. Expected Outputs
- ESP32 logs network connection and update status.
- Check ThingsBoard dashboard to confirm it displays correct values of voltages.


Common Issues & Fixes
| Issue | Possible Cause | Solution |
| No data appearing in ThingsBoard | APN is incorrect or not set | Verify apn[] in code matches your SIM provider’s APN |
| GPRS session not active | Check AT response to AT+QIACT? — should show an active PDP context , Check SIM card inserted properly. | |
| MQTT connection failed | Confirm mqttServer, mqttPort, and accessToken are correct | |
| GPRS connects but MQTT fails | Invalid payload length | Ensure message length in AT+QMTPUBEX matches the JSON string size |
| No voltage readings on dashboard | Widget keys don’t match telemetry keys | Ensure ThingsBoard widget keys match JSON keys (A0, A1, etc.) sent by device |
| Data updates delayed or missing | Long send interval; GPRS signal dropouts | Reduce telemetry interval in code; check GPRS signal strength |
| Readings stuck or not changing | Sensor not connected or faulty | Inspect sensor wiring; test sensor output with multimeter |