#include <Arduino.h> // Include core Arduino library
#include <U8g2lib.h> // Include OLED display library
#include "SdFat.h" // Include SD card library
//#include <Adafruit_ADXL345_U.h> // Include accelerometer library
#include <Adafruit_ADXL375.h>
#include <DHT.h> // Include DHT sensor library
#include <OneWire.h> // Include OneWire library for DS18B20 sensors
#include <DallasTemperature.h> // Include DallasTemperature library
#define ADXL375_SCK 13
#define ADXL375_MISO 12
#define ADXL375_MOSI 11
#define ADXL375_CS 10
#define OLED_SDA 14 // Define OLED SDA pin
#define OLED_SCL 15 // Define OLED SCL pin
#define SCREEN_WIDTH 128 // Define OLED screen width
#define SCREEN_HEIGHT 64 // Define OLED screen height
#define ONE_WIRE_BUS 27 // Define OneWire bus pin for DS18B20 sensors
#define MCP9700AT_PIN 35 // Define pin for MCP9700AT temperature sensor
#define DHT_PIN 4 // Define pin for DHT sensor
#define DHT_TYPE DHT22 // Define DHT sensor type
#define ADC_VREF 3.3 // Define ADC reference voltage
#define ADC_RESOLUTION 4095.0 // Define ADC resolution
#define iSense 32 // Define current sensor pin
#define Vin 33 // Define voltage sensor pin
#define loadCellPin 13 // Define load cell pin
#define MOSI_PIN 23 // Define MOSI pin for SPI
#define SCK_PIN 25 // Define SCK pin for SPI
#define SPI_SPEED SD_SCK_MHZ(1) // Define SPI speed for SD card
#define CS_PIN 5 // Define CS pin for SD card
#define VibratorPin 18 // Define pin for vibrator motor
#define freq 5000 // Define frequency for PWM
#define VibChannel 2 // Define PWM channel for vibrator
#define DeicingLengthms 10000 //360000//""420000"//360000 // Define deicing length in milliseconds
#define Frostingtimems 5000 //18000000 //5400000//"180000"//5400000 // Define frosting time in milliseconds
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, OLED_SDA, OLED_SCL, U8X8_PIN_NONE); // Create OLED display object
/* Assign a unique ID to this sensor at the same time */
/* Uncomment following line for default Wire bus */
Adafruit_ADXL375 accel = Adafruit_ADXL375(12345);
/* Uncomment for software SPI */
//Adafruit_ADXL375 accel = Adafruit_ADXL375(ADXL375_SCK, ADXL375_MISO, ADXL375_MOSI, ADXL375_CS, 12345);
/* Uncomment for hardware SPI */
//Adafruit_ADXL375 accel = Adafruit_ADXL375(ADXL375_CS, &SPI, 12345);
////Adafruit_ADXL375_Unified accel = Adafruit_ADXL375_Unified(12345); // Create accelerometer object
OneWire oneWire(ONE_WIRE_BUS); // Create OneWire object for DS18B20 sensors
DallasTemperature sensors(&oneWire); // Create DallasTemperature object
DHT dht(DHT_PIN, DHT_TYPE); // Create DHT sensor object
SdFat sd; // Create SD card object
// Define variables for sensor readings and control parameters
float loadcellV = 0, humidity = 50, temperature = 20, X_MAX, Y_MAX, Z_MAX, ax, ay, az, aMagn, aMagnMax, frequencyZ = 0, lastZ = 0, currentZ = 0, dew, THX, tempC;
int Volt = 1, counter = 1, Valvetime = 0, baselinefor_Z = 0, cyclecount = 0, leaveloop = 0, timexp = 0, dutycycle = 560, dutycycleFan = 180, SDCount = 1, targetRH = 87.5, error;
//Blue motor vibrator calibration curve speed can be found in excell here C:\Users\Ayyoub Profile\OneDrive - ultratechsol.com\UTS Team Shared Folder\BTO De-Icing\Reports\Q11 Report\freezerDataLoggerLoadcellVibRHOled3WalvesQ11\cleanedupcodewithChatGPT\DataLoggerFreezerSDCleanedupChatGPT
unsigned long lastMillis = 0, currentMillis = 0;
const int NUM_READINGS = 2, MAX_HUMIDITY_READINGS = 2, dt = 1, median = 750;
int currentRaw = 222; // Declare currentRaw variable
float rhData[MAX_HUMIDITY_READINGS] = {0}; // Array to store humidity readings
int rhBufferIndex = 0; // Index for humidity readings array
bool showGraphPage = false; // Flag to toggle between display pages
void setup() {
pinMode(2, OUTPUT); // Set pin 2 as output for SD card error LED
pinMode(16, OUTPUT); // Set pin 16 as output for valve 1
pinMode(17, OUTPUT); // Set pin 17 as output for valve 2
pinMode(VibratorPin, OUTPUT); // Set pin for vibrator motor as output
ledcSetup(VibChannel, freq, 12); // Configure PWM channel for vibrator motor
ledcAttachPin(VibratorPin, VibChannel); // Attach PWM channel to vibrator pin
Wire.begin(21, 22); // Initialize I2C for accelerometer
Serial.begin(115200); // Initialize serial communication
if (!accel.begin()) { // Check if accelerometer is connected
Serial.println("Could not find a valid ADXL375 sensor, check wiring!"); // Print error message
digitalWrite(2, HIGH); // Set pin 2 to HIGH
while (1); // Stay here if accelerometer is not found
}
// accel.setRange(ADXL375_RANGE_16_G); // Set accelerometer range
lastMillis = millis(); // Store current time
dht.begin(); // Initialize DHT sensor
sensors.begin(); // Initialize DS18B20 sensors
sensors.setResolution(9); // Set resolution for DS18B20 sensors
pinMode(iSense, INPUT); // Set current sensor pin as input
analogSetPinAttenuation(iSense, ADC_0db); // Set attenuation for current sensor
pinMode(Vin, INPUT); // Set voltage sensor pin as input
analogSetPinAttenuation(Vin, ADC_0db); // Set attenuation for voltage sensor
pinMode(loadCellPin, INPUT); // Set load cell pin as input
if (!u8g2.begin()) { // Initialize OLED display
Serial.println(F("U8g2 initialization failed")); // Print error message if initialization fails
for (;;); // Stay here if OLED initialization fails
}
SPI.begin(SCK_PIN); // Initialize SPI with custom SCK pin
if (!sd.begin(CS_PIN, SD_SCK_MHZ(4))) { // Initialize SD card
Serial.println("SD initialization failed"); // Print error message if SD initialization fails
digitalWrite(2, HIGH); // Turn on error LED
return; // Exit setup if SD initialization fails
}
}
void loop() {
// Reset sensor data
X_MAX = 0; Y_MAX = 0; Z_MAX = 0; frequencyZ = 0.; aMagnMax = 0;
cyclecount = 0; leaveloop = 0; unsigned long timestart = micros(); // Reset timing variables
// Read accelerometer data
for (int i = 0; i < 2000; i++) {
if (leaveloop < 4) {
sensors_event_t event; // Create event object for accelerometer
accel.getEvent(&event); // Get accelerometer event
ax = event.acceleration.x; // Read X-axis acceleration
ay = event.acceleration.y; // Read Y-axis acceleration
az = event.acceleration.z; // Read Z-axis acceleration
delay(1); // I just added
aMagn = sqrt(ax * ax + ay * ay + az * az); // Calculate magnitude of acceleration
X_MAX = max(X_MAX, abs(ax)); // Update max X-axis acceleration
Y_MAX = max(Y_MAX, abs(ay)); // Update max Y-axis acceleration
Z_MAX = max(Z_MAX, abs(az)); // Update max Z-axis acceleration
aMagnMax = max(aMagnMax, aMagn); // Update max acceleration magnitude
currentZ = az-9.8; // Update current Z-axis acceleration //9.8 is the baseline in Z
if ((lastZ * currentZ < 0)) { // Check for zero-crossing in Z-axis
unsigned long timeend = micros(); // Update end time
cyclecount++; // Increment cycle count
if (cyclecount == 1) { // Check if one cycle is completed
frequencyZ = 0.25 / ((timeend - timestart) * 0.000001); // Calculate frequency
cyclecount = 0; // Reset cycle count
leaveloop = leaveloop+1; // Exit loop
// Serial.print(frequencyZ); Serial.print(","); // Print frequency
// Serial.println(aMagn);
break; // Break loop
}
timestart = timeend; // Update start time
}
lastZ = currentZ; // Update last Z-axis acceleration
}
}
currentRaw = analogReadMilliVolts(iSense); // Read current sensor
Volt = analogReadMilliVolts(Vin); // Read voltage sensor
humidity = dht.readHumidity(); // Read humidity
temperature = dht.readTemperature(); // Read temperature
sensors.requestTemperatures(); // Request temperatures from DS18B20 sensors
delay(3); // Delay for stable reading
float temperatureC1 = sensors.getTempCByIndex(0); // Read temperature from sensor 1
float temperatureC2 = sensors.getTempCByIndex(1); // Read temperature from sensor 2
float temperatureC3 = sensors.getTempCByIndex(2); // Read temperature from sensor 3
float temperatureC4 = sensors.getTempCByIndex(3); // Read temperature from sensor 4
float temperatureC5 = sensors.getTempCByIndex(4); // Read temperature from sensor 5
dutycycle = 2000 + 2000 * sin(20.0 * 3.1415 * ((timexp - Valvetime) / DeicingLengthms)); //560 + max(0., 3400 * sin(20 * 3.1415 * ((timexp - Valvetime) / DeicingLengthms))); //20 TIMES Motor going from zero to full speed during the defrosting
unsigned long timexp = millis(); // Get current time
if (timexp - Valvetime > Frostingtimems) { // Check if frosting time has passed
counter = -counter; // Toggle counter
Valvetime = timexp; // Update valve time
}
if (counter == 1) { // Check if in frosting mode
digitalWrite(16, HIGH); // Set valve 1 to HIGH
digitalWrite(17, LOW); // Set valve 2 to LOW
ledcWrite(VibChannel, 0); // Turn off vibrator motor
} else { // In deicing mode
digitalWrite(16, LOW); // Set valve 1 to LOW
digitalWrite(17, HIGH); // Set valve 2 to HIGH
digitalWrite(2, HIGH); delay(100);
if (timexp - Valvetime > DeicingLengthms) { // Check if deicing time has passed
counter = 1; // Switch to frosting mode
Valvetime = timexp; // Update valve time
}
ledcWrite(VibChannel, dutycycle); // Set vibrator motor duty cycle
}
dew = temperature + (0.1221 * temperature + 12.655) * log(humidity / 100); // Calculate dew point
rhData[rhBufferIndex] = humidity; // Store humidity reading
rhBufferIndex = (rhBufferIndex + 1) % MAX_HUMIDITY_READINGS; // Update buffer index
int sensorValue = analogRead(MCP9700AT_PIN); // Read MCP9700AT sensor
float PCB_TEMP = 0.09000 * sensorValue - 44.04357; // Calculate PCB temperature
loadcellV = analogRead(loadCellPin); // Read load cell
//Serial.println(frequencyZ); // Print frequency
if (timexp % 2000 < 1) { // Check if it's time to update display
draw(); // Update display
}
File file = sd.open("/time.txt", O_RDWR | O_CREAT | O_APPEND); // Open SD card file
if (file) {
if (SDCount == 1) { // Print header if first time
file.println("Sec, RH, Tin, Tdew, TEDC, FanDC, temperatureC1, temperatureC2, temperatureC3, temperatureC4, temperatureC5, vibratorDuty%, Amp, Vin, PCB_Temp, Loadcell, Xmax, aMagn, Zmax, aMagnMax, frequencyZ, Valve");
SDCount = 0; // Update SD count
}
file.print(timexp / 1000.); // Print time in seconds
file.print(" , ");
file.print(humidity); // Print humidity
file.print(", ");
file.print(temperature); // Print temperature
file.print(", ");
file.print(dew); // Print dew point
file.print(", ");
file.print(100 * dutycycle / 4095); // Print duty cycle for 12 bit
file.print(" , ");
file.print(100 * dutycycleFan / 255); // Print fan duty cycle
file.print(" , ");
file.print(temperatureC1); // Print temperature 1
file.print(" , ");
file.print(temperatureC2); // Print temperature 2
file.print(" , ");
file.print(temperatureC3); // Print temperature 3
file.print(" , ");
file.print(temperatureC4); // Print temperature 4
file.print(" , ");
file.print(temperatureC5); // Print temperature 5
file.print(" , ");
file.print(100 * dutycycle / 4095); // Print vibrator duty cycle
file.print(" , ");
file.print(-0.010905 * currentRaw + 10.381318); // Print current
file.print(" , ");
file.print(0.0917 * Volt - 1.1167); // Print voltage
file.print(", ");
file.print(PCB_TEMP); // Print PCB temperature
file.print(", ");
file.print(loadcellV); // Print load cell value
file.print(" , ");
file.print(X_MAX); // Print max X-axis acceleration
file.print(" , ");
file.print(aMagn); // Print acceleration magnitude Y-axis acceleration
file.print(" , ");
file.print(Z_MAX); // Print max Z-axis acceleration
file.print(" ,");
file.print(aMagnMax); // Print max acceleration magnitude
file.print(" ,");
aMagnMax=0;Z_MAX=0;Y_MAX=0;X_MAX=0; //this is just added to reset the max numbers
file.print(frequencyZ); // Print frequency
file.print(" ,");
file.println(counter); // Print counter
file.close(); // Close file
}
}
void draw() {
u8g2.begin(); // Initialize OLED display
u8g2.clearBuffer(); // Clear display buffer
u8g2.setFont(u8g2_font_profont11_mr); // Set font
u8g2.setCursor(0, 10); // Set cursor position
u8g2.print("t:"); // Print label
u8g2.print(timexp / 1000.); // Print time
u8g2.setCursor(0, 25); // Set cursor position
u8g2.print("RH:"); // Print label
u8g2.print(humidity); // Print humidity
u8g2.setCursor(0, 40); // Set cursor position
u8g2.print("Tin:"); // Print label
u8g2.print(dht.readTemperature()); // Print temperature
u8g2.setCursor(0, 55); // Set cursor position
u8g2.print("Tdew:"); // Print label
u8g2.print(dew); // Print dew point
u8g2.setCursor(60, 10); // Set cursor position
u8g2.print("DcT"); // Print label
u8g2.print(100 * dutycycle / 4095); // Print duty cycle for 12 bit
u8g2.print(" F");
u8g2.print(100 * dutycycleFan / 255); // Print fan duty cycle
u8g2.setCursor(60, 25); // Set cursor position
u8g2.print("THX:"); // Print label
u8g2.print("0"); // Print placeholder
u8g2.setCursor(60, 40); // Set cursor position
u8g2.print("Cur:"); // Print label
u8g2.print(-0.010905 * currentRaw + 10.381318); // Print current
u8g2.setCursor(60, 55); // Set cursor position
u8g2.print("Vin:"); // Print label
u8g2.print(0.0917 * Volt - 1.1167); // Print voltage
u8g2.sendBuffer(); // Send buffer to display
}