#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Stepper.h>
#include <TinyGPS++.h>
#include <HardwareSerial.h>
// Thông tin kết nối Wi-Fi
#define ssid "Wokwi-GUEST"
#define password ""
// Thông tin MQTT
const char* mqtt_server = "test.mosquitto.org";
const int mqtt_port = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
// --for button--//
#define BUTTON1_PIN 35 // Chân kết nối với nút bấm 1
#define PRESS_TIME_REQUIRED 100 // Thời gian nhấn cần thiết (milliseconds)
bool button1_status = false; // Trạng thái nút bấm 1: false = Tắt, true = Bật
// Biến để quản lý thời gian nhấn và trạng thái
unsigned long press_start_time1 = 0;
bool button1_pressed = false;
void handleButton1() {
int reading = digitalRead(BUTTON1_PIN);
if (reading == HIGH) { // Nếu nút bấm 1 đang được nhấn
if (!button1_pressed) { // Nếu chưa bắt đầu đếm thời gian nhấn
press_start_time1 = millis(); // Lưu thời gian bắt đầu nhấn
button1_pressed = true; // Đánh dấu rằng nút đang được nhấn
}
} else { // Nếu nút bấm 1 được thả
if (button1_pressed) { // Nếu đã bắt đầu đếm thời gian nhấn và đã thả nút
unsigned long press_duration = millis() - press_start_time1; // Tính thời gian nhấn
if (press_duration >= PRESS_TIME_REQUIRED) {
// Nếu thời gian nhấn >= PRESS_TIME_REQUIRED
button1_status = !button1_status; // Chuyển đổi trạng thái
// Push trạng thái đã thay đổi lên mqtt
String res = button1_status ? "true" : "false";
char msg[25];
res.toCharArray(msg, sizeof(msg));
client.publish("22CLC06SmartBracelet/send_music", msg);
}
// Reset trạng thái nhấn
button1_pressed = false;
press_start_time1 = 0;
}
}
}
// -- end button--//
//-- neopixel--//
bool neopixel_status = false;
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define NEOPIXEL_PIN 25 // Pin kết nối với NeoPixel
#define LED_COUNT 16 // Số lượng LED trong dải
#define BRIGHTNESS 250 // Độ sáng ban đầu (0-255)
// Khai báo đối tượng NeoPixel
Adafruit_NeoPixel strip(LED_COUNT, NEOPIXEL_PIN, NEO_RGB + NEO_KHZ800);
// Hàm thực hiện chế độ mode 0
void turnOffNeoPixel() {
strip.clear(); // Tắt tất cả các LED
strip.show(); // Cập nhật trạng thái
}
void neopixel() {
if(neopixel_status == false)
{
turnOffNeoPixel();
return;
}
// Chuỗi các colorWipe với màu sắc và độ trễ khác nhau
colorWipe(strip.Color(255, 0, 0), 50); // Đỏ (sáng)
colorWipe(strip.Color( 0, 255, 0), 50); // Xanh lá (sáng)
colorWipe(strip.Color( 0, 0, 255), 50); // Xanh dương (sáng)
}
// Hàm colorWipe: Chiếu màu lên dải LED từng pixel một
void colorWipe(uint32_t color, int wait) {
for(int i = 0; i < strip.numPixels(); i++) { // Duyệt qua từng pixel
strip.setPixelColor(i, color); // Đặt màu cho pixel hiện tại
strip.show(); // Cập nhật dải LED
delay(wait); // Chờ một khoảng thời gian
}
}
//-- end neo pixel--
const int stepsPerRevolution = 2048; // change this to fit the number of steps per revolution
// Khởi tạo LCD tại địa chỉ 0x27 với kích thước 16x2
LiquidCrystal_I2C LCD(0x27, 16, 2);
// Khai báo chân
const int DHT_PIN =13;
#define DHTTYPE DHT22
//gps
#define RXD2 2
#define TXD2 15
#define GPS_BAUDRATE 9600 // The default baudrate of NEO-6M is 9600
TinyGPSPlus gps; // the TinyGPS++ object
HardwareSerial ss(1); // Use UART2 for GPS
// vibrate
bool vibrate_status = false;
#define IN1 32
#define IN2 5
#define IN3 19
#define IN4 33
// initialize the stepper library
Stepper myStepper(stepsPerRevolution, IN1, IN3, IN2, IN4);
const int buzzer_pin = 17;
const int red_pin = 0;
const int green_pin = 14;
const int blue_pin = 12;
bool buzzer_status = false;
const int light_pin = 4;
//rain-sensor
#define RAIN_ANALOG 34
#define RAIN_DIGITAL 16
//DHT
DHT dht(DHT_PIN, DHTTYPE);
// Biến lưu trữ giá trị trước đó để kiểm tra sự thay đổi
int lastTemp = 0; // Lưu trữ nhiệt độ dưới dạng int
int lastHum = 0; // Lưu trữ độ ẩm dưới dạng int
String lastLight = "";
String lastWeather = "";
String lastLocation = "";
// Hàm kết nối Wi-Fi
void initWiFi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
// Hàm kiểm tra có sự thay đổi về dữ liệu thu nhận từ cảm biến
void do_vibration()
{
if (vibrate_status == false) return;
for (int i = 1; i<= 20; i++)
{
myStepper.step(10); // Di chuyển 20 bước tiến
delay(20); // Ngắt quãng ngắn giữa các rung
// Di chuyển cùng số bước về hướng ngược lại
myStepper.step(-10); // Di chuyển 20 bước lùi
delay(20);
}
}
void updateSensorData() {
// Cập nhật giá trị của các cảm biến
bool isChanged = false; // Cờ để kiểm tra sự thay đổi
String light;
if (! (digitalRead(light_pin)))
{
light = "trời sáng";
}
else light = "trời tối";
//Giả lập tạm
String location;
float latitude, longitude;
if (gps.location.isValid()) { // Check if GPS location
latitude = gps.location.lat();
longitude = gps.location.lng();
} else {
latitude = 23.05;
longitude = 23.03;
}
location = "latitude: " + String(latitude, 6) + ", longitude: " + String(longitude, 6);
int temperature = dht.readTemperature();
int humidity = dht.readHumidity();
if (temperature < 5 || temperature > 45)
{
tone(buzzer_pin, 192);
myStepper.step(20);
myStepper.step(-20);
// String res = "true" ;
// char msg[25];
// res.toCharArray(msg, sizeof(msg));
// client.publish("22CLC06SmartBracelet/send_music", msg);
// client.publish("22CLC06SmartBracelet/send_vibration", msg);
// button1_status = true;
}
String weather;
Serial.println(analogRead(RAIN_ANALOG));
if(digitalRead(RAIN_DIGITAL))
{
weather = "mưa";
}
else
weather = "không mưa";
// Kiểm tra sự thay đổi từng giá trị
if (temperature != lastTemp || humidity != lastHum)
{
displayLCD(temperature, humidity);
isChanged = true;
}
if (light != lastLight || humidity != lastHum || weather != lastWeather || location != lastLocation)
{
isChanged = true;
}
lastLight = light;
lastHum = humidity;
lastTemp = temperature;
lastWeather = weather;
lastLocation = location;
// Nếu có sự thay đổi, tạo JSON và publish
if (isChanged) {
// Tạo tài liệu JSON
StaticJsonDocument<256> jsonDoc;
jsonDoc["Light"] = light;
jsonDoc["Temperature"] = temperature;
jsonDoc["Humidity"] = humidity;
jsonDoc["Weather"] = weather;
jsonDoc["GPS"] = location;
// Chuyển đổi JSON thành chuỗi
char msg[256];
serializeJson(jsonDoc, msg, sizeof(msg));
// Publish chuỗi JSON lên MQTT
if (client.publish("22CLC06SmartBracelet/get", msg)) {
Serial.println("Published: ");
Serial.println(msg);
} else {
Serial.println("Failed to publish message");
}
}
}
// Hàm hiển thị nhiệt độ và độ ẩm trên LCD
void displayLCD(int temperature, int humidity) {
char tempBuffer[16]; // Đảm bảo buffer đủ lớn
snprintf(tempBuffer, sizeof(tempBuffer), "Temp: %dC ", temperature);
LCD.setCursor(0, 0);
LCD.print(tempBuffer);
// Cập nhật màn hình LCD với độ ẩm
char humBuffer[16]; // Đảm bảo buffer đủ lớn
snprintf(humBuffer, sizeof(humBuffer), "Humidity: %d%% ", humidity);
LCD.setCursor(0, 1);
LCD.print(humBuffer);
}
// Hàm xử lý callback MQTT
void mqttCallback(char* topic, byte* payload, unsigned int length) {
Serial.println(topic);
payload[length] = '\0'; // Đảm bảo chuỗi kết thúc đúng cách
Serial.println((char*)payload);
if(strcmp((char*)payload, "music on") == 0)
{
buzzer_status = true;
button1_status = true;
//tone(buzzer_pin, 120,5000);
}
else if (strcmp((char*)payload, "music off") == 0)
{
buzzer_status = false;
button1_status = false;
noTone(buzzer_pin);
}
else if (strcmp((char*)payload, "vibration on") == 0)
{
vibrate_status = true;
}
else if (strcmp((char*)payload, "vibration off") == 0)
{
vibrate_status = false;
}
else if (strcmp((char*)payload, "Neopixel on") == 0)
{
neopixel_status = true;
}
else if (strcmp((char*)payload, "Neopixel off") == 0)
{
neopixel_status = false;
}
else if (strcmp((char*)payload, "Led Red") == 0)
{
displayRed();
}
else if (strcmp((char*)payload, "Led Green") == 0)
{
displayGreen();
}
else if (strcmp((char*)payload, "Led Blue") == 0)
{
displayBlue();
}
else if (strcmp((char*)payload, "on backlight") == 0)
{
LCD.backlight();
}
else if (strcmp((char*)payload, "off backlight") == 0)
{
LCD.noBacklight();
}
}
// Hàm kết nối tới server MQTT
void connectMqttServer() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("22CLC06-22127476")) {
Serial.println("Connected to MQTT server");
client.subscribe("22CLC06SmartBracelet/receive_music"); // Subscribe to topic
client.subscribe("22CLC06SmartBracelet/receive_led");
client.subscribe("22CLC06SmartBracelet/receive_vibration");
client.subscribe("22CLC06SmartBracelet/receive_neopixel");
client.subscribe("22CLC06SmartBracelet/receive_backlight");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void setup() {
// Khởi tạo client MQTT và callback
client.setServer(mqtt_server, mqtt_port);
client.setCallback(mqttCallback);
pinMode(BUTTON1_PIN, INPUT); // Thiết lập chân nút bấm 1 làm INPUT
// set up neopixel //
// Cấu hình cho Adafruit Trinket 5V 16 MHz
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// Kết thúc phần code dành cho Trinket
strip.begin(); // Khởi tạo NeoPixel strip
strip.show(); // Tắt tất cả LED
strip.setBrightness(BRIGHTNESS); // Đặt độ sáng
// end neopixel
Serial.begin(115200);
dht.begin();
pinMode(red_pin, OUTPUT);
pinMode(green_pin, OUTPUT);
pinMode(blue_pin, OUTPUT);
pinMode(buzzer_pin, OUTPUT);
pinMode(light_pin, INPUT);
// for gps
ss.begin(GPS_BAUDRATE, SERIAL_8N1, RXD2, TXD2);
//
myStepper.setSpeed(90);
//
pinMode(RAIN_ANALOG, INPUT);
pinMode(RAIN_DIGITAL, INPUT);
analogReadResolution(10);
// Kết nối Wi-Fi trong setup
initWiFi();
// Khởi tạo và bật đèn nền của LCD
LCD.init();
LCD.noBacklight();
// Hiển thị thông báo khởi động
LCD.setCursor(0, 0);
LCD.print("Starting...");
LCD.setCursor(0, 1);
LCD.print("Initializing...");
delay(2000); // Hiển thị thông báo trong 2 giây
// Kết nối MQTT
connectMqttServer();
}
void loop() {
if (!client.connected())
{
connectMqttServer();
}
client.loop();
handleButton1(); // Xử lý nút bấm 1
updateSensorData();
do_vibration();
neopixel();
music();
// Gửi dữ liệu lên MQTT (nhiệt độ và độ ẩm dưới dạng int)
// char msg[50];
// int tmp = int(data.temperature);
// snprintf(msg, 50, "%d", tmp);
// client.publish("/22127476/Temperature", msg);
// // Chờ 1 giây trước khi đọc lại
// delay(5000);
}