#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// GPIOs where the NTC thermistors are connected
const int ntcPins[4] = {32, 33, 34, 35};
// Button pins
const int buttonUpPin = 12;
const int buttonDownPin = 13;
const int buttonOkayPin = 14;
// WiFi credentials
struct WiFiNetwork {
const char* ssid;
const char* password;
};
WiFiNetwork wifiNetworks[] = {
{"Wokwi-GUEST", ""},
{"Network1", "password1"},
{"Network2", "password2"},
{"Network3", "password3"}
};
const int wifiNetworkCount = sizeof(wifiNetworks) / sizeof(WiFiNetwork);
int selectedNetworkIndex = 0;
// Google Sheets API details
const char* google_script_id = "AKfycbzqP-j1L4cLd2TkbbbYWMGUI7_q09IZqja56CQ9RQrjCrRYBax08MNN2u6101fmSKAPSA";
// Constants for the NTC thermistor and resistor
const float nominalResistance = 10000; // 10kΩ resistor
const float nominalTemperature = 25; // Nominal temperature for the thermistor
const float bCoefficient = 3950; // Beta coefficient of the thermistor
const float seriesResistor = 10000; // Value of the series resistor
// ILI9341 display settings
#define TFT_CS 15
#define TFT_RST 4
#define TFT_DC 2
Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// Timing variables
unsigned long previousMillis = 0;
const long interval = 10000; // Interval for sending data to Google Sheets (10 seconds)
// Menu variables
enum MenuState { MAIN_MENU, TEMPERATURE_MENU, WIFI_SETTINGS_MENU, WIFI_CONNECTING_MENU, WIFI_STATUS_MENU };
MenuState menuState = MAIN_MENU;
int menuIndex = 0;
const int menuItems = 2;
// Track WiFi connection time
unsigned long wifiConnectedTime = 0;
// Logging control
bool loggingEnabled = false;
void setup() {
// Start the Serial Monitor
Serial.begin(115200);
// Initialize ILI9341 display
display.begin();
display.setRotation(1);
display.fillScreen(ILI9341_BLACK);
display.setTextColor(ILI9341_WHITE);
display.setTextSize(2);
delay(2000);
// Initialize buttons
pinMode(buttonUpPin, INPUT_PULLUP);
pinMode(buttonDownPin, INPUT_PULLUP);
pinMode(buttonOkayPin, INPUT_PULLUP);
}
void loop() {
// Check button states
if (digitalRead(buttonUpPin) == LOW) {
if (menuState == TEMPERATURE_MENU) {
menuState = MAIN_MENU;
loggingEnabled = false; // Stop logging when exiting menu
} else if (menuState == WIFI_SETTINGS_MENU) {
selectedNetworkIndex = (selectedNetworkIndex > 0) ? selectedNetworkIndex - 1 : wifiNetworkCount - 1;
} else {
menuIndex = (menuIndex > 0) ? menuIndex - 1 : menuItems - 1;
}
delay(200); // Debounce delay
}
if (digitalRead(buttonDownPin) == LOW) {
if (menuState == TEMPERATURE_MENU) {
menuState = MAIN_MENU;
loggingEnabled = false; // Stop logging when exiting menu
} else if (menuState == WIFI_SETTINGS_MENU) {
selectedNetworkIndex = (selectedNetworkIndex < wifiNetworkCount - 1) ? selectedNetworkIndex + 1 : 0;
} else {
menuIndex = (menuIndex < menuItems - 1) ? menuIndex + 1 : 0;
}
delay(200); // Debounce delay
}
if (digitalRead(buttonOkayPin) == LOW) {
if (menuState == TEMPERATURE_MENU) {
loggingEnabled = !loggingEnabled; // Toggle logging state
} else if (menuState == WIFI_SETTINGS_MENU) {
menuState = WIFI_CONNECTING_MENU;
connectToWiFi(wifiNetworks[selectedNetworkIndex].ssid, wifiNetworks[selectedNetworkIndex].password);
} else {
switch (menuIndex) {
case 0:
menuState = TEMPERATURE_MENU;
break;
case 1:
menuState = WIFI_SETTINGS_MENU;
break;
}
}
delay(200); // Debounce delay
}
// Update the display based on the current menu state
switch (menuState) {
case MAIN_MENU:
displayMainMenu();
break;
case TEMPERATURE_MENU:
displayTemperatureMenu();
break;
case WIFI_SETTINGS_MENU:
displayWiFiSettingsMenu();
break;
case WIFI_CONNECTING_MENU:
displayWiFiConnectingMenu();
break;
case WIFI_STATUS_MENU:
displayWiFiStatusMenu();
break;
}
// Handle timing for sending data to Google Sheets
if (loggingEnabled) {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Prepare the data to be sent
String data = prepareData();
// Send data to Google Sheets
sendToGoogleSheets(data);
}
}
// Update WiFi status indicator
updateWiFiStatus();
}
void connectToWiFi(const char* ssid, const char* password) {
WiFi.begin(ssid, password);
unsigned long startAttemptTime = millis();
// Attempt to connect for 10 seconds
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
delay(500);
Serial.print(".");
}
display.fillScreen(ILI9341_BLACK);
display.setTextSize(2);
display.setCursor(0, 0);
if (WiFi.status() == WL_CONNECTED) {
wifiConnectedTime = millis();
Serial.println("Connected to WiFi");
display.println("Connected to WiFi");
} else {
Serial.println("Failed to connect to WiFi");
display.println("Failed to connect to WiFi");
}
delay(2000); // Show the connection status for 2 seconds
menuState = MAIN_MENU; // Return to main menu after showing connection status
}
String prepareData() {
String data = "timestamp=" + String(millis()) + "&";
for (int i = 0; i < 4; i++) {
float temperatureC = readTemperature(ntcPins[i]);
if (isnan(temperatureC)) {
Serial.print("Error: Could not read temperature data from sensor ");
Serial.println(i + 1);
data += "sensor" + String(i + 1) + "=Error&";
} else {
data += "sensor" + String(i + 1) + "=" + String(temperatureC) + "&";
}
}
// Remove the last '&'
data.remove(data.length() - 1);
return data;
}
float readTemperature(int pin) {
int adcValue = analogRead(pin);
float resistance = seriesResistor / ((4095.0 / adcValue) - 1);
float steinhart;
steinhart = resistance / nominalResistance; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= bCoefficient; // 1/B * ln(R/Ro)
steinhart += 1.0 / (nominalTemperature + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // Convert to Celsius
return steinhart;
}
void displayMainMenu() {
display.fillScreen(ILI9341_BLACK);
display.setTextSize(2);
display.setCursor(0, 0);
display.println("Main Menu");
display.setCursor(0, 40);
display.setTextColor(menuIndex == 0 ? ILI9341_BLACK : ILI9341_WHITE, menuIndex == 0 ? ILI9341_WHITE : ILI9341_BLACK);
display.println("1. Temperatures");
display.setCursor(0, 80);
display.setTextColor(menuIndex == 1 ? ILI9341_BLACK : ILI9341_WHITE, menuIndex == 1 ? ILI9341_WHITE : ILI9341_BLACK);
display.println("2. WiFi Settings");
}
void displayTemperatureMenu() {
display.fillScreen(ILI9341_BLACK);
display.setTextSize(2);
display.setCursor(0, 0);
display.println("Temperatures");
display.setTextSize(1);
for (int i = 0; i < 4; i++) {
float temperatureC = readTemperature(ntcPins[i]);
display.setCursor(0, 30 + (i * 20));
display.print("Sensor ");
display.print(i + 1);
display.print(": ");
if (isnan(temperatureC)) {
display.println("Error");
} else {
display.print(temperatureC);
display.println(" C");
}
}
// Indicate logging status
display.setCursor(0, 120);
display.setTextSize(2);
display.setTextColor(loggingEnabled ? ILI9341_WHITE : ILI9341_BLACK, loggingEnabled ? ILI9341_BLACK : ILI9341_WHITE);
display.print(loggingEnabled ? "Logging: ON" : "Logging: OFF");
}
void displayWiFiSettingsMenu() {
display.fillScreen(ILI9341_BLACK);
display.setTextSize(2);
display.setCursor(0, 0);
display.println("WiFi Settings");
display.setTextSize(1);
for (int i = 0; i < wifiNetworkCount; i++) {
display.setCursor(0, 30 + (i * 20));
display.setTextColor(i == selectedNetworkIndex ? ILI9341_BLACK : ILI9341_WHITE, i == selectedNetworkIndex ? ILI9341_WHITE : ILI9341_BLACK);
display.println(wifiNetworks[i].ssid);
}
}
void displayWiFiConnectingMenu() {
display.fillScreen(ILI9341_BLACK);
display.setTextSize(2);
display.setCursor(0, 0);
display.print("Connecting to ");
display.println(wifiNetworks[selectedNetworkIndex].ssid);
}
void displayWiFiStatusMenu() {
display.fillScreen(ILI9341_BLACK);
display.setTextSize(2);
display.setCursor(0, 0);
display.println("WiFi Status");
display.setTextSize(1);
display.setCursor(0, 30);
display.print("SSID: ");
display.println(WiFi.SSID());
display.setCursor(0, 50);
display.print("Signal: ");
int32_t rssi = WiFi.RSSI();
display.print(rssi);
display.println(" dBm");
unsigned long connectedTime = (millis() - wifiConnectedTime) / 1000;
display.setCursor(0, 70);
display.print("Connected for: ");
display.print(connectedTime);
display.println(" s");
// Check for back button
if (digitalRead(buttonOkayPin) == LOW) {
menuState = MAIN_MENU;
delay(200); // Debounce delay
}
}
void updateWiFiStatus() {
// Draw a small dot indicator for WiFi status
display.fillCircle(300, 10, 5, (WiFi.status() == WL_CONNECTED) ? ILI9341_GREEN : ILI9341_RED);
}
void sendToGoogleSheets(const String& data) {
WiFiClientSecure client;
HTTPClient http;
client.setInsecure();
String url = String("https://script.google.com/macros/s/") + google_script_id + "/exec?" + data;
http.begin(client, url);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.println("Data sent successfully");
} else {
Serial.println("Error in sending data: " + String(httpCode));
}
http.end();
}