TTGO ESP32 + GSM 800l AT Commands - arduino

Good day all
I'm working on a project that takes sensor data and sends it to an online database using HTTP requests.Im ussing the TTGO esp32 sim 800 board, Everything works fine and all the data is stored in my online database the problem is that I cant get the AT commands to work, I need the Signal strength, battery voltage, and amount of Data available on the sim card.
Can someone please assist with this matter?
kind regards Hansie
Code
#include <HCSR04.h>
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701
// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1
// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800 // Modem is SIM800
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
// Define the serial console for debug prints, if needed
//#define DUMP_AT_COMMANDS
#include <Wire.h>
#include <TinyGsmClient.h>
#define uS_TO_S_FACTOR 1000000UL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 36 /* Time ESP32 will go to sleep (in seconds) 3600 seconds = 1 hour */
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
// TTGO T-Call pins
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
int deviceID=101;
const int trigPin = 5;
const int echoPin = 18;
//Calculation variable for depth
//define sound speed in cm/uS
long duration;
float distanceCm;
double damDepth =200;
// Your GPRS credentials
const char apn[] = "Vodacom APN"; // APN
const char gprsUser[] = ""; // GPRS User
const char gprsPass[] = ""; // GPRS Password
// SIM card PIN (leave empty, if not defined)
const char simPIN[] = "";
// Server details
const char server[] = "grow-with-pierre.com"; // domain name:
const char resource[] = "/post-data.php"; // resource path, for example: /post-data.php
const int port = 80; // server port number
// Keep this API Key value to be compatible with the PHP code
String apiKeyValue = "tPmAT5Ab3j7F9";
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
// I2C for SIM800 (to keep it running when powered from battery)
TwoWire I2CPower = TwoWire(0);
// TinyGSM Client for Internet connection
TinyGsmClient client(modem);
bool setPowerBoostKeepOn(int en)
{
I2CPower.beginTransmission(IP5306_ADDR);
I2CPower.write(IP5306_REG_SYS_CTL0);
if (en)
{
I2CPower.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
} else
{
I2CPower.write(0x35); // 0x37 is default reg value
}
return I2CPower.endTransmission() == 0;
}
void setup()
{
Serial.begin(115200); // Starts the serial communication
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
// Set serial monitor debugging window baud rate to 115200
SerialMon.begin(115200);
// Start I2C communication
I2CPower.begin(I2C_SDA, I2C_SCL, 400000);
// Keep power when running from battery
bool isOk = setPowerBoostKeepOn(1);
SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));
// Set modem reset, enable, power pins
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
// Restart SIM800 module, it takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// use modem.init() if you don't need the complete restart
// Unlock your SIM card with a PIN if needed
if (strlen(simPIN) && modem.getSimStatus() != 3 )
{
modem.simUnlock(simPIN);
}
// Configure the wake up source as timer wake up
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
}
void loop()
{
postData();
Serial.print(String(" Percentage: ") + depth());
// Put ESP32 into deep sleep mode (with timer wake up)
esp_deep_sleep_start();
}
String postData()
{
SerialMon.print("Connecting to APN: ");
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass))
{
SerialMon.println(" fail");
}
else
{
SerialMon.println(" OK");
SerialMon.print("Connecting to ");
SerialMon.print(server);
if (!client.connect(server, port))
{
SerialMon.println(" fail");
}
else
{
SerialMon.println(" OK");
// Making an HTTP POST request
SerialMon.println("Performing HTTP POST request...");
String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(deviceID)
+ "&value2=" + String(distanceCm) + "&value3=" + String(80) + "&value4=" + String(40) + ""+ "&value5=" + String(50) + "";
// then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
// String httpRequestData = "api_key=tPmAT5Ab3j7F9&value1=24.75&value2=49.54&value3=1005.14";
client.print(String("POST ") + resource + " HTTP/1.1\r\n");
client.print(String("Host: ") + server + "\r\n");
client.println("Connection: close");
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(httpRequestData.length());
client.println();
client.println(httpRequestData);
unsigned long timeout = millis();
while (client.connected() && millis() - timeout < 10000L)
{
// Print available data (HTTP response from server)
while (client.available())
{
char c = client.read();
SerialMon.print(c);
timeout = millis();
}
}
SerialMon.println();
// Close client and disconnect
client.stop();
SerialMon.println(F("Server disconnected"));
modem.gprsDisconnect();
SerialMon.println(F("GPRS disconnected"));
}
}
}
float depth() //Find Depth in cm
{
double persentage;
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculate the distance
distanceCm = duration * SOUND_SPEED/2;
// Prints the distance in the Serial Monitor
Serial.print("Distance (cm): ");
Serial.println(distanceCm);
persentage = (distanceCm/damDepth)*100;
if(persentage>=100)
{
persentage=100;
}
else
{
persentage=100- persentage;
}
return persentage;
}

