/*
Forum: https://forum.arduino.cc/t/hanging-up-not-progressing-past-setup/1289901/16
Wokwi: https://wokwi.com/projects/405673151569291265
2024/08/08
ec2021
*/
#define WOKWI
// Libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_HTU21DF.h>
#include <EEPROM.h>
const char Celsius[] = {' ', char(247), 'C', '\0'};
const char Fahrenheit[] = {' ', char(247), 'F', '\0'};
const char Kelvin[] = " K";
const char MilesPerHour[] = " MPH";
const char Knots[] = " Kts";
const char KmPerHour[] = " Kph";
const char MeterPerSec[] = " m/s";
const char Seconds[] = " Seconds";
const char AverageTiming[] = "Average timing";
const char oneMinute[] = "1 Minute";
const char Transmission[] = "Transmission";
// OLED Declarations
#define screenW 128
#define screenH 64
#define oledreset -1
Adafruit_SSD1306 disp = Adafruit_SSD1306(screenW, screenH, &Wire, oledreset);
// HTU21D Temp and Humid Declarations
//Adafruit_HTU21DF htu = Adafruit_HTU21DF();
#ifdef WOKWI
#include "DHT.h"
#define DHTPIN 6 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
DHT htu(DHTPIN, DHTTYPE);
#else
//HTU21D Temp and Humid Declarations
Adafruit_HTU21DF htu = Adafruit_HTU21DF();
#endif
unsigned long THStartMillis = 0,
THCurrentMillis = 0;
const unsigned int THDelay = 1000;
// Anem Debounce
unsigned long lastDB = 0;
unsigned long delayDB = 1000;
// Wind Declarations
float windspeed = 0;
int count = 0;
// Weather Declaratons
float temp = 0,
pressure = 0,
altitude = 0,
QNH = 1013.15;
// Pin Delarations
const int pinInterrupt = 2,
LButt = 3,
MButt = 4,
RButt = 5,
led = 7,
Rel1 = 8,
Rel2 = 9;
// Button States
int LBState = 0,
MBState = 0,
RBState = 0;
// Last Button State
int LBLState = 0,
MBLState = 0,
RBLState = 0;
// Button and Menu Counts
unsigned int MBCount = 0;
int unitCount = 0,
tempUnitCount = 0,
averageDisplayCount = 0,
averageTransmitCount = 0;
// Average Wind Declarations
unsigned long averageStartMillis = 0,
averageCurrentMillis = 0;
unsigned int averageDelayArr[3] = { 10000, 30000, 60000 };
unsigned int averageDelay = 0;
float averageRunningTotal = 0,
averageWindspeed = 0;
unsigned int averageDenom = 0;
// Transmission Timing
unsigned long transStartMillis = 0;
unsigned long transCurrentMillis = 0;
unsigned int transPeriodArr[3] = { 5000, 10000, 15000 };
unsigned int transPeriod = 0;
unsigned long sendStartMillis = 0;
int sendPeriod = 1000;
// Loading
int loading = 0;
// Data Save
unsigned long saveStartMillis = 0,
saveCurrentMillis = 0;
unsigned int savePeriod = 10000;
// Function to count interupts
void onChange() {
if (digitalRead(pinInterrupt) == LOW) {
count++;
}
}
void printData() {
Serial.print(F("MC - "));
Serial.print(MBCount);
Serial.print(F(" UC - "));
Serial.print(unitCount);
Serial.print(F(" TC - "));
Serial.print(tempUnitCount);
Serial.print(F(" ADC - "));
Serial.print(averageDisplayCount);
Serial.print(F(" ATC - "));
Serial.println(averageTransmitCount);
}
void setup() {
// Begin Serial
Serial.begin(115200);
Serial.print(F("Serial Begin."));
// Start Timers
averageStartMillis = millis();
transStartMillis = millis();
THStartMillis = millis();
Serial.print(F(" Timers Started."));
// Pin Modes
pinMode(pinInterrupt, INPUT_PULLUP);
pinMode(led, OUTPUT);
pinMode(LButt, INPUT_PULLUP);
pinMode(MButt, INPUT_PULLUP);
pinMode(RButt, INPUT_PULLUP);
pinMode(Rel1, OUTPUT);
pinMode(Rel2, OUTPUT);
Serial.print(" Pin Modes Set.");
// HTU21D Temp and Humid Initialization
#ifdef WOKWI
htu.begin();
#else
if (!htu.begin()) {
Serial.println(F("No Temp/Humid Sensor Detected"));
while (1) ;
}
#endif
delay(500);
Serial.print(F(" HTU Started."));
// Display Initialization
#ifdef WOKWI
disp.begin(SSD1306_SWITCHCAPVCC, 0x3D);
#else
disp.begin(SSD1306_SWITCHCAPVCC, 0x3C);
#endif
delay(500);
disp.clearDisplay();
disp.display();
disp.setTextColor(WHITE);
printAt(30, 25, 1, "WINDSPEEDS!");
disp.display();
delay(1000);
loading = 32;
char c = char(175);
for (int i = 0; i < 7; i++) {
disp.setCursor(loading, 40);
disp.print(c);
disp.display();
delay(100);
loading = loading + 9;
}
delay(1000);
Serial.println(F(" Screen Initialised."));
// Initialize interrupt
attachInterrupt(digitalPinToInterrupt(pinInterrupt), onChange, FALLING);
// Average
averageDelay = 10000;
// Transmission
transPeriod = 10000;
// Data Read
unitCount = EEPROM.read(0);
averageDisplayCount = EEPROM.read(1);
averageTransmitCount = EEPROM.read(2);
tempUnitCount = EEPROM.read(3);
// LED
digitalWrite(led, HIGH);
}
void printAt(byte Col, byte Row, byte Size, char * txt) {
disp.setCursor(Col, Row);
disp.setTextSize(Size);
disp.print(txt);
}
void printAt(byte Col, byte Row, byte Size, char * before, float f, char * after) {
char Fbuf[10];
char buf[40];
dtostrf(f, 3, 2, Fbuf);
strcpy(buf, before);
strcat(buf, Fbuf);
strcat(buf, after);
printAt(Col, Row, Size, buf);
}
void printAt(byte Col, byte Row, byte Size, char * before, float f) {
printAt(Col, Row, Size, before, f, "");
}
void printAt(byte Col, byte Row, byte Size, float f, char * after) {
printAt(Col, Row, Size, "", f, after);
}
void loop() {
// Start Loop Timers
transCurrentMillis = millis();
averageCurrentMillis = millis();
saveCurrentMillis = millis();
THCurrentMillis = millis();
// Calculate windspeed and display to Serial.
if ((millis() - lastDB) > delayDB) {
windspeed = ((count * 8.75) / 100);
lastDB = millis();
//Serial.println(millis());
//Serial.print(windspeed);
averageRunningTotal = averageRunningTotal + windspeed;
count = 0;
//Serial.println("m/s");
}
delay(5);
// Read Temperature and Humidty
if (THCurrentMillis - THStartMillis >= THDelay)
{
temp = htu.readTemperature();
float rel_hum = htu.readHumidity(); // Not used further!!!
THStartMillis = THCurrentMillis;
Serial.println(temp);
}
// Read Button States
LBState = digitalRead(LButt);
MBState = digitalRead(MButt);
RBState = digitalRead(RButt);
// Main Button Count
if (MBState != MBLState) {
if (MBState == HIGH) {
MBCount++;
printData();
}
delay(50);
}
MBLState = MBState;
// MAIN SCREEN - if MCount is 0
if (MBCount == 0) {
disp.clearDisplay();
printAt(0, 2, 1, "Live -");
printAt(0, 18, 1, "Av(", averageDelayArr[averageDisplayCount] / 1000, " s) - ");
printAt(0, 34, 1, "Trans(", transPeriodArr[averageTransmitCount] / 1000, " s) - ");
// Temp Unit Commands
// C
if (tempUnitCount == 0) {
printAt(0, 50, 1, temp, Celsius);
}
// F
else if (tempUnitCount == 1) {
float t = temp * (9 / 5) + 32;
printAt(0, 50, 1, t, Fahrenheit);
}
// K
else if (tempUnitCount == 2) {
float t = temp + 273.15;
printAt(0, 50, 1, t, Kelvin);
}
// Wind Unit Commands
// M/S
if (unitCount == 0) {
// Main
printAt(50, 2, 1, windspeed, MeterPerSec);
// Average
printAt(70, 18, 1, averageWindspeed, MeterPerSec);
}
// KPH
else if (unitCount == 1) {
// Main
printAt(50, 2, 1, windspeed * 3.6, KmPerHour);
// Average
printAt(70, 18, 1, averageWindspeed * 3.6, KmPerHour);
}
// MPH
else if (unitCount == 2) {
// Main
printAt(50, 2, 1, windspeed * 2.237, MilesPerHour);
// Average
printAt(70, 18, 1, averageWindspeed * 2.237, MilesPerHour);
}
// KT
else if (unitCount == 3) {
// Main
printAt(50, 2, 1, windspeed * 1.94384, Knots);
// Average
printAt(70, 18, 1, averageWindspeed * 1.94384, Knots);
}
//Average Time Commands
// 10 Seconds
if (averageDisplayCount == 0) {
averageDelay = averageDelayArr[0];
averageDenom = averageDelay / 1000;
}
// 30 Seconds
else if (averageDisplayCount == 1) {
averageDelay = averageDelayArr[1];
averageDenom = averageDelay / 1000;
}
// 1 Minute
else if (averageDisplayCount == 2) {
averageDelay = averageDelayArr[2];
averageDenom = averageDelay / 1000;
}
//Transmission Commands
if (digitalRead(Rel1) == HIGH) {
disp.fillRect(82, 33, 30, 9, WHITE);
disp.setTextColor(BLACK);
printAt(85, 34, 1, "SEND");
disp.setTextColor(WHITE);
} else if (digitalRead(Rel1) == LOW) {
disp.fillRect(80, 34, 48, 8, BLACK);
}
//DISPLAY MAIN SCREEN
disp.display();
}
// Unit Set Screen MBCount = 1
else if (MBCount == 1) {
// LEFT BUTTON
if (LBState != LBLState) {
if (LBState == HIGH) {
unitCount--;
printData();
}
delay(50);
}
LBLState = LBState;
// RIGHT BUTTON
if (RBState != RBLState) {
if (RBState == HIGH) {
unitCount++;
printData();
}
delay(50);
}
RBLState = RBState;
// Limit Unit Count 0 - 3
if (unitCount > 3) {
unitCount = 0;
} else if (unitCount < 0) {
unitCount = 3;
}
// Display
disp.clearDisplay();
printAt(0, 0, 2, "Units");
// M/S
if (unitCount == 0) {
printAt(50, 30, 2, MeterPerSec);
}
// KPH
else if (unitCount == 1) {
printAt(50, 30, 2, KmPerHour);
}
// MPH
else if (unitCount == 2) {
printAt(50, 30, 2, MilesPerHour);
}
// KTS
else if (unitCount == 3) {
printAt(50, 30, 2, Knots);
}
// DISPLAY UNITS
disp.display();
}
// Temp Unit Set Screen MBCount = 2
else if (MBCount == 2) {
// LEFT BUTTON
if (LBState != LBLState) {
if (LBState == HIGH) {
tempUnitCount--;
printData();
}
delay(50);
}
LBLState = LBState;
// RIGHT BUTTON
if (RBState != RBLState) {
if (RBState == HIGH) {
tempUnitCount++;
printData();
}
delay(50);
}
RBLState = RBState;
// Limit Temp Unit Count 0 - 2
if (tempUnitCount > 2) {
tempUnitCount = 0;
} else if (tempUnitCount < 0) {
tempUnitCount = 2;
}
// Display
disp.clearDisplay();
disp.setTextSize(2);
printAt(0, 0, 2, "Temp Units");
// C
if (tempUnitCount == 0) {
printAt(50, 30, 2, Celsius);
}
// F
else if (tempUnitCount == 1) {
printAt(50, 30, 2, Fahrenheit);
}
// K
else if (tempUnitCount == 2) {
printAt(50, 30, 2, Kelvin);
}
disp.display();
}
// Average Time Setting Screen MBCount = 2
else if (MBCount == 3) {
// LEFT BUTTON
if (LBState != LBLState) {
if (LBState == HIGH) {
averageDisplayCount--;
printData();
}
delay(50);
}
LBLState = LBState;
// RIGHT BUTTON
if (RBState != RBLState) {
if (RBState == HIGH) {
averageDisplayCount++;
printData();
}
delay(50);
}
RBLState = RBState;
// Limit Average Time Count 0 - 2
if (averageDisplayCount > 2) {
averageDisplayCount = 0;
} else if (averageDisplayCount < 0) {
averageDisplayCount = 2;
}
// Display
disp.clearDisplay();
printAt(0, 0, 1, AverageTiming);
if (averageDisplayCount == 0) {
printAt(50, 30, 1, 10, Seconds);
} else if (averageDisplayCount == 1) {
printAt(50, 30, 1, 30, Seconds);
} else if (averageDisplayCount == 2) {
printAt(50, 30, 1, oneMinute);
}
disp.display();
}
// Transmission delay Settings MBCount = 3
else if (MBCount == 4) {
// LEFT BUTTON
if (LBState != LBLState) {
if (LBState == HIGH) {
averageTransmitCount--;
printData();
}
delay(50);
}
LBLState = LBState;
// RIGHT BUTTON
if (RBState != RBLState) {
if (RBState == HIGH) {
averageTransmitCount++;
printData();
}
delay(50);
}
RBLState = RBState;
// Limit Average Transmit Time Count 0 - 2
if (averageTransmitCount > 2) {
averageTransmitCount = 0;
} else if (averageTransmitCount < 0) {
averageTransmitCount = 2;
}
// Display
disp.clearDisplay();
printAt(0, 0, 1, Transmission);
// transmission period 1 ... 3
if (averageTransmitCount >= 0 && averageTransmitCount < 3) {
printAt(50, 30, 1, transPeriodArr[averageTransmitCount] / 1000, Seconds);
transPeriod = transPeriodArr[averageTransmitCount];
}
disp.display();
} else if (MBCount >= 5) {
MBCount = 0;
}
// Average timing and calculations
if (averageCurrentMillis - averageStartMillis >= averageDelay) {
averageWindspeed = (averageRunningTotal / averageDenom);
averageStartMillis = averageCurrentMillis;
averageRunningTotal = 0;
Serial.println(millis());
Serial.print(averageWindspeed);
Serial.print('\n');
}
// Transmission Timing
if (transCurrentMillis - transStartMillis >= transPeriod) {
digitalWrite(Rel1, HIGH);
Serial.println(F("TRANSMITTING"));
transStartMillis = transCurrentMillis;
}
if (transCurrentMillis - transStartMillis > sendPeriod) {
digitalWrite(Rel1, LOW);
}
// Save Preferences
if (saveCurrentMillis - saveStartMillis >= savePeriod) {
EEPROM.update(0, unitCount);
EEPROM.update(1, averageDisplayCount);
EEPROM.update(2, averageTransmitCount);
EEPROM.update(3, tempUnitCount);
Serial.println(F("Saved"));
saveStartMillis = saveCurrentMillis;
}
}