Blog

  • Using a flow sensor with esp32

    #include <WiFi.h>
    #include <PubSubClient.h>
    #include <time.h>  // ไลบรารีสำหรับดึงเวลาจาก NTP
    #include "esp_adc_cal.h"
    
    extern "C" {
      uint8_t temprature_sens_read();
    }
    
    // WiFi Credentials
    const char *ssid = "xxx";  // เปลี่ยนเป็นชื่อ WiFi ของคุณ
    const char *password = "xxx";   // เปลี่ยนเป็นรหัสผ่าน WiFi ของคุณ
    
    // MQTT Broker Settings
    const char *mqtt_server = "xxx"; // เปลี่ยนเป็น mqtt server ของคุณ
    const int mqtt_port = 1883;
    const char *mqtt_user = "";
    const char *mqtt_pass = "";
    
    // Sensor Settings
    const int SENSOR_PIN = 4; // GPIO4 สำหรับเชื่อมต่อ flow sensor
    volatile long pulse;
    
    //Restart
    unsigned long startMillis = 0;  // เวลาเริ่มต้นสำหรับจับเวลา
    const unsigned long rebootInterval = 300000; // 5 นาที = 300,000 ms ตั้งเวลารีบูต MCU
    
    const char *DISPENSOR_ID = "xxx"; // ตั้งชื่อ ID ของอุปกรณ์ของคุณ
    
    #define SEND_LED 25 // ขาที่ต่อ สำหรับ led แสดงการส่งข่้อมูล
    #define WIFI_LED 13 // ขาที่ต่อ สำหรับ led แสดงการเชื่อมต่อ wifi
    #define MQTT_LED 14 // ขาที่ต่อ สำหรับ led แสดงการเชื่อมต่อ mqtt
    
    WiFiClient espClient;
    PubSubClient client(espClient);
    unsigned long lastMsg = 0;
    #define MSG_BUFFER_SIZE (256)
    char msg[MSG_BUFFER_SIZE];
    
    // ตั้งค่า Timezone เป็น GMT+7 (ประเทศไทย)
    const char* ntpServer = "pool.ntp.org";
    const long  gmtOffset_sec = 7 * 3600; // UTC+7
    const int   daylightOffset_sec = 0;
    
    void IRAM_ATTR increase() {
      pulse++;
    }
    
    // ฟังก์ชันเชื่อมต่อ WiFi
    void setup_wifi() {
      Serial.print("Connecting to WiFi: ");
      Serial.println(ssid);
      digitalWrite(WIFI_LED, LOW);
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
    
      int attempt = 0;
      while (WiFi.status() != WL_CONNECTED && attempt < 20) {
        delay(1000);
        Serial.print(".");
        attempt++;
      }
    
      if (WiFi.status() == WL_CONNECTED) {
        Serial.println("\nWiFi Connected!");
        Serial.print("IP Address: ");
        Serial.println(WiFi.localIP());
        Serial.print("MAC Address: ");
        Serial.println(WiFi.macAddress());
        Serial.print("WiFi Status: ");
        Serial.println(WiFi.status());
        digitalWrite(WIFI_LED, HIGH);  // ติด LED ที่ IO1 เมื่อเชื่อม WiFi สำเร็จ
        // ตั้งค่า NTP
        configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
        delay(2000); //ก่อน MQTT 2 วิ
      } else {
        Serial.println("\nWiFi Connection Failed!");
        digitalWrite(WIFI_LED, LOW);  // ดับ LED ที่ IO1 เมื่อเชื่อม WiFi ไม่สำเร็จ
      }
    }
    
    // ฟังก์ชัน Callback เมื่อได้รับ MQTT Message
    void callback(char *topic, byte *payload, unsigned int length) {
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");
      
      for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
      }
      Serial.println();
    
      // เช็คค่าจาก Payload (0 หรือ 1) เพื่อควบคุม LED
      if ((char)payload[0] == '1') {
        digitalWrite(SEND_LED, LOW);
      } else {
        digitalWrite(SEND_LED, HIGH);
        digitalWrite(MQTT_LED, LOW);//ดับ mqtt
      }
    }
    
    // ฟังก์ชันเชื่อมต่อ MQTT
    void reconnect() {
      while (!client.connected()) {
        Serial.print("Attempting MQTT connection...");
        String clientId = String(DISPENSOR_ID) + "-" + String(random(0xffff), HEX);
    
        if (client.connect(clientId.c_str(), mqtt_user, mqtt_pass)) {
          Serial.println("Connected to MQTT Broker!");
          digitalWrite(MQTT_LED, HIGH);  // ติด LED ที่ IO3 เมื่อเชื่อมต่อ MQTT ได้
          digitalWrite(WIFI_LED, LOW); // ดับ Wifi-LED
          client.subscribe("KMITL/water");
        } else {
                int retryCount = 0;
                while (!client.connected()) {
                  Serial.print("Failed, rc=");
                  Serial.print(client.state());
                  Serial.println(" Try again in 5 seconds...");
                  delay(2000);
                  retryCount++;
    
                  if (retryCount >= 5) {
                    Serial.println("Failed to connect 5 times. Restarting...");
                    digitalWrite(MQTT_LED, LOW);
                    ESP.restart();
                  }
                }
        }
      }
    }
    
    // ฟังก์ชันดึงเวลาปัจจุบัน
    String getTimeString() {
      struct tm timeinfo;
      if (!getLocalTime(&timeinfo)) {
        Serial.println("Failed to obtain time");
        return "N/A";
      }
      
      char timeStr[20];
      strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo);
      return String(timeStr);
    }
    
    void setup() {
      pinMode(SEND_LED, OUTPUT);
      pinMode(WIFI_LED, OUTPUT);  
      pinMode(MQTT_LED, OUTPUT);  
      Serial.begin(115200);
    
      pinMode(SENSOR_PIN, INPUT);
      attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), increase, RISING);
    
      setup_wifi();
      client.setServer(mqtt_server, mqtt_port);
      client.setCallback(callback);
    
      startMillis = millis();
    }
    
    void loop() {
      if (!client.connected()) {
        reconnect();
      }
      client.loop();
    
      unsigned long now = millis();
      if (now - lastMsg > 20000) { // ส่งข้อมูลทุก 30 วินาที / หักไฟกระพริบ 10 วิ
        lastMsg = now;
        float volume = pulse * 1.25;
        pulse = 0;
    
        // รับเวลาปัจจุบัน
        String timestamp = getTimeString();
    
        Serial.print("Volume: ");
        Serial.print(volume);
        Serial.println(" ml");
    
      uint8_t temp_farenheit = temprature_sens_read();
      float temp_celsius = ( temp_farenheit - 32 ) / 1.8;
      
      Serial.print("Internal Temperature (°C): ");
      Serial.println(temp_celsius);
    
        // ส่งข้อมูล MQTT พร้อม Timestamp
          snprintf(msg, MSG_BUFFER_SIZE, "{\"id\":\"%s\",\"volume\":%.2f,\"timestamp\":\"%s\",\"ip\":\"%s\",\"Gateway ip\":\"%s\",\"MCU\":%.2f}", 
          DISPENSOR_ID, volume, timestamp.c_str(), WiFi.localIP().toString().c_str(), WiFi.gatewayIP().toString().c_str(), temp_celsius);
    
        Serial.println(msg);
        client.publish("KMITL/water", msg);
        //ส่งข้อมูลไฟกระพริบ 50 ครั้ง 10 วินาที 10,000/50/2
        for (int i = 0; i < 50; i++) {
          digitalWrite(SEND_LED, LOW);
          delay(100);
          digitalWrite(SEND_LED, HIGH);
          delay(100);
        }
      }
    
        // ตรวจสอบว่าครบ 5 นาทีหรือยัง
        if (millis() - startMillis >= rebootInterval) {
        Serial.println("Rebooting MCU...");
        delay(100);  // หน่วงเล็กน้อยให้ข้อความส่งออกก่อน
        ESP.restart();  // สั่งให้รีบูต
      }
    }