For at least some of the desired functions, it isn't necessary to push AT-commands.
Try signalStrength = modem.getSignalQuality(); instead. It works for me on the Lilygo T-Call SIM800L. You can check out TinyGSM's Github-page for additional commands or this handy class reference

Related

Thinger.IO client setup for GPRS enabled ESP32 project

I've been using the Thinger.io platform for some of my IoT projects (mostly ESP8266 modules) for quite a long time now. The way I implemented it is something similar to that:
#include <ThingerESP8266.h>
#include <ESP8266WIFI.h>
#define USERNAME "username"
#define DEVICE_ID "deviceid"
#define DEVICE_CREDENTIAL "devicecredential"
ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
void connectToWifi() {
...
}
void setup() {
connectToWifi();
}
void loop() {
thing.handle();
}
and it just works. It is good to also mention that I've been using WiFi all the way.
Now I am trying to achieve the same by taking advantage of a controller called TTGO T-Call ESP32. It is GPRS enabled (using the TinyGsmClient.h) and I have inserted a SIM card inside of it which successfully connects to the internet. The issue is that I can not really establish a connection to the Thinger.io platform where my devices are hosted. This is what my code looks like (making a reference to this library example)
// Your GPRS credentials (leave empty, if not needed)
const char apn[] = ""; // APN (example: internet.vodafone.pt) use https://wiki.apnchanger.org
const char gprsUser[] = ""; // GPRS User
const char gprsPass[] = ""; // GPRS Password
// SIM card PIN (leave empty, if not defined)
const char simPIN[] = "";
// TTGO T-Call pins
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1
// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800 // Modem is SIM800
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
// Define the serial console for debug prints, if needed
//#define DUMP_AT_COMMANDS
#include <Wire.h>
#include <TinyGsmClient.h>
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
// I2C for SIM800 (to keep it running when powered from battery)
TwoWire I2CPower = TwoWire(0);
// TinyGSM Client for Internet connection
TinyGsmClient client(modem);
#define uS_TO_S_FACTOR 1000000UL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 3600 /* Time ESP32 will go to sleep (in seconds) 3600 seconds = 1 hour */
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
bool setPowerBoostKeepOn(int en){
I2CPower.beginTransmission(IP5306_ADDR);
I2CPower.write(IP5306_REG_SYS_CTL0);
if (en) {
I2CPower.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
} else {
I2CPower.write(0x35); // 0x37 is default reg value
}
return I2CPower.endTransmission() == 0;
}
void connectToApn(){
SerialMon.println("Connecting to: internet.vivacom.bg ... ");
while(!modem.gprsConnect(apn, gprsUser, gprsPass))
delay(500);
SerialMon.println("Successfully connected to: internet.vivacom.bg");
}
// #include <ThingerCore32.h> => ArduinoJson.h: No such file or directory
// #include <ThingerESP8266.h> => ESP8266WiFi.h : No such file or directory
#define USERNAME ""
#define DEVICE_ID ""
#define DEVICE_CREDENTIAL ""
#include <ThingerESP32.h>
ThingerESP32 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
//#include "arduino_secrets.h"
// Server details
const char server[] = "vsh.pp.ua";
const char resource[] = "/TinyGSM/logo.txt";
const int port = 80;
#include <ArduinoHttpClient.h>
HttpClient http(client, server, port);
void setup() {
// Set serial monitor debugging window baud rate to 115200
SerialMon.begin(115200);
// Start I2C communication
I2CPower.begin(I2C_SDA, I2C_SCL, 400000);
// Keep power when running from battery
bool isOk = setPowerBoostKeepOn(1);
SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));
// Set modem reset, enable, power pins
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
// Restart SIM800 module, it takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// Unlock your SIM card with a PIN if needed
if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
modem.simUnlock(simPIN);
}
// Configure the wake up source as timer wake up
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
// Connect to APN
connectToApn();
}
void loop() {
thing.handle();
SerialMon.println("In the loop ...");
delay(3000);
SerialMon.print(F("Performing HTTP GET request... "));
int err = http.get(resource);
if (err != 0) {
SerialMon.println(F("failed to connect"));
delay(10000);
return;
}
int status = http.responseStatusCode();
SerialMon.print(F("Response status code: "));
SerialMon.println(status);
if (!status) {
delay(10000);
return;
}
SerialMon.println(F("Response Headers:"));
while (http.headerAvailable()) {
String headerName = http.readHeaderName();
String headerValue = http.readHeaderValue();
SerialMon.println(" " + headerName + " : " + headerValue);
}
int length = http.contentLength();
if (length >= 0) {
SerialMon.print(F("Content length is: "));
SerialMon.println(length);
}
if (http.isResponseChunked()) {
SerialMon.println(F("The response is chunked"));
}
String body = http.responseBody();
SerialMon.println(F("Response:"));
SerialMon.println(body);
SerialMon.print(F("Body length is: "));
SerialMon.println(body.length());
// Put ESP32 into deep sleep mode (with timer wake up)
// esp_deep_sleep_start();
}
NOTE: The board I've picked from the Arduino IDE is called ESP32 Wrover Module
It would be better if you ask this question on the thinger community, the thinger.io https://community.thinger.io/ where the thinger devs or community will be listening.
I have some working code, see below, this works with SIM7000E, but it should work OK with SIM800 the code should work the same. I have noticed that you are not using the thinger library (ThingerTinyGSM.h) and this is probably why the device isn't connecting to thinger.
#define THINGER_SERIAL_DEBUG //This will provide debug messages of what thinger
code is trying to do
#define _DISABLE_TLS_ //TLS needs to be disabled if using ESP32 (not sure why, this is a known bug)
// Select your modem:
//#define TINY_GSM_MODEM_SIM800 //Note SimCom docs state that SIM7000e used same commands as SIM800
#define TINY_GSM_MODEM_SIM7000 //Note SimCom docs state that SIM7000e used same commands as SIM800
#define APN_NAME "..."
#define APN_USER "..."
#define APN_PSWD "..."
//Pins for connecting to SIM module using 2nd Serial connection
#define RXD1 16
#define TXD1 17
#include <TinyGsmClient.h>
#include <ThingerTinyGSM.h>
//Thinger credentials
#define USERNAME "...." //Thinger Account User Name
#define DEVICE_ID "...." //Thinger device IC
#define DEVICE_CREDENTIAL "...." //Thinger device credential (password)
ThingerTinyGSM thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL, Serial2);
/*******************************
**** SET-UP **** SET-UP ****
********************************/
void setup() {
// open serial for debugging
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, RXD1, TXD1);
delay(1000);
Serial.println(); Serial.println();
Serial.println("Starting Thinger GSM Test");
delay(1000);
// set APN, you can remove user and password from call if your apn does not require them
thing.setAPN(APN_NAME, APN_USER, APN_PSWD);
////// Thinger resource output example (i.e. reading a sensor value)
thing["Status"] >> [](pson & out) {
out["Timer(ms)"] = millis();
out["device"] = String(DEVICE_ID);
};
}
void loop() {
thing.handle();
}
This is the code which worked for me:
const char apn[] = ""; // APN (example: internet.vodafone.pt) use https://wiki.apnchanger.org
const char gprsUser[] = ""; // GPRS User
const char gprsPass[] = ""; // GPRS Password
// SIM card PIN (leave empty, if not defined)
const char simPIN[] = "";
// TTGO T-Call pins
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1
// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800 // Modem is SIM800
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
#include <Wire.h>
#include <TinyGsmClient.h>
TinyGsm modem(SerialAT);
// TinyGSM Client for Internet connection
TinyGsmClient client(modem);
void connectToApn(){
SerialMon.println("Connecting to: internet.vivacom.bg ... ");
while(!modem.gprsConnect(apn, gprsUser, gprsPass))
delay(500);
SerialMon.println("Successfully connected to: internet.vivacom.bg");
}
#define USERNAME ""
#define DEVICE_ID ""
#define DEVICE_CREDENTIAL ""
#include <ThingerTinyGSM.h>
ThingerTinyGSM thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL, Serial1);
void setup() {
// Set serial monitor debugging window baud rate to 115200
SerialMon.begin(115200);
// Set modem reset, enable, power pins
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
// Restart SIM800 module, it takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// Unlock your SIM card with a PIN if needed
if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
modem.simUnlock(simPIN);
}
// Connect to APN
connectToApn();
}
void loop() {
thing.handle();
}

