Hi...here I'm finishing a project. In this project I made a server room monitoring system using 2 slaves (slave 1 sent 1 sensor data and slave 2 sent 3 sensor data) using Arduino Nano to the master (Wemos D1 ESP8266). Here I use the max485 ttl to rs485 converter module and the modbusRtu Library from GitHub - smarmengol/Modbus-Master-Slave-for-Arduino: Modbus Master-Slave library for Arduino.
Here I have 2 examples of the master code that I made, the first slave code only sends data and the master prints data on the serial monitor. In this first code all slaves can be read by sensors. (results can be seen in the image below)
Then I developed the feature on the master by connecting to Telegram. Here I managed to connect the system to Telegram and Telegram was able to send messages as requested, but in this 2nd code, data from slave 2 could not be read and data that was successfully read when sent to Telegram still had a value of 0. (as shown below)
Here is the code for the master and each slave.
MASTER (Code 1)
// arduino mega master testing code
// modbus RS485 read and write register
// V1.1
// 1 master 2 slave,
// 1 slave : 1 input 1 output
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Wire.h>
#include <ModbusRtu.h>
#define slaveNumber 5
#define delayCom 15
#define maxQuery 2*2//slaveNumer*2
#define RX D3
#define TX D4
#define RTS D8
#include <SoftwareSerial.h>
//#include <LiquidCrystal_I2C.h>
SoftwareSerial mySerial(RX, TX);
//LiquidCrystal_I2C lcd(0x27,16,2);
char ssid[] = "BATU"; // diisi nama wifi
char password[] = "estehmanis";
WiFiClientSecure client;
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query
uint16_t dataBus[7];
uint16_t lastPrint = 100;
int slaveID[slaveNumber] = {11, 12, 13, 14, 15};
/**
Modbus object declaration
u8id : node id = 0 for master, = 1..247 for slave
port : Serial1 port
u8txenpin : 0 for RS-232 and USB-FTDI
or any pin number > 1 for RS-485
*/
Modbus master(0, mySerial, RTS); // ID, seriapNumber, enablePin
/**
This is an structe which contains a query to an slave device
*/
modbus_t telegram[slaveNumber * 2];
unsigned long u32wait;
void init_modBus() {
int num = 0;
int addr = 0;
////SLAVE 1
// Read 1 data from Slave 11
telegram[num].u8id = slaveID[0]; // slave address
telegram[num].u8fct = 3; // function code (this one is registers read)
telegram[num].u16RegAdd = 0; // start address in slave
telegram[num].u16CoilsNo = 2; // number of elements (coils or registers) to read
telegram[num].au16reg = dataBus; // pointer to a memory array in the Arduino
num += 1;
addr += 2;
//SLAVE 2
// Read 1 data from Slave 2
telegram[num].u8id = slaveID[1]; // slave address
telegram[num].u8fct = 3; // function code (this one is registers read)
telegram[num].u16RegAdd = 0; // start address in slave
telegram[num].u16CoilsNo = 5; // number of elements (coils or registers) to read
telegram[num].au16reg = dataBus + 3; // pointer to a memory array in the Arduino
num += 1;
addr += 2;
master.start();
master.setTimeOut( 100 ); // if there is no answer in 100 ms, roll over
u32wait = millis() + 40;
u8state = u8query = 0;
}
void rtuState() {
switch ( u8state ) {
case 0:
if (millis() >= u32wait) u8state++; // wait state
break;
case 1:
master.query( telegram[u8query] ); // send query (only once)
u8state++;
u8query++;
if (u8query >= maxQuery)
u8query = 0;
break;
case 2:
master.poll(); // check incoming messages if communication in idle state
if (master.getState() == COM_IDLE) {
u8state = 0;
u32wait = millis() + delayCom; //delay for next state
}
break;
}
}
void printData() {
if (millis() - lastPrint > 200) {
//print data to validate
// Serial.print("Slave:");Serial.println(dataBus[0]);
// Serial.print("Arus:");Serial.println(dataBus[1]);
// Serial.print("Slave:");Serial.println(dataBus[3]);
// Serial.print("Suhu:");Serial.println(dataBus[4]);
// Serial.print("Kelembapan:");Serial.println(dataBus[5]);
// Serial.print("Getaran:");Serial.println(dataBus[6]);
Serial.print(dataBus[0]); Serial.print(":");
Serial.print(dataBus[1]); Serial.print(":");
Serial.print(dataBus[2]); Serial.print("\t:\t");
Serial.print(dataBus[3]); Serial.print(":");
Serial.print(dataBus[4]); Serial.print(":");
Serial.print(dataBus[5]); Serial.print(":");
Serial.print(dataBus[6]);
Serial.println();
}
}
void setup() {
Serial.begin (9600); //baud rate of Serial PC
mySerial.begin( 19200 ); // baud-rate of RS485
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.print("Connecting Wifi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi terhubung");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
init_modBus();
}
void loop() {
rtuState();
printData();
//processData();
}
MASTER (Code 2 with Telegram)
// arduino mega master testing code
// modbus RS485 read and write register
// V1.1
// 1 master 2 slave,
// 1 slave : 1 input 1 output
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Wire.h>
#include <ModbusRtu.h>
#define slaveNumber 5
#define delayCom 15
#define maxQuery 2*2//slaveNumer*2
#define RX D3
#define TX D4
#define RTS D8
#include <SoftwareSerial.h>
//#include <LiquidCrystal_I2C.h>
SoftwareSerial mySerial(RX, TX);
//LiquidCrystal_I2C lcd(0x27,16,2);
const long utcOffsetInSeconds = 3600 * 7; //timer
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
char daysOfTheWeek[7][12] = {"Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"};
char ssid[] = "BATU"; // diisi nama wifi
char password[] = "estehmanis";
#define BOTtoken "5404730433:AAFjsIjfVkY9IdEfhi2wOK59J_pFTAbMNKo" // diisi Token Bot (Dapat dari Telegram Botfather)
#define idChat "-1001841459091" //idbot
//int botRequestDelay = 1000;
unsigned long lastTimeBotRan;
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query
uint16_t dataBus[7];
uint16_t lastPrint = 100;
int slaveID[slaveNumber] = {11, 12, 13, 14, 15};
/**
Modbus object declaration
u8id : node id = 0 for master, = 1..247 for slave
port : Serial1 port
u8txenpin : 0 for RS-232 and USB-FTDI
or any pin number > 1 for RS-485
*/
Modbus master(0, mySerial, RTS); // ID, seriapNumber, enablePin
/**
This is an structe which contains a query to an slave device
*/
modbus_t telegram[slaveNumber * 2];
unsigned long u32wait;
void init_modBus() {
int num = 0;
int addr = 0;
////SLAVE 1
// Read 1 data from Slave 11
telegram[num].u8id = slaveID[0]; // slave address
telegram[num].u8fct = 3; // function code (this one is registers read)
telegram[num].u16RegAdd = 0; // start address in slave
telegram[num].u16CoilsNo = 2; // number of elements (coils or registers) to read
telegram[num].au16reg = dataBus; // pointer to a memory array in the Arduino
num += 1;
addr += 2;
//SLAVE 2
// Read 1 data from Slave 2
telegram[num].u8id = slaveID[1]; // slave address
telegram[num].u8fct = 3; // function code (this one is registers read)
telegram[num].u16RegAdd = 0; // start address in slave
telegram[num].u16CoilsNo = 4; // number of elements (coils or registers) to read
telegram[num].au16reg = dataBus + 3; // pointer to a memory array in the Arduino
num += 1;
addr += 2;
master.start();
master.setTimeOut( 100 ); // if there is no answer in 100 ms, roll over
u32wait = millis() + 40;
u8state = u8query = 0;
}
void rtuState() {
switch ( u8state ) {
case 0:
if (millis() >= u32wait) u8state++; // wait state
break;
case 1:
master.query( telegram[u8query] ); // send query (only once)
u8state++;
u8query++;
if (u8query >= maxQuery)
u8query = 0;
break;
case 2:
master.poll(); // check incoming messages if communication in idle state
if (master.getState() == COM_IDLE) {
u8state = 0;
u32wait = millis() + delayCom; //delay for next state
}
break;
}
}
void printData() {
if (millis() - lastPrint > 200) {
//print data to validate
Serial.print(dataBus[0]); Serial.print(":");
Serial.print(dataBus[1]); Serial.print(":");
Serial.print(dataBus[2]); Serial.print("\t:\t");
Serial.print(dataBus[3]); Serial.print(":");
Serial.print(dataBus[4]); Serial.print(":");
Serial.print(dataBus[5]); Serial.print(":");
Serial.print(dataBus[6]);
Serial.println();
}
}
void setup() {
Serial.begin (9600); //baud rate of Serial PC
mySerial.begin( 19200 ); // baud-rate of RS485
client.setInsecure();
uint32_t notConnectedCounter = 0;
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.print("Connecting Wifi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi terhubung");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
init_modBus();
}
void loop() {
rtuState();
printData();
peringatan();
//processData();
}
void peringatan() {
timeClient.update();
Serial.print("Suhu saat ini : ");
Serial.print(dataBus[2]);
Serial.println(" *C\n");
Serial.print("Kelembapan saat ini : ");
Serial.print(dataBus[5]);
Serial.println("%");
Serial.print("Getaran saat ini : ");
Serial.print(dataBus[6]);
Serial.println();
//
// if (timeClient.getHours() <= 9) {lcd.print("0");}
// if (timeClient.getMinutes() <= 9) {lcd.print("0");}
// if (timeClient.getSeconds() <= 9) {lcd.print("0");}
if (timeClient.getHours() == 20 and timeClient.getMinutes() == 50 and timeClient.getSeconds() <= 15) {
bot.sendChatAction(idChat, "Sedang mengetik...");
String suhu = "KONDISI SUHU DAN KELEMBAPAN SAAT INI\n";
suhu += "\nHari : ";
suhu += daysOfTheWeek[timeClient.getDay()];
suhu += "\nPukul : ";
suhu += timeClient.getHours();
suhu += ":";
suhu += timeClient.getMinutes();
suhu += ":";
suhu += timeClient.getSeconds();
suhu += " WIB";
suhu += "\nSuhu : ";
suhu += int(dataBus[2]);
suhu += " *C\n";
suhu += "Kelembapan : ";
suhu += int(dataBus[5]);
suhu += " %\n";
suhu += "Getaran : ";
suhu += int(dataBus[6]);
bot.sendMessage(idChat, suhu, "");
Serial.print("Mengirim data sensor ke telegram\n");
}
if (timeClient.getHours() == 21 and timeClient.getMinutes() == 00 and timeClient.getSeconds() <= 15) {
bot.sendChatAction(idChat, "Sedang mengetik...");
String suhu = "KONDISI SUHU DAN KELEMBAPAN SAAT INI\n";
suhu += "\nHari : ";
suhu += daysOfTheWeek[timeClient.getDay()];
suhu += "\nPukul : ";
suhu += timeClient.getHours();
suhu += ":";
suhu += timeClient.getMinutes();
suhu += ":";
suhu += timeClient.getSeconds();
suhu += " WIB";
suhu += "\nSuhu : ";
suhu += int(dataBus[2]);
suhu += " *C\n";
suhu += "Kelembapan : ";
suhu += int(dataBus[5]);
suhu += " %\n";
suhu += "Getaran : ";
suhu += int(dataBus[6]);
bot.sendMessage(idChat, suhu, "");
Serial.print("Mengirim data sensor ke telegram\n");
}
if (dataBus[2] < 18) {
if (timeClient.getMinutes() == 30 or timeClient.getMinutes() == 0) {
bot.sendChatAction(idChat, "Sedang mengetik...");
String suhu = "SUHU RUANGAN RENDAH\n";
suhu += "\nHari : ";
suhu += daysOfTheWeek[timeClient.getDay()];
suhu += "\n Pukul : ";
suhu += timeClient.getHours();
suhu += ":";
suhu += timeClient.getMinutes();
suhu += ":";
suhu += timeClient.getSeconds();
suhu += " WIB";
suhu += "Suhu : ";
suhu += int(dataBus[2]);
suhu += " *C\n";
bot.sendMessage(idChat, suhu, "");
Serial.print("Mengirim data sensor ke telegram\n");
}
}
if (dataBus[5] < 40) {
if (timeClient.getMinutes() == 30 or timeClient.getMinutes() == 0) {
bot.sendChatAction(idChat, "Sedang mengetik...");
String suhu = "KELEMBAPAN RUANGAN RENDAH\n";
suhu += "\nHari : ";
suhu += daysOfTheWeek[timeClient.getDay()];
suhu += "\nPukul : ";
suhu += timeClient.getHours();
suhu += ":";
suhu += timeClient.getMinutes();
suhu += ":";
suhu += timeClient.getSeconds();
suhu += " WIB";
suhu += "Kelembapan : ";
suhu += int(dataBus[5]);
suhu += " %\n";
bot.sendMessage(idChat, suhu, "");
Serial.print("Mengirim data sensor ke telegram\n");
}
}
if (dataBus[2] > 27) {
if (timeClient.getMinutes() == 5 or timeClient.getMinutes() == 10 or timeClient.getMinutes() == 15 or timeClient.getMinutes() == 20 or timeClient.getMinutes() == 25 or timeClient.getMinutes() == 30 or timeClient.getMinutes() == 35 or timeClient.getMinutes() == 40 or timeClient.getMinutes() == 45 or timeClient.getMinutes() == 50 or timeClient.getMinutes() == 55 or timeClient.getMinutes() == 0) {
if (timeClient.getSeconds() <= 15) {
bot.sendChatAction(idChat, "Sedang mengetik...");
String suhu = "SUHU RUANGAN TINGGI\n";
suhu += "\nHari : ";
suhu += daysOfTheWeek[timeClient.getDay()];
suhu += "\nPukul : ";
suhu += timeClient.getHours();
suhu += ":";
suhu += timeClient.getMinutes();
suhu += ":";
suhu += timeClient.getSeconds();
suhu += " WIB";
suhu += "\nSuhu : ";
suhu += int(dataBus[2]);
suhu += " *C\n";
bot.sendMessage(idChat, suhu, "");
Serial.print("Mengirim data sensor ke telegram\n");
}
}
}
if (dataBus[5] > 60) {
if (timeClient.getMinutes() == 5 or timeClient.getMinutes() == 10 or timeClient.getMinutes() == 15 or timeClient.getMinutes() == 20 or timeClient.getMinutes() == 25 or timeClient.getMinutes() == 30 or timeClient.getMinutes() == 35 or timeClient.getMinutes() == 40 or timeClient.getMinutes() == 45 or timeClient.getMinutes() == 50 or timeClient.getMinutes() == 55 or timeClient.getMinutes() == 0) {
if (timeClient.getSeconds() <= 15) {
bot.sendChatAction(idChat, "Sedang mengetik...");
String suhu = "KELEMBAPAN RUANGAN TINGGI\n";
suhu += "\nHari : ";
suhu += daysOfTheWeek[timeClient.getDay()];
suhu += "\nPukul : ";
suhu += timeClient.getHours();
suhu += ":";
suhu += timeClient.getMinutes();
suhu += ":";
suhu += timeClient.getSeconds();
suhu += " WIB";
suhu += "\nKelembapan : ";
suhu += int(dataBus[5]);
suhu += " %\n";
bot.sendMessage(idChat, suhu, "");
Serial.print("Mengirim data sensor ke telegram\n");
}
}
}
}
SLAVE 1 (send 1 data)
#include <ModbusRtu.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);
#include <DHT.h>
#define slaveID 11
#define DHTPIN 7
#define DHTTYPE DHT11
int SWPIN=8;
DHT dht(DHTPIN,DHTTYPE);
int t;
int h;
int g;
uint16_t Suhu = 0;
uint16_t Lembab = 0;
uint16_t Getar = 0;
unsigned long lastPrint = 0;
// data array for modbus network sharing
uint16_t au16data[4] = {
slaveID, 225, 8888, 9999};
Modbus slave(slaveID, mySerial, 4); // this is slave @1 and RS-232 or USB-FTDI
void setup() {
Serial.begin(9600);
mySerial.begin( 19200 ); // baud-rate at 19200
dht.begin();
pinMode (SWPIN, INPUT);
slave.start();
delay(10);
}
void loop() {
slave.poll( au16data, 4 );
if (millis() - lastPrint>200){
Serial.print(au16data[0]); Serial.print(":");
Serial.print(au16data[1]); Serial.print(":");
Serial.print(au16data[2]); Serial.println();
lastPrint = millis();
}
readSensor(); //for ultrasonic sensor
}
//long vibration(){
// long g=pulseIn (SWPIN, HIGH);
// return g;
//}
void readSensor() {
t = dht.readTemperature();
h = dht.readHumidity();
if (isnan(h) || isnan (t)){
au16data[1] = 0;
}
Suhu = t;
au16data[1] = Suhu; //data to be sent to slave device
}
SLAVE 2 (Send 3 data to master)
#include <ModbusRtu.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);
#include <DHT.h>
#define slaveID 12
#define DHTPIN 7
#define DHTTYPE DHT11
int SWPIN=8;
DHT dht(DHTPIN,DHTTYPE);
int t;
int h;
int g;
uint16_t Suhu = 0;
uint16_t Lembab = 0;
uint16_t Getar = 0;
unsigned long lastPrint = 0;
// data array for modbus network sharing
uint16_t au16data[5] = {
slaveID, 225, 255,255, 9999
};
Modbus slave(slaveID, mySerial, 4); // this is slave @1 and RS-232 or USB-FTDI
void setup() {
Serial.begin(9600);
mySerial.begin( 19200 ); // baud-rate at 19200
dht.begin();
pinMode (SWPIN, INPUT);
slave.start();
delay(10);
}
void loop() {
slave.poll( au16data, 5 );
if (millis() - lastPrint > 200) {
Serial.print(au16data[0]); Serial.print(":");
Serial.print(au16data[1]); Serial.print(":");
Serial.print(au16data[2]); Serial.print(":");
Serial.print(au16data[3]); Serial.println();
lastPrint = millis();
}
readSensor(); //for ultrasonic sensor
}
long vibration(){
long g=pulseIn (SWPIN, HIGH);
return g;
}
void readSensor() {
t = dht.readTemperature();
h = dht.readHumidity();
g = vibration();
cekGetar();
if (isnan(h) || isnan (t)){
au16data[1] = 0;
au16data[2] = 0;
}
Suhu = t;
Lembab = h;
au16data[1] = Suhu; //data to be sent to slave device
au16data[2] = Lembab;
au16data[3] = Getar;
}
void cekGetar(){
if (g==0){
Getar = 0;
}
if (g>0 && g<=1000){
Getar = 1;
}
if (g>1000 && g<=10000){
Getar = 2;
}
if (g>10000){
Getar = 3;
}
return Getar;
}
I hope someone can help me because I'm being chased by having a deadline of 3 days :(.
Thanks,
Fatwatul