// Khi khởi động 3 led sẽ nhấp nháy rồi tắt
// Nếu có RTC thì khởi động xong LED1 bên trái sẽ sáng
// Nếu thẻ SD được lắp vào khi khởi động thì LED2 sẽ sáng
// Bấm nút IO-0 sẽ bật LED1 bên trái thả ra sẽ tắt
// Bấm giữ IO-0 3s LED3 sẽ sáng và thực hiện cuộc gọi hoặc gửi SMS để TEST-SIM
#include <SPI.h>
#include <SD.h>
#include <Ethernet.h>
#include <WiFi.h>
#include <ModbusMaster.h>
#include "RTClib.h"
#include "Wire.h"
#include <HardwareSerial.h>
#define BUTTON 0
// LED pins (LOW active)
#define LED1 12
#define LED2 13
#define LED3 5
// UART pins for Modbus RTU
#define RXD2 17
#define TXD2 16
// I2C pins for RTC
#define SDA 22
#define SCL 21
// SD card CS pin
#define SD_CS 33
RTC_DS1307 rtc;
#define PHONE_NUMBER "+84971113732"
// SIM4G Serial
#define simSerial Serial2
#define MCU_SIM_BAUDRATE 115200
#define MCU_SIM_TX_PIN 26
#define MCU_SIM_RX_PIN 27
#define MCU_SIM_EN_PIN 25
// Ethernet W5500 pins
#define ETH_CS_PIN 32
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
const char *ssid = "iMTrongThan";
const char *password = "imaker12345";
// Modbus Master object
ModbusMaster node;
uint16_t startAddress = 0;
uint8_t quantity = 1;
uint16_t data[1];
char datachar[1];
// Thêm biến lưu trạng thái nút và LED1
bool lastButtonState = HIGH;
bool led1State = HIGH;
bool wifiConnected = false;
bool ethConnected = false;
unsigned long lastWifiBlink = 0, lastEthBlink = 0;
bool wifiLedState = HIGH, ethLedState = HIGH;
// Biến cho nút nhấn giữ
unsigned long buttonPressTime = 0;
bool buttonLongPressed = false;
void blinkAllLEDs()
{
for (int i = 0; i < 3; i++)
{
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(250);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(250);
}
}
void sim_at_wait()
{
delay(100);
while (simSerial.available())
{
Serial.write(simSerial.read());
}
}
bool sim_at_cmd(String cmd)
{
simSerial.println(cmd);
sim_at_wait();
return true;
}
bool sim_at_send(char c)
{
simSerial.write(c);
return true;
}
void sent_sms()
{
sim_at_cmd("AT+CMGF=1");
String temp = "AT+CMGS=\"";
temp += (String)PHONE_NUMBER;
temp += "\"";
sim_at_cmd(temp);
sim_at_cmd("ESP32-SIM7600X");
sim_at_send(0x1A);
}
void call()
{
String temp = "ATD";
temp += PHONE_NUMBER;
temp += ";";
sim_at_cmd(temp);
delay(20000);
sim_at_cmd("ATH");
}
// Kiểm tra SD card
bool checkSDCard()
{
if (SD.begin(SD_CS))
{
Serial.println("✅ SD Card detected");
digitalWrite(LED2, LOW); // Sáng LED2 nếu có SD
return true;
}
else
{
Serial.println("❌ No SD Card");
digitalWrite(LED2, HIGH); // Tắt LED2 nếu không có SD
return false;
}
}
// Kiểm tra RTC
bool checkRTC()
{
if (!rtc.begin())
{
Serial.println("❌ RTC not found");
led1State = HIGH;
digitalWrite(LED1, led1State); // Tắt LED1 nếu không có RTC
return false;
}
Serial.println("✅ RTC detected");
led1State = LOW;
digitalWrite(LED1, led1State); // Sáng LED1 nếu có RTC
return true;
}
void setup()
{
Serial.begin(115200);
// Setup LEDs
pinMode(LED1, OUTPUT);
digitalWrite(LED1, HIGH);
pinMode(LED2, OUTPUT);
digitalWrite(LED2, HIGH);
pinMode(LED3, OUTPUT);
digitalWrite(LED3, HIGH);
// Button input
pinMode(BUTTON, INPUT_PULLUP);
// Khi khởi động 3 led sẽ nhấp nháy rồi tắt
blinkAllLEDs();
// Ethernet setup
Ethernet.init(ETH_CS_PIN);
if (Ethernet.begin(mac) == 0)
{
Serial.println("❌ Ethernet DHCP failed");
ethConnected = false;
}
else
{
Serial.print("✅ Ethernet IP: ");
Serial.println(Ethernet.localIP());
ethConnected = true;
}
// WiFi connection
WiFi.begin(ssid, password);
Serial.println("🔄 Connecting WiFi...");
// Modbus setup
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
node.begin(1, Serial2);
Wire.begin(SDA, SCL);
// Nếu thẻ SD được lắp vào khi khởi động thì LED2 sẽ sáng
checkSDCard();
// Nếu có RTC thì khởi động xong LED1 bên trái sẽ sáng
checkRTC();
delay(20);
Serial.println("\n\n\n\n-----------------------\nSystem started!!!!");
}
void loop()
{
// Đọc trạng thái nút IO-0
bool currentButtonState = digitalRead(BUTTON);
Serial.println(currentButtonState);
// Phát hiện cạnh xuống (HIGH -> LOW): nhấn nút
if (lastButtonState == HIGH && currentButtonState == LOW)
{
// Đảo trạng thái LED1
led1State = !led1State;
digitalWrite(LED1, led1State);
buttonPressTime = millis(); // bắt đầu tính thời gian giữ nút
}
// Nếu đang giữ nút (LOW), kiểm tra thời gian giữ để xử lý LED3 và gửi SMS/cuộc gọi
if (currentButtonState == LOW)
{
if (!buttonLongPressed && (millis() - buttonPressTime > 3000))
{
digitalWrite(LED3, LOW); // Sáng LED3
/* Power enable SIM */
pinMode(MCU_SIM_EN_PIN, OUTPUT);
digitalWrite(MCU_SIM_EN_PIN, HIGH);
// Delay 8s for power on
delay(8000);
simSerial.begin(MCU_SIM_BAUDRATE, SERIAL_8N1, MCU_SIM_RX_PIN, MCU_SIM_TX_PIN);
// Check AT Command
sim_at_cmd("AT");
sim_at_cmd("ATI");
sim_at_cmd("AT+CPIN?");
sim_at_cmd("AT+CSQ");
sim_at_cmd("AT+CIMI");
delay(1000);
// sent_sms();
// delay(5000);
call();
buttonLongPressed = true;
}
}
// Lưu trạng thái nút cho lần lặp tiếp theo
lastButtonState = currentButtonState;
// Check WiFi
if (!wifiConnected && WiFi.status() == WL_CONNECTED)
{
Serial.print("✅ WiFi Connected, IP: ");
Serial.println(WiFi.localIP());
wifiConnected = true;
}
// LED2 blinking if WiFi connected
if (wifiConnected && millis() - lastWifiBlink > 500)
{
wifiLedState = !wifiLedState;
digitalWrite(LED2, wifiLedState);
lastWifiBlink = millis();
}
// LED3 blinking if Ethernet connected
if (ethConnected && millis() - lastEthBlink > 500)
{
ethLedState = !ethLedState;
digitalWrite(LED3, ethLedState);
lastEthBlink = millis();
}
// Modbus read every 1s, only print if read is successful, else print error code
static unsigned long lastModbusRead = 0;
if (millis() - lastModbusRead >= 500)
{
lastModbusRead = millis();
uint8_t result = node.readHoldingRegisters(startAddress, quantity);
if (result == node.ku8MBSuccess)
{
uint16_t regValue = node.getResponseBuffer(0);
Serial.print("Register 0: ");
Serial.println(regValue);
}
else
{
Serial.print("Modbus read failed, error code: ");
Serial.println(result);
}
}
}