#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Инициализация LCD дисплея 20x4 с адресом 0x27
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Режимы работы
enum Mode {
MODE_IDLE,
MODE_GSM,
MODE_GPS,
MODE_BLE
};
Mode currentMode = MODE_IDLE;
// Переменные для симуляции отправки данных
unsigned long previousSimMillis = 0;
long simInterval = 2000; // Интервал для симуляции
// Буфер для приема данных
String inputBuffer = "";
// Данные для GSM
String smsNumber = "";
String smsText = "";
unsigned long smsReceiveTime = 0;
// Данные для GPS
float latitude = 0.0;
char latDir = 'N';
float longitude = 0.0;
char lonDir = 'E';
float speed = 0.0;
char status = 'V';
// Данные для BLE
float temperature = 23.5;
int humidity = 65;
void setup() {
Serial.begin(115200); // ESP32 поддерживает высокие скорости
// Инициализация LCD
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("ESP32 System");
lcd.setCursor(0, 1);
lcd.print("Ready");
lcd.setCursor(0, 2);
lcd.print("Commands:");
lcd.setCursor(0, 3);
lcd.print("GSM/GPS/BLE");
Serial.println("=================================");
Serial.println("ESP32 Wireless Simulation System");
Serial.println("=================================");
Serial.println("Available commands: GSM, GPS, BLE");
Serial.println("CPU Frequency: " + String(getCpuFrequencyMhz()) + " MHz");
Serial.println("Free Heap: " + String(ESP.getFreeHeap()) + " bytes");
Serial.println("=================================");
}
void loop() {
// Обработка команд из Serial
if (Serial.available() > 0) {
char c = Serial.read();
if (c == '\n' || c == '\r') {
if (inputBuffer.length() > 0) {
processCommand(inputBuffer);
inputBuffer = "";
}
} else {
inputBuffer += c;
}
}
// Симуляция отправки данных
unsigned long currentMillis = millis();
if (currentMode != MODE_IDLE && (currentMillis - previousSimMillis >= simInterval)) {
previousSimMillis = currentMillis;
simulateData();
}
}
// Обработка команд
void processCommand(String cmd) {
cmd.trim();
cmd.toUpperCase();
Serial.print("Command received: ");
Serial.println(cmd);
if (cmd == "GSM") {
currentMode = MODE_GSM;
simInterval = 3000;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("GSM Mode Active");
lcd.setCursor(0, 1);
lcd.print("Waiting for SMS");
Serial.println(">>> GSM mode activated");
previousSimMillis = millis() - simInterval;
}
else if (cmd == "GPS") {
currentMode = MODE_GPS;
simInterval = 2000;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("GPS Mode Active");
lcd.setCursor(0, 1);
lcd.print("Waiting for data");
Serial.println(">>> GPS mode activated");
previousSimMillis = millis() - simInterval;
}
else if (cmd == "BLE") {
currentMode = MODE_BLE;
simInterval = 2000;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("BLE Mode Active");
lcd.setCursor(0, 1);
lcd.print("Waiting for data");
Serial.println(">>> BLE mode activated");
previousSimMillis = millis() - simInterval;
}
else {
Serial.println("Unknown command. Use: GSM, GPS, or BLE");
}
}
void simulateData() {
switch (currentMode) {
case MODE_GSM:
simulateGSM();
break;
case MODE_GPS:
simulateGPS();
break;
case MODE_BLE:
simulateBLE();
break;
default:
break;
}
}
void simulateGSM() {
static int smsCounter = 0;
String testNumbers[] = {"+79123456789", "+79876543210", "+79111222333"};
String testMessages[] = {"Hello World!", "Test message", "ESP32 rocks!"};
String simData = "GSM:SMS:" + testNumbers[smsCounter % 3] + ":\"" + testMessages[smsCounter % 3] + "\"";
smsCounter++;
Serial.print("Simulated GSM data: ");
Serial.println(simData);
parseGSM(simData);
}
void parseGSM(String data) {
// Формат: GSM:SMS:+79123456789:"Текст сообщения"
if (data.startsWith("GSM:SMS:")) {
smsReceiveTime = millis();
int firstColon = data.indexOf(':', 8);
if (firstColon > 0) {
smsNumber = data.substring(8, firstColon);
int firstQuote = data.indexOf('"', firstColon);
int lastQuote = data.lastIndexOf('"');
if (firstQuote > 0 && lastQuote > firstQuote) {
smsText = data.substring(firstQuote + 1, lastQuote);
}
// Вывод на LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SMS from:");
lcd.setCursor(0, 1);
lcd.print(smsNumber);
lcd.setCursor(0, 2);
lcd.print("Message text:");
lcd.setCursor(0, 3);
if (smsText.length() > 16) {
lcd.print(smsText.substring(0, 16));
} else {
lcd.print(smsText);
}
Serial.println(">>> GSM data parsed and displayed");
Serial.println("Time: " + String(smsReceiveTime) + " ms");
}
}
}
void simulateGPS() {
static int gpsCounter = 0;
String testGPS[] = {
"GPS:$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A",
"GPS:$GPRMC,124520,A,5545.123,N,03736.456,E,015.2,125.6,230394,003.1,W*6A",
"GPS:$GPRMC,125521,V,6012.789,N,02456.123,E,000.0,000.0,230394,003.1,W*6A"
};
String simData = testGPS[gpsCounter % 3];
gpsCounter++;
Serial.print("Simulated GPS data: ");
Serial.println(simData);
parseGPS(simData);
}
void parseGPS(String data) {
// Формат: GPS:$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
if (data.startsWith("GPS:$GPRMC")) {
String nmea = data.substring(4); // Убираем префикс "GPS:"
int indices[15];
int idx = 0;
for (int i = 0; i < nmea.length() && idx < 15; i++) {
if (nmea.charAt(i) == ',') {
indices[idx++] = i;
}
}
if (idx >= 7) {
status = nmea.charAt(indices[1] + 1);
String latStr = nmea.substring(indices[2] + 1, indices[3]);
latitude = parseCoordinate(latStr);
latDir = nmea.charAt(indices[3] + 1);
String lonStr = nmea.substring(indices[4] + 1, indices[5]);
longitude = parseCoordinate(lonStr);
lonDir = nmea.charAt(indices[5] + 1);
String spdStr = nmea.substring(indices[6] + 1, indices[7]);
speed = spdStr.toFloat();
// Вывод на LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("LAT:");
lcd.print(latitude, 5);
lcd.print(" ");
lcd.print(latDir);
lcd.setCursor(0, 1);
lcd.print("LON:");
lcd.print(longitude, 5);
lcd.print(" ");
lcd.print(lonDir);
lcd.setCursor(0, 2);
lcd.print("SPD:");
lcd.print(speed, 1);
lcd.print("km/h");
lcd.setCursor(0, 3);
lcd.print("STAT:");
lcd.print(status);
Serial.println(">>> GPS data parsed and displayed");
}
}
}
float parseCoordinate(String coord) {
if (coord.length() < 4) return 0.0;
float value = coord.toFloat();
int degrees = (int)(value / 100);
float minutes = value - (degrees * 100);
return degrees + (minutes / 60.0);
}
void simulateBLE() {
static float temp = 20.0;
static int hum = 50;
// Небольшое изменение значений
temp += random(-10, 20) / 10.0;
hum += random(-5, 6);
// Ограничения
if (temp < 15.0) temp = 15.0;
if (temp > 30.0) temp = 30.0;
if (hum < 30) hum = 30;
if (hum > 90) hum = 90;
String simData = "BLE:TEMP:" + String(temp, 1) + ":HUM:" + String(hum);
Serial.print("Simulated BLE data: ");
Serial.println(simData);
parseBLE(simData);
}
void parseBLE(String data) {
// Формат: BLE:TEMP:23.5:HUM:65
if (data.startsWith("BLE:TEMP:")) {
int humIndex = data.indexOf(":HUM:");
if (humIndex > 0) {
String tempStr = data.substring(9, humIndex);
temperature = tempStr.toFloat();
String humStr = data.substring(humIndex + 5);
humidity = humStr.toInt();
// Вывод на LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temperature:");
lcd.setCursor(0, 1);
lcd.print(temperature, 1);
lcd.print(" C");
lcd.setCursor(0, 2);
lcd.print("Humidity:");
lcd.setCursor(0, 3);
lcd.print(humidity);
lcd.print(" %");
Serial.println(">>> BLE data parsed and displayed");
}
}
}