can't recieve a msg on node red published from arduino using mqtt protocol

i have a problem in my arduino code, i'm using esp8266 to get data from a sensor, and i have to send this data to node red dashboard using mqtt protocol. The problem is that i couldn't publish a "string".
this is my code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#define Potentiometer A0
char ssid[] = "Fixbox-71CD43"; // your network SSID (name)
char pass[] = "ZTA0NWY2"; // your network password (use for WPA, or use as key for WEP)
//int keyIndex = 0; // your network key Index number (needed only for WEP)
const char* mqtt_server = "192.168.0.4";
int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the static IP instead of the name for the server:
// IPAddress server(74,125,232,128); // static IP for Google (no DNS)
//char server[] = "www.google.com"; // name address for Google (using DNS)
WiFiClient espclient;
PubSubClient client(espclient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
//char msg[MSG_BUFFER_SIZE];
//char message[50];
int sensorValue;
float VWC, Threshold1, Threshold2 , SubCalSlope, SubCalIntercept;
void setup() {
//*********************//*********************
// Declare variables for four 10HS sensors
//*********************//*********************
//*********************//*********************
unsigned long lastMsg = 0;
//*********************//*********************
//*********************//*********************
// SUBSTRATE CALIBRATION: You have to convert the voltage to VWC using soil or substrate specific calibration. Decagon has generic calibrations (check the 10HS manual at http://manuals.decagon.com/Manuals/13508_10HS_Web.pdf) or you can determine your own calibration. We used our own calibration for Fafard 1P (peat: perlite, Conrad Fafard, Inc., Agawam, MA)
SubCalSlope = 1.1785;
SubCalIntercept = -0.4938;
// IRRIGATION THRESHOLDS: Values used to trigger irrigation when the sensor readings are below a specific VWC (in units of m3/m3 or L/L)
Threshold1 = 0.4;
Threshold2 = 0.6;
//*********************//*********************
Serial.begin(115200);
// Configure digital pins D2 and D3 as outputs to apply voltage to all four sensors (D2: sensor 1 and 2; D3, sensor 3 and 4)
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
// client.setCallback(callback);
// initialize serial communication:
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// initialize the WiFi module:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi module not detected");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WiFi network ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected.\nWiFi network status:");
printWifiStatus();
Serial.println("\nStarting connection to MQTT server...");
client.setServer(mqtt_server, 1883);
// if you get a connection, report back via serial:
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("GW_sensor/humidity", "hello world");
client.publish("GW_sensor/salinity", "hello world");
// ... and resubscribe
client.subscribe("GW_sensor/#");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi device's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
}
void loop() {
char msg[10];
char msgtext[25];
String themsg;
// if there are incoming bytes available
// from the server, read them and print them:
// if the server's disconnected, stop the client:
if (!client.connected()) {
reconnect();
}
client.loop();
//*********************
// Apply power to 10HS sensor
// Wait 10 ms,
delay(10);
// Measure the analog output from sensor #1 and #2 (red wires connected to analog pins A0 and A1)
sensorValue = analogRead(0);
// And turn the power to the sensors off
digitalWrite(2, LOW);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 1.1V) that is used to calculate the VWC using a calibration equation
VWC = sensorValue * (1.1/1023.0) * SubCalSlope + SubCalIntercept;
//*********************//*********************
// Print the VWC
Serial.print("VWC (m3/m3): ");
Serial.print(" = ");
Serial.print(VWC);
//*********************//*********************
unsigned long now = millis();
//send data every 6 second
if (now - lastMsg > 500) {
lastMsg = now;
// Check to see if the VWC reading is below Threshold1
if (VWC < Threshold1) {
// If so, write an error message to the screen
Serial.print("WARNING:(too low) Irrigation needed. ");
sprintf(msgtext,"Irrigation needed",VWC);
}
// If the measured VWC is > Threshold2
if (VWC > Threshold2) {
// Write an error message to the screen
Serial.print("WARNING:(too high) Irrigation not needed. ");
sprintf(msgtext,"Irrigation not needed",VWC);
}
sprintf(msg,"%i",VWC);
//publish sensor data to MQTT broker
client.publish("GW_sensor/VWC_msg", msgtext);
client.publish("GW_sensor/VWC_val", msg);
}
please can you help me to fix my code? it can only send the values to the broker and the msg.
thank you all!
Payload isn't a "String", its a char buffer.
You need something like this:
snprintf (msg, BUF_SIZE, "msg: %i", VWC)
client.publish("GW_sensor/VWC_msg", msg)
The PubSubClient repo even has an ESP8266 example: https://github.com/knolleary/pubsubclient/blob/master/examples/mqtt_esp8266/mqtt_esp8266.ino

How to publish and subscribe to MQTT broker through GSM Module in Arduino/ESP8266?

I am currently working in a project where I have to publish and possibly subscribe to MQTT topic over GSM network (I am using ESP8266 and Ai Thinker A6 GSM Module). So far I am able to publish message to the broker once using MQTT Example code from TinyGSM library,where they pass the GPRS client instance to Pubsub Client class, but when I add a code in loop to publish message continuously every n seconds. The message is published only once or twice and then freezes.
I doubt the mqttclient.loop() function in the void loop(). But, I am just wondering is there any other library which is completely tested, because the TinyGSM developer itself has mentioned this code is not tested in github.
The example code with mqtt publish in loop
// Select your modem:
#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_SIM5360
// #define TINY_GSM_MODEM_SIM7600
// #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_SARAR4
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
// #define TINY_GSM_MODEM_SEQUANS_MONARCH
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1
// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
//SoftwareSerial SerialAT(2, 3); // RX, TX
// See all AT commands, if wanted
// #define DUMP_AT_COMMANDS
// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
// Range to attempt to autobaud
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200
// Add a reception delay - may be needed for a fast processor at a slow baud rate
// #define TINY_GSM_YIELD() { delay(2); }
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
// MQTT details
const char* broker = "broker.hivemq.com";
const char* topicLed = "GsmClientTest/led";
const char* topicInit = "GsmClientTest/init";
const char* topicLedStatus = "GsmClientTest/ledStatus";
#include <TinyGsmClient.h>
#include <PubSubClient.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
PubSubClient mqtt(client);
#define LED_PIN 13
int ledStatus = LOW;
uint32_t lastReconnectAttempt = 0;
void mqttCallback(char* topic, byte* payload, unsigned int len) {
SerialMon.print("Message arrived [");
SerialMon.print(topic);
SerialMon.print("]: ");
SerialMon.write(payload, len);
SerialMon.println();
// Only proceed if incoming message's topic matches
if (String(topic) == topicLed) {
ledStatus = !ledStatus;
digitalWrite(LED_PIN, ledStatus);
mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
}
}
boolean mqttConnect() {
SerialMon.print("Connecting to ");
SerialMon.print(broker);
// Connect to MQTT Broker
boolean status = mqtt.connect("GsmClientTest");
// Or, if you want to authenticate MQTT:
//boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass");
if (status == false) {
SerialMon.println(" fail");
return false;
}
SerialMon.println(" success");
mqtt.publish(topicInit, "GsmClientTest started");
mqtt.subscribe(topicLed);
return mqtt.connected();
}
void setup() {
// Set console baud rate
SerialMon.begin(115200);
delay(10);
pinMode(LED_PIN, OUTPUT);
// !!!!!!!!!!!
// Set your reset, enable, power pins here
// !!!!!!!!!!!
SerialMon.println("Wait...");
// Set GSM module baud rate
// TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
SerialAT.begin(9600);
delay(3000);
// Restart takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
#if TINY_GSM_USE_GPRS
// Unlock your SIM card with a PIN if needed
if ( GSM_PIN && modem.getSimStatus() != 3 ) {
modem.simUnlock(GSM_PIN);
}
#endif
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
#endif
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_XBEE
// The XBee must run the gprsConnect function BEFORE waiting for network!
modem.gprsConnect(apn, gprsUser, gprsPass);
#endif
SerialMon.print("Waiting for network...");
if (!modem.waitForNetwork()) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if (modem.isNetworkConnected()) {
SerialMon.println("Network connected");
}
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
#endif
// MQTT Broker setup
mqtt.setServer(broker, 1883);
mqtt.setCallback(mqttCallback);
}
void loop() {
if (!mqtt.connected()) {
SerialMon.println("=== MQTT NOT CONNECTED ===");
// Reconnect every 10 seconds
uint32_t t = millis();
if (t - lastReconnectAttempt > 10000L) {
lastReconnectAttempt = t;
if (mqttConnect()) {
lastReconnectAttempt = 0;
}
}
delay(100);
return;
}
else
{
mqtt.publish("Topic/test","Hi");
delay(1000);
}
mqtt.loop();
}

Error in sending data to cloud server and arduino lagging

The code im working on, is suppose to show temperature, humidity and able to take and show heart rate on the lcd. After data is shown, it will send data to "ThingSpeak". After sending, there will be a http code error -401 which is ok as it can only send data very 15 sec. But after awhile, it will change it error http code -301... and then it will hang. Another issue is when i try to use the temperature sensor with the heart rate sensor, the lcd will hang and it will not work till i reset.
#include "ThingSpeak.h"
#include "SPI.h"
#include "DHT.h"
#include <Ethernet.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(10, 9, 5, 4, 3, 2); //numbers of interface pins
#define redLED 8
int sensorPin = A8;
float tempC;
#define DHTPIN 6
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
float h;
#define USE_ARDUINO_INTERRUPTS true // Set-up low-level interrupts for most acurate BPM math.
#include <PulseSensorPlayground.h> // Includes the PulseSensorPlayground Library.
// Variables
const int PulseWire = A9; // PulseSensor PURPLE WIRE connected to ANALOG PIN 0
const int blinkPin = 22; // The on-board Arduino LED, close to PIN 13.
int Threshold = 550; // Determine which Signal to "count as a beat" and which to ignore.
PulseSensorPlayground pulseSensor; // Creates an instance of the PulseSensorPlayground object called "pulseSensor"
byte mac[] = {0x90, 0xA2, 0xDA, 0x10, 0x40, 0x4F};
unsigned long myChannelNumber = ;
const char * myWriteAPIKey = "";
// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(172, 17, 171, 199);
IPAddress myDns(172, 17, 171, 254);
float get_temperature(int pin)
{
float temperature = analogRead(pin); // Calculate the temperature based on the reading and send that value back
float voltage = temperature * 5.0;
voltage = voltage / 1024.0;
return ((voltage - 0.5) * 100);
}
EthernetClient client;
void setup()
{
lcd.begin(16, 2);
pinMode(redLED, OUTPUT);
pulseSensor.analogInput(PulseWire);
pulseSensor.blinkOnPulse(blinkPin); //auto-magically blink Arduino's LED with heartbeat.
pulseSensor.setThreshold(Threshold);
pulseSensor.begin();
dht.begin();
Ethernet.init(10); // Most Arduino Ethernet hardware
Serial.begin(9600); //Initialize serial
// start the Ethernet connection:
Serial.println("Initialize Ethernet with DHCP:");
if (Ethernet.begin(mac) == 0)
{
Serial.println("Failed to configure Ethernet using DHCP");
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true)
{
delay(10); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
}
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip, myDns);
}
else
{
Serial.print(" DHCP assigned IP ");
Serial.println(Ethernet.localIP());
}
// give the Ethernet shield a second to initialize:
delay(1000);
ThingSpeak.begin(client); // Initialize ThingSpeak
}
void loop()
{
h = dht.readHumidity();
{
tempC = get_temperature(sensorPin);
}
if (tempC < 31)
{
lcd.setCursor(0, 0);
lcd.print(tempC);
lcd.print(" "); //print the temp
lcd.print((char)223); // to get ° symbol
lcd.print("C");
lcd.print(" ");
lcd.print(h);
lcd.print("%");
delay(750);
}
else if (tempC > 31)
{
lcd.setCursor(0, 0);
lcd.print(tempC);
lcd.print(" "); //print the temp
lcd.print((char)223); // to get ° symbol
lcd.print("C");
lcd.print(" ");
lcd.print(h);
lcd.print("%");
delay(750);
}
int myBPM = pulseSensor.getBeatsPerMinute(); // Calls function on our pulseSensor object that returns BPM as an "int".
// "myBPM" hold this BPM value now.
if (pulseSensor.sawStartOfBeat())
{
lcd.setCursor(0,1);
lcd.print("BPM:"); // Print phrase "BPM: "
lcd.println(myBPM); // Print the value inside of myBPM.
lcd.print(" ");
delay(100);
}
// Write to ThingSpeak channel.
ThingSpeak.setField(1, tempC);
ThingSpeak.setField(2, h);
ThingSpeak.setField(3, myBPM);
int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if (x == 200)
{
Serial.println("Channel update successful.");
}
else
{
Serial.println("Problem updating channel. HTTP error code " + String(x));
}
}

