#include <Wire.h>
#include <Adafruit_MLX90614.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <DHT.h>
// Pin Definitions
#define DHTPIN 2
#define DHTTYPE DHT11
#define laser 12
#define buttonPin 7
#define chargingPin 6
const int batteryPin = A0;
const float referenceVoltage = 5.0; // Reference voltage of the Arduino (adjust if necessary)
// Constants
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define MIN_VOLTAGE 3.3
#define MAX_VOLTAGE 4.1
const float emissivity = 0.95;
const float calibrationOffsetObject = 6.4;
// Flags and Intervals
const int blinkInterval = 100;
bool isCelsius = true;
bool isBlinkVisible = true;
unsigned long lastBlinkMillis = 0;
// Objects
DHT dht(DHTPIN, DHTTYPE);
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Debounce variables
unsigned long lastButtonPress = 0;
unsigned long debounceDelay = 10;
// Check if charging status has changed
static bool wasCharging = false;
void setup()
{
Serial.begin(9600);
Wire.begin();
dht.begin();
mlx.begin();
pinMode(buttonPin, INPUT_PULLUP);
pinMode(chargingPin, INPUT);
pinMode(laser, OUTPUT);
digitalWrite(laser, LOW);
displaySetup();
Serial.println("Temperature Sensor MLX90614");
displayMessage(" Thermometer", "Initializing");
delay(1000);
display.clearDisplay();
}
void displaySetup()
{
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}
void displayMessage(String line1, String line2)
{
// Display a message on the OLED screen
display.clearDisplay();
display.setCursor(25, 15);
display.setTextSize(1);
display.setTextColor(WHITE);
display.println(line1);
display.setCursor(25, 35);
display.setTextSize(1);
display.print(line2);
display.display();
delay(1500);
display.clearDisplay();
}
void drawBatteryIcon(float batteryVoltage)
{
// Map battery voltage to a percentage level
float batteryPercentage = map(batteryVoltage, MIN_VOLTAGE, MAX_VOLTAGE, 0, 100);
batteryPercentage = constrain(batteryPercentage, 0, 100); // Ensure the percentage is within 0-100 range
// Calculate battery width based on the battery percentage
int batteryWidth = map(batteryPercentage, 0, 100, 0, 16);
// Draw battery outline
display.drawRect(SCREEN_WIDTH - 22, 2, 20, 7, SSD1306_WHITE);
display.drawRect(SCREEN_WIDTH - 2, 3, 1, 5, SSD1306_WHITE);
// Fill the battery based on the battery percentage
display.fillRect(SCREEN_WIDTH - 20, 4, batteryWidth, 3, SSD1306_WHITE);
display.setCursor(SCREEN_WIDTH - 50, 1);
display.setTextSize(.5);
if (batteryPercentage >= 100)
{
// Display "Full Charge" when battery level is 99% or higher
display.setCursor(0, 0);
display.print("Full Charge");
}
else
{
// Display battery level when not fully charged
float batteryPercentage = map(batteryVoltage * 100, MIN_VOLTAGE * 100, MAX_VOLTAGE * 100, 0, 100);
batteryPercentage = constrain(batteryPercentage, 0, 100);
Serial.println(batteryPercentage); // Print the calculated percentage to Serial Monitor
display.print((int)batteryPercentage);
display.print("%");
// Calculate battery width based on the battery percentage
int batteryWidth = map(batteryPercentage, 0, 100, 0, 16);
// Fill the battery based on the calculated width
display.fillRect(SCREEN_WIDTH - 20, 4, batteryWidth, 3, SSD1306_WHITE);
// Check charging status and display indicator
if (digitalRead(chargingPin) == HIGH)
{
display.setCursor(SCREEN_WIDTH - 20, 1);
display.setCursor(0, 0);
display.setTextSize(.5);
display.print("Charging");
}
else
{
// Clear the charging indicator if charging is not detected
display.setCursor(SCREEN_WIDTH - 40, 1);
display.setTextSize(.5);
display.print(" "); // Clear the space reserved for the charging indicator
}
// Battery warning for low charge (below 20%)
if (batteryPercentage <= 20 && digitalRead(chargingPin) == LOW)
{
// Toggle the visibility of the battery icon based on the blink interval
if (millis() - lastBlinkMillis >= blinkInterval)
{
isBlinkVisible = !isBlinkVisible;
lastBlinkMillis = millis();
}
if (isBlinkVisible)
{
// If visible, display low battery warning
display.setCursor(0, 1);
display.setTextSize(.5);
display.print("Low Battery! ");
}
}
}
}
void toggleTemperatureUnit()
{
// Toggle between Celsius and Fahrenheit
isCelsius = !isCelsius;
}
void updateDisplay(float tempObj, float tempAmb, float tempDHT, float humidity, float batteryVoltage)
{
// Update the information on the OLED screen
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// Check if charging status has changed
bool isCharging = digitalRead(chargingPin) == HIGH;
if (isCharging != wasCharging)
{
// Charging status has changed
wasCharging = isCharging;
// If not charging, clear the display
if (!isCharging)
{
display.clearDisplay();
display.display();
}
}
drawBatteryIcon(batteryVoltage);
display.setCursor(0, 25);
display.print("Object Temp: ");
display.print(isCelsius ? tempObj : convertToFahrenheit(tempObj));
display.print(isCelsius ? " C" : " F");
display.setCursor(0, 35);
display.print("Device Temp: ");
display.print(isCelsius ? tempAmb : convertToFahrenheit(tempAmb));
display.print(isCelsius ? " C" : " F");
display.setCursor(0, 45);
display.print("Ambient Temp: ");
display.print(isCelsius ? tempDHT : convertToFahrenheit(tempDHT));
display.print(isCelsius ? " C" : " F");
display.setCursor(0, 55);
display.print("Humidity: ");
display.print(humidity);
display.print(" %");
display.setCursor(95, 10);
display.setTextSize(.5);
display.print(batteryVoltage);
display.print("V");
display.display();
}
float convertToFahrenheit(float celsius)
{
// Convert Celsius to Fahrenheit
return celsius * 9 / 5 + 32;
}
void loop()
{
// Turn on laser
digitalWrite(laser, HIGH);
// Read battery voltage
int rawValue = analogRead(batteryPin);
float batteryVoltage = (rawValue / 1023.0) * referenceVoltage;
// Print raw battery voltage to Serial Monitor
Serial.print("Raw Battery Voltage: ");
Serial.println(batteryVoltage, 2); // Print with 2 decimal places
// Read sensor values
float temperature_object = mlx.readObjectTempC() + calibrationOffsetObject;
float temperature_ambient = mlx.readAmbientTempC();
float humidity = dht.readHumidity();
float temperature_dht = dht.readTemperature();
// Check for button press to toggle temperature units
static bool buttonPressed = false;
if (digitalRead(buttonPin) == LOW && !buttonPressed)
{
toggleTemperatureUnit();
buttonPressed = true;
}
else if (digitalRead(buttonPin) == HIGH)
{
buttonPressed = false;
}
// Update the OLED display
updateDisplay(temperature_object, temperature_ambient, temperature_dht, humidity, batteryVoltage);
delay(1000);
}