Untitled

 avatar
unknown
plain_text
5 months ago
7.5 kB
7
Indexable
#include <OneWire.h> // Library for talking to temp sensors
#include <DallasTemperature.h> // Library for Dallas temp sensors

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h> // Graphics support for OLED
#include <Adafruit_SSD1306.h> // OLED display library

#include <math.h> // Math functions

#define ONE_WIRE_BUS 2 // Pin for OneWire data
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

#define SCREEN_WIDTH 128 // OLED display width
#define SCREEN_HEIGHT 32 // OLED display height
#define OLED_RESET -1 // OLED reset pin (not used)
#define SCREEN_ADDRESS 0x3C // OLED I2C address
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

unsigned long lastTempUpdateTime = 0; // Last time temp updated
float temperature, celsius, fahrenheit; // Temp variables
bool anomalies = false; // Flag for anomaly detection
float baseline = 0; // Baseline temp to compare against
int baselineCounter = 0; // Number of readings for baseline
int sprayPin = 3; // Pin controlling spray mechanism
bool configuring = true; // Flag for baseline config mode
float temperatureReadings[10]; // Store last 10 temp readings
int readingIndex = 0; // Index for temp readings
bool readingsFilled = false; // Flag for when all reading slots filled

void setup() {
  pinMode(sprayPin, OUTPUT); // Set spray pin as output
  Serial.begin(9600); // Start serial comm for debug

  sensors.begin(); // Init temp sensor

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { // Init display
    Serial.println(F("SSD1306 allocation failed")); // Print error if display init fails
    for (;;); // Loop forever if display fails
  }
  display.display(); // Show splash screen
  delay(2000); // Wait 2 secs
  display.clearDisplay(); // Clear splash screen
  display.setTextSize(3); // Set text size for initial screen
  display.setTextColor(SSD1306_WHITE); // Set text color to white
  display.setCursor(10, 0); // Set cursor position for display text
}

void loop() {
  unsigned long currentMillis = millis(); // Get current time in ms

  if (configuring) { // If in baseline config mode
    display.clearDisplay(); // Clear display before showing new text
    display.setTextSize(1); // Smaller text size for config msg
    display.setCursor(0, 0); // Set cursor pos for config msg
    display.print("CONFIGURING..."); // Display config msg
    display.setCursor(0, 20); // Set cursor for second line
    display.print("HANDS OFF"); // Display instructions during setup
    display.display(); // Update display with config msg

    int progress = (baselineCounter * 16) / 10; // Calc progress of config (scaled)
    for (int i = 0; i < progress; i++) { // Loop to show progress bar
      display.setCursor(i * 8, 30); // Set cursor for each progress step
      display.print("%"); // Show progress indicator
    }
    display.display(); // Update display with progress

    if (currentMillis - lastTempUpdateTime >= 1000) { // If 1 sec passed since update
      updateTemperatureReadings(); // Get new temp reading
      baseline += temperature; // Add current temp to baseline total
      baselineCounter++; // Increment baseline counter
      lastTempUpdateTime = currentMillis; // Update last temp time
    }

    if (baselineCounter == 10) { // If 10 readings taken
      baseline /= 10; // Calc avg baseline temp
      Serial.print("Baseline (K): "); // Print baseline temp to serial
      Serial.println(baseline, 2); // Print baseline value w/ 2 decimals
      configuring = false; // End config mode
      display.clearDisplay(); // Clear display after config
    }
  } else { // Normal operation mode
    if (currentMillis - lastTempUpdateTime >= 1000) { // If 1 sec passed since last update
      updateTemperatureReadings(); // Get new temp reading
      for (int i = 9; i > 0; i--) { // Shift readings in array to make room for new one
        temperatureReadings[i] = temperatureReadings[i - 1]; // Move previous reading to next index
      }
      temperatureReadings[0] = temperature; // Store latest temp at start of array
      if (readingIndex < 10) { // If readings array not full
        readingIndex++; // Increment reading index
      } else {
        readingsFilled = true; // Mark readings as filled if all slots used
      }
      lastTempUpdateTime = currentMillis; // Update last temp update time
      checkForAnomalies(); // Check for anomalies in temp readings
    }

    if (anomalies) { // If anomaly detected
      displayAnomalyScreen(); // Show anomaly info on screen
    } else { // If no anomaly
      displayTemperatureScreen(); // Show regular temp info
    }
  }
  delay(100); // Short delay to smooth loop, avoid rapid updates
}

// Function to update temp readings from sensor
void updateTemperatureReadings() {
  sensors.requestTemperatures();  // Request temp from sensor
  celsius = sensors.getTempCByIndex(0); // Get temp in Celsius
  fahrenheit = sensors.getTempFByIndex(0); // Get temp in Fahrenheit
  temperature = celsius + 273.15; // Convert Celsius to Kelvin

  Serial.println(temperature); // Print temp (in Kelvin) for debug
}

// Function to check for anomalies in temp readings vs baseline
void checkForAnomalies() {
  if (readingsFilled) { // Only check if all slots full
    float sum = 0; // Sum of temp readings
    float sumSquares = 0; // Sum of squares of temp readings
    for (int i = 0; i < 10; i++) { // Loop through all readings
      sum += temperatureReadings[i]; // Add each reading to sum
      sumSquares += pow(temperatureReadings[i], 2); // Add square of each reading
    }
    float mean = sum / 10; // Calc mean of readings
    float variance = (sumSquares / 10) - pow(mean, 2); // Calc variance
    float stdDeviation = sqrt(variance); // Calc standard deviation

    if (abs(temperature - baseline) > 2 * stdDeviation && temperature > baseline) { // If temp deviates a lot from baseline
      anomalies = true; // Set anomaly flag
      digitalWrite(sprayPin, 1); // Activate spray
    } else { // If no big deviation
      anomalies = false; // Clear anomaly flag
      digitalWrite(sprayPin, 0); // Deactivate spray
    }
    Serial.print("Anomaly: "); // Print anomaly status
    Serial.println(anomalies ? "True" : "False"); // Print if anomaly detected
  }
}

// Function to display current temp readings on screen
void displayTemperatureScreen() {
  display.clearDisplay(); // Clear display before new info
  display.setTextSize(2); // Set text size for temp info
  display.setCursor(0, 0); // Set cursor for Kelvin info
  display.print("K:"); // Label for Kelvin temp
  display.print(temperature, 2); // Show temp in Kelvin w/ 2 decimals
  display.setCursor(0, 16); // Set cursor for Celsius info
  display.print("C:"); // Label for Celsius temp
  display.print(celsius, 2); // Show temp in Celsius w/ 2 decimals
  display.display(); // Update display with temp info
}

// Function to display anomaly info on screen
void displayAnomalyScreen() {
  display.clearDisplay(); // Clear display before anomaly info
  display.setTextSize(1); // Set text size for anomaly
  display.setCursor(0, 0); // Set cursor for baseline
  display.print("Baseline:"); // Label for baseline temp
  display.print(baseline, 2); // Show baseline temp w/ 2 decimals
  display.setCursor(0, 16); // Set cursor for current
  display.print("->"); // Arrow pointing to current temp
  display.print(temperature, 2); // Show current temp w/ 2 decimals
  display.display(); // Update display with anomaly info
}
Editor is loading...
Leave a Comment