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 https://github.com/smarmengol/Modbus-Master-Slave-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. 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.
Here is the code for the master and each slave.
MASTER(CODE 1, just receive data form slave)
// 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 (Sent 1 sensor data to master)
#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 (Sent 3 sensor 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