Sending data to Xively using Arduino mega + Gprs shield sim 900

I am using Arduino Mega2560 and GPRS Shield Sim900 and trying to send data to Xively using the code below.
What should I change in this code to send data to Xively with Sim900 GPRS Shield?
/*
* Xively WiFi Sensor Tutorial
*
* This sketch is designed to take sensors (from photocell) and
* upload the values to Xively at consistant intervals. At the
* same time it gets a setable value from Xively to adjust the
* brigthness of an LED. This sketch is reusable and can be
* adapted for use with many different sensors.
*
* Derived from Xively Ardino Sensor Client by Sam Mulube.
*
* By Calum Barnes 3-4-2013
* BSD 3-Clause License - [http://opensource.org/licenses/BSD-3-Clause]
* Copyright (c) 2013 Calum Barnes
*/
#include <SPI.h>
#include <WiFi.h>
#include <HttpClient.h>
#include <Xively.h>
char ssid[] = "SSID_HERE"; // your network SSID (name)
char pass[] = "PASS_HERE"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
// Your Xively key to let you upload data
char xivelyKey[] = "API_KEY_HERE";
//your xively feed ID
#define xivelyFeed FEED_ID_HERE
//datastreams
char sensorID[] = "LIGHT_SENSOR_CHANNEL";
char ledID[] = "LED_CHANNEL";
// Analog pin which we're monitoring (0 and 1 are used by the Ethernet shield)
#define sensorPin A2
//led connected pin
#define ledPin 9
// Define the strings for our datastream IDs
XivelyDatastream datastreams[] = {
XivelyDatastream(sensorID, strlen(sensorID), DATASTREAM_FLOAT),
XivelyDatastream(ledID, strlen(ledID), DATASTREAM_FLOAT),
};
// Finally, wrap the datastreams into a feed
XivelyFeed feed(xivelyFeed, datastreams, 2 /* number of datastreams */);
WiFiClient client;
XivelyClient xivelyclient(client);
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm \n");
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
//pin setup
pinMode(sensorPin, INPUT);
pinMode(ledPin, OUTPUT);
Serial.println("Starting single datastream upload to Xively...");
Serial.println();
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, keyIndex, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
}
void loop() {
//adjust LED level. set from Xively
int getReturn = xivelyclient.get(feed, xivelyKey); //get data from xively
if (getReturn > 0) {
Serial.println("LED Datastream");
Serial.println(feed[1]);
} else {
Serial.println("HTTP Error");
}
//write value to LED - change brightness
int level = feed[1].getFloat();
if (level < 0) {
level = 0;
} else if (level > 255) {
level = 255;
}
//actually write the value
digitalWrite(ledPin, level);
//read sensor values
int sensorValue = analogRead(sensorPin);
datastreams[0].setFloat(sensorValue);
//print the sensor valye
Serial.print("Read sensor value ");
Serial.println(datastreams[0].getFloat());
//send value to xively
Serial.println("Uploading it to Xively");
int ret = xivelyclient.put(feed, xivelyKey);
//return message
Serial.print("xivelyclient.put returned ");
Serial.println(ret);
Serial.println("");
//delay between calls
delay(15000);
}

Resources