///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The data read from the Aht30 sensor is sent to Google Apps Script to run the function to send the data to be written to Google Sheet.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//https://docs.google.com/spreadsheets/d/1fD02864bB4h2RF_ZBDSY9PC6rvvo82XcJ_R0wZY08QM/edit?gid=0#gid=0
// Spreadsheet ID คือส่วนของ Url ที่ได้มาจากช่อง Url ของ Google Sheet โดยตัดช่วงมาตั้งแต่
//หลัง https://docs.google.com/spreadsheets/d/
//ถึงก่อน /edit?gid=0#gid=0
//จาก Url ด้านบนนี้ Spreadsheet ID ก็คือ 1fD02864bB4h2RF_ZBDSY9PC6rvvo82XcJ_R0wZY08QM
//นำไปใช้ในโค้ด Apps Script
//--------- ชื่อชีต Esp32 & AHT30 -----------
//--------- ชื่อสคริปต์ Esp32_Aht30 ----------
//---------- Apps Script Code ------------
/*
function doGet(e) {
Logger.log( JSON.stringify(e) );
var result = 'Ok';
if (e.parameter == 'undefined') {
result = 'No Parameters';
}
else {
var sheet_id = '1fD02864bB4h2RF_ZBDSY9PC6rvvo82XcJ_R0wZY08QM'; //*Spreadsheet ID
var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet();
var newRow = sheet.getLastRow() + 1;
var rowData = [];
var Curr_Date = new Date();
rowData[0] = Curr_Date; // Date in column A
var Curr_Time = Utilities.formatDate(Curr_Date, "Asia/Bangkok", 'HH:mm:ss');
rowData[1] = Curr_Time; // Time in column B
for (var param in e.parameter) {
Logger.log('In for loop, param=' + param);
var value = stripQuotes(e.parameter[param]);
Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'temp':
rowData[2] = value; // Temperature in column C
result = 'temp Written on column C';
break;
case 'humi':
rowData[3] = value; // Temperature in column D
result = 'humidity Written on column D';
break;
}
}
Logger.log(JSON.stringify(rowData));
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
return ContentService.createTextOutput(result);
}
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}
*/
//----------- Arduino Code -------------
// -----------------------------------------------------------
// AHT30 + NTP Time + Google Sheet (ESP32/ESP8266)
// พร้อมคอมเมนต์อธิบายเข้าใจง่ายทุกบรรทัด
// -----------------------------------------------------------
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#elif defined(ESP32)
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#endif
#include <Wire.h>
#include <Adafruit_AHTX0.h> // ไลบรารีสำหรับเซ็นเซอร์ AHT30
#include "time.h" // ไลบรารีสำหรับดึงเวลาจาก NTP Server
// -----------------------------------------------------------
// NTP Server ตั้งค่า (ใช้เวลาไทย +7)
// -----------------------------------------------------------
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 7 * 3600; // GMT+7 (เวลาไทย)
const int daylightOffset_sec = 0; // ไม่ใช้ Daylight Saving
// -----------------------------------------------------------
Adafruit_AHTX0 aht; // สร้างอ็อบเจกต์สำหรับ AHT30
#if defined(ESP8266)
ESP8266WiFiMulti WiFiMulti; // สำหรับเชื่อม WiFi แบบรองรับหลาย AP
#elif defined(ESP32)
WiFiMulti WiFiMulti;
#endif
#define WAIT_MINUTES 5 // กำหนดเวลารอระหว่างรอบ (หน่วย: นาที)
// URL Google Apps Script ที่ใช้เชื่อมต่อ Google Sheet
const char SCRIPT_URL[] PROGMEM =
"https://script.google.com/macros/s/AKfycbxeW7ifG_H7KS3rsnW9if76IgEFkIu8Eb_M8OonLMgIs0zsELuCKPaC3x9zREEmSCol/exec";
// -----------------------------------------------------------
// 🔧 getTimeNow()
// อ่านเวลา NTP และแปลงเป็น HH:MM:SS เพื่อแสดงบน Serial Monitor
// -----------------------------------------------------------
String getTimeNow() {
struct tm timeinfo;
// ถ้าอ่าน NTP ไม่ได้
if (!getLocalTime(&timeinfo)) {
return "NTP Error";
}
char buffer[20];
strftime(buffer, sizeof(buffer), "%H:%M:%S", &timeinfo);
return String(buffer);
}
// -----------------------------------------------------------
// 🔧 setup()
// รันครั้งเดียวตอนเปิดเครื่อง
// -----------------------------------------------------------
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println(F("AHT30 Sensor + NTP + Google Apps Script"));
delay(100);
// -------------------------
// เริ่มทำงานกับ AHT30
// -------------------------
if (!aht.begin()) {
Serial.println(F("AHT30 not found! (ตรวจสายไฟ)"));
while (1) delay(10);
}
Serial.println(F("AHT30 OK"));
Serial.println(F("--------------------------------"));
// -------------------------
// เชื่อมต่อ Wi-Fi
// -------------------------
WiFi.mode(WIFI_STA); // ใช้โหมด Station
WiFiMulti.addAP("happy_2.4G", "0816599222"); // ชื่อไวไฟ + รหัส
Serial.print(F("Connecting WiFi"));
while (WiFiMulti.run() != WL_CONNECTED) { // รอจนกว่าจะเชื่อมสำเร็จ
Serial.print(".");
delay(300);
}
Serial.println();
Serial.print(F("IP Address: "));
Serial.println(WiFi.localIP());
// -------------------------
// เริ่มต้นระบบเวลา NTP
// -------------------------
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Serial.println(F("NTP time initialized"));
delay(500);
}
// -----------------------------------------------------------
// 🔧 loop()
// ทำงานซ้ำตลอด (ทุก WAIT_MINUTES นาที)
// -----------------------------------------------------------
void loop() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// ---------------------------------------------------
// อ่านค่าจากเซ็นเซอร์ AHT30
// ---------------------------------------------------
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);
// ---------------------------------------------------
// แสดงผลสวย ๆ บน Serial Monitor
// ---------------------------------------------------
Serial.println();
Serial.println(F("=============================================="));
Serial.println(F(" 📡 AHT30 SENSOR READING"));
Serial.println(F("=============================================="));
Serial.print(F("Time: "));
Serial.println(getTimeNow()); // ⭐ แสดงเวลาจริง NTP
Serial.print(F("Temperature: "));
Serial.print(temp.temperature, 2);
Serial.println(F(" °C"));
Serial.print(F("Humidity: "));
Serial.print(humidity.relative_humidity, 2);
Serial.println(F(" %"));
Serial.println(F("----------------------------------------------"));
Serial.println(F("Sending data to Google Sheet..."));
Serial.println(F("----------------------------------------------"));
// ---------------------------------------------------
// สร้าง URL เพื่อส่งข้อมูลขึ้น Google Sheet
// ---------------------------------------------------
char url[300];
snprintf(url, sizeof(url), "%s?temp=%.2f&humi=%.2f",
FPSTR(SCRIPT_URL),
temp.temperature,
humidity.relative_humidity);
#if defined(ESP8266)
WiFiClientSecure client;
client.setInsecure(); // ESP8266 ต้องปิดการตรวจ SSL
http.begin(client, url);
#else
http.begin(url); // ESP32 ใช้ได้ทันที
#endif
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
// ---------------------------------------------------
// ส่งข้อมูลแบบ GET
// ---------------------------------------------------
int httpCode = http.GET();
if (httpCode > 0) {
Serial.println(httpCode); // แสดงรหัสตอบกลับ
Serial.println(http.getString()); // แสดงข้อความตอบกลับ
} else {
Serial.println(F("Data transmission failed."));
}
http.end();
}
else {
Serial.println(F("WiFi lost! Reconnecting..."));
WiFiMulti.run(); // สั่งให้ลองเชื่อมใหม่อัตโนมัติ
}
// ---------------------------------------------------
// หน่วงเวลา WAIT_MINUTES นาที ก่อนส่งรอบต่อไป
// ---------------------------------------------------
Serial.print(F("Wait "));
Serial.print(WAIT_MINUTES);
Serial.println(F(" minute to resend..."));
delay(WAIT_MINUTES * 60000ULL); // แปลงนาทีเป็นมิลลิวินาที
}