First init.

This commit is contained in:
2025-10-12 09:13:56 +02:00
commit 1548aeaf9b
458 changed files with 118808 additions and 0 deletions

View File

@@ -0,0 +1,266 @@
/* Latest DinoFan 28.06.2024-001
Added watchdog timer, 4 seconds.
Removed SoftSerial since it interferred with Wire.h
Added M3200 sensor for oil temp and pressure. */
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <avr/wdt.h>
#define TFT_RST 8
#define TFT_CS 10
#define TFT_DC 9
#define ST7735_ORANGE 0xF4E3
#define ST7735_CYAN2 0x6658
#define ST7735_DGRAY 0x3186
float version = 240630;
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
int M3200address = 0x28; // 0x28, 0x36, or 0x46, depending on the sensor.
float maxPressure = 100; // pressure in PSI for this sensor, 100, 250, 500, ... 10k.
float pressure;
float temperature;
byte status;
float tempForFanStartup = 85.0; // 175 target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 100.0; // 210 target High temp. above this temperature, the fan will be on at full power
float voltsForFanStartup = 2.0; // Roughly the signal voltage that triggers the slowest speed.
const int fanPwmOutPin = 3; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = 2; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
float fanSpeedPct;
OneWire oneWire1 (tempSensorPin);
DallasTemperature sensorClt1(&oneWire1);
//Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned long previousMillis = 0; // Variable to store the last time the serial data was sent
const long interval = 5000; // Interval between serial data transmissions (in milliseconds)
unsigned long previous2Millis = 0;
const int pressureTiming = 1000; // 500ms every data acquisition
void setup() {
wdt_enable(WDTO_4S);
Serial.begin(9600);
Wire.begin();
tft.initR(INITR_BLACKTAB);
tft.fillScreen(ST77XX_BLACK);
tft.setRotation(3);
/* if (!display.begin(i2c_Address)) {
Serial.println(F("SH110X allocation failed"));
for (;;);
}
display.clearDisplay(); // Clear the display buffer */
sensorClt1.begin();
sensorClt1.requestTemperatures();
currTemperature = sensorClt1.getTempCByIndex(0);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
delay(500);
Serial.print("F20.0");
delay(20);
Serial.print("D000");
}
void loop() {
unsigned long currentMillis = millis();
unsigned long pressureMillis = millis();
//Pull data from M3200 every second.
if (pressureMillis - previous2Millis >= pressureTiming) {
get_data_from_M3200();
previous2Millis = pressureMillis;
}
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // uncomment this line for testing and calibration to the laptop.
// Check if it's time to send serial data
if (currentMillis - previousMillis >= interval) {
serial_to_signal_generator(); // Send serial data
previousMillis = currentMillis; // Save the last time serial data was sent
}
displayOutput();
wdt_reset();
}
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
//analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
//analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) +.5); // actual PWM duty is calculated here
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100);
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
//analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() {
// Request temperature readings
sensorClt1.requestTemperatures();
// Read the temperature from the sensor
float tempC = sensorClt1.getTempCByIndex(0);
// Check if the temperature reading is within the valid range
if (tempC > -30 && tempC < 130) {
// If the reading is within the valid range, update the current temperature
currTemperature = tempC;
} else if (tempC < -50 || tempC > 150) {
// If the reading is outside the extreme range, set the current temperature to 0
currTemperature = 0;
}
// If the reading is outside the valid range, do not update the current temperature
}
void displayOutput() {
//display.clearDisplay();
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
// Display temperature on the screen in Celsius with one decimal place
tft.setCursor(26, 0);
tft.print("Pontiac LeMans '69");
tft.drawLine(2, 10, 159, 10, ST7735_WHITE);
tft.setCursor(0, 16);
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
tft.print("Temp Coolant:");
tft.setCursor(88, 16);
tft.print(currTemperature, 1); // Display one decimal place
tft.print(" C ");
tft.setCursor(0, 26);
tft.print("Temp Oil :");
tft.setCursor(88, 26);
tft.print(temperature, 1);
tft.print(" C ");
tft.setCursor(0, 36);
tft.print("Oil Pressure:");
tft.setCursor(88, 36);
tft.print(pressure, 1);
tft.print(" b ");
// Calculate and display fan speed percentage
if (currTemperature < tempForFanStartup) {
fanSpeedPct = 0; // Set fan speed to 0% if temperature is below startup threshold
} else {
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100); // Calculate fan speed percentage
}
tft.setCursor(0, 56);
tft.print("Fan Speed :");
tft.setCursor(88, 56);
tft.print((int)fanSpeedPct);
tft.print(" % ");
tft.setCursor(4, 120);
tft.setTextColor(ST7735_DGRAY, ST77XX_BLACK);
tft.print("BoopLabs Vitals");
tft.setCursor(120, 120);
tft.setTextColor(ST7735_DGRAY, ST77XX_BLACK);
tft.print(version, 0);
}
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature C: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
Serial.print(F("Percentage: ")); Serial.println((int)fanSpeedPct);
}
void serial_to_signal_generator() {
// Determine fan speed percentage to send
int speedToSend = (int)fanSpeedPct;
// Ensure fan speed is 0 if temperature is below startup threshold
if (currTemperature < tempForFanStartup) {
speedToSend = 0;
}
// Check the length of fanSpeedPct
if (speedToSend < 10) {
Serial.print(F("D00")); // Add "D00" prefix for single-digit fan speed
} else if (speedToSend < 100) {
Serial.print(F("D0")); // Add "D0" prefix for double-digit fan speed
} else {
Serial.print(F("D")); // Add "D" prefix for triple-digit fan speed
}
Serial.print(speedToSend); // Send fan speed
}
void get_data_from_M3200() {
Wire.requestFrom(M3200address, 4); // request 4 bytes
int n = Wire.available();
if (n == 4) {
status = 0;
uint16_t rawP; // pressure data from sensor
uint16_t rawT; // temperature data from sensor
rawP = (uint16_t) Wire.read(); // upper 8 bits
rawP <<= 8;
rawP |= (uint16_t) Wire.read(); // lower 8 bits
rawT = (uint16_t) Wire.read(); // upper 8 bits
rawT <<= 8;
rawT |= (uint16_t) Wire.read(); // lower 8 bits
status = rawP >> 14; // The status is 0, 1, 2, or 3
rawP &= 0x3FFF; // keep 14 bits, remove status bits
rawT >>= 5; // the lowest 5 bits are not used
pressure = ((rawP - 1000.0) / (15000.0 - 1000.0)) * maxPressure;
temperature = ((rawT - 512.0) / (1075.0 - 512.0)) * 55.0;
// Serial.println("--- Values from M3200 ---");
// Serial.println(temperature);
// Serial.println(pressure);
} else {
Serial.println("M3200 Pressure Transducer not Detected");
}
}

View File

@@ -0,0 +1,270 @@
/* Latest DinoFan 16.07.2024-001
Updated for the GMT020-02 display.
Added watchdog timer, 4 seconds.
Removed SoftSerial since it interferred with Wire.h
Added M3200 sensor for oil temp and pressure. */
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <avr/wdt.h>
#include <Fonts/FreeSans9pt7b.h>
#define TFT_RST 8
#define TFT_CS 10
#define TFT_DC 9
#define PUP_ORANGE 0xF4E3
#define PUP_CYAN2 0x6658
#define PUP_DGRAY 0x3186
#define PUP_LBLUE 0x051D
#define PUP_POISON 0xA7C9
float version = 24071601;
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
int M3200address = 0x28; // 0x28, 0x36, or 0x46, depending on the sensor.
float maxPressure = 100; // pressure in PSI for this sensor, 100, 250, 500, ... 10k.
float pressure;
float temperature;
byte status;
float tempForFanStartup = 85.0; // 175 target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 100.0; // 210 target High temp. above this temperature, the fan will be on at full power
float voltsForFanStartup = 2.0; // Roughly the signal voltage that triggers the slowest speed.
const int fanPwmOutPin = 3; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = 2; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
float fanSpeedPct;
OneWire oneWire1 (tempSensorPin);
DallasTemperature sensorClt1(&oneWire1);
//Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned long previousMillis = 0; // Variable to store the last time the serial data was sent
const long interval = 5000; // Interval between serial data transmissions (in milliseconds)
unsigned long previous2Millis = 0;
const int pressureTiming = 1000; // 500ms every data acquisition
void setup() {
wdt_enable(WDTO_4S);
Serial.begin(9600);
Wire.begin();
tft.init(240, 320, SPI_MODE3);
tft.setRotation(3);
tft.fillScreen(ST77XX_BLACK);
/* if (!display.begin(i2c_Address)) {
Serial.println(F("SH110X allocation failed"));
for (;;);
}
display.clearDisplay(); // Clear the display buffer */
sensorClt1.begin();
sensorClt1.requestTemperatures();
currTemperature = sensorClt1.getTempCByIndex(0);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
delay(500);
Serial.print("F20.0");
delay(20);
Serial.print("D000");
}
void loop() {
unsigned long currentMillis = millis();
unsigned long pressureMillis = millis();
//Pull data from M3200 every second.
if (pressureMillis - previous2Millis >= pressureTiming) {
get_data_from_M3200();
previous2Millis = pressureMillis;
}
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // uncomment this line for testing and calibration to the laptop.
// Check if it's time to send serial data
if (currentMillis - previousMillis >= interval) {
serial_to_signal_generator(); // Send serial data
previousMillis = currentMillis; // Save the last time serial data was sent
}
displayOutput();
wdt_reset();
}
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
//analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
//analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) +.5); // actual PWM duty is calculated here
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100);
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
//analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() {
// Request temperature readings
sensorClt1.requestTemperatures();
// Read the temperature from the sensor
float tempC = sensorClt1.getTempCByIndex(0);
// Check if the temperature reading is within the valid range
if (tempC > -30 && tempC < 130) {
// If the reading is within the valid range, update the current temperature
currTemperature = tempC;
} else if (tempC < -50 || tempC > 150) {
// If the reading is outside the extreme range, set the current temperature to 0
currTemperature = 0;
}
// If the reading is outside the valid range, do not update the current temperature
}
void displayOutput() {
//display.clearDisplay();
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
// Display temperature on the screen in Celsius with one decimal place
tft.setCursor(26, 0);
tft.print("Pontiac LeMans '69");
tft.drawLine(2, 10, 159, 10, ST77XX_WHITE);
tft.setCursor(0, 16);
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
tft.print("Temp Coolant:");
tft.setCursor(88, 16);
tft.print(currTemperature, 1); // Display one decimal place
tft.print(" C ");
tft.setCursor(0, 26);
tft.print("Temp Oil :");
tft.setCursor(88, 26);
tft.print(temperature, 1);
tft.print(" C ");
tft.setCursor(0, 36);
tft.print("Oil Pressure:");
tft.setCursor(88, 36);
tft.print(pressure, 1);
tft.print(" b ");
// Calculate and display fan speed percentage
if (currTemperature < tempForFanStartup) {
fanSpeedPct = 0; // Set fan speed to 0% if temperature is below startup threshold
} else {
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100); // Calculate fan speed percentage
}
tft.setCursor(0, 56);
tft.print("Fan Speed :");
tft.setCursor(88, 56);
tft.print((int)fanSpeedPct);
tft.print(" % ");
tft.setCursor(4, 120);
tft.setTextColor(PUP_DGRAY, ST77XX_BLACK);
tft.print("BoopLabs Vitals");
tft.setCursor(120, 120);
tft.setTextColor(PUP_DGRAY, ST77XX_BLACK);
tft.print(version, 0);
}
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature C: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
Serial.print(F("Percentage: ")); Serial.println((int)fanSpeedPct);
}
void serial_to_signal_generator() {
// Determine fan speed percentage to send
int speedToSend = (int)fanSpeedPct;
// Ensure fan speed is 0 if temperature is below startup threshold
if (currTemperature < tempForFanStartup) {
speedToSend = 0;
}
// Check the length of fanSpeedPct
if (speedToSend < 10) {
Serial.print(F("D00")); // Add "D00" prefix for single-digit fan speed
} else if (speedToSend < 100) {
Serial.print(F("D0")); // Add "D0" prefix for double-digit fan speed
} else {
Serial.print(F("D")); // Add "D" prefix for triple-digit fan speed
}
Serial.print(speedToSend); // Send fan speed
}
void get_data_from_M3200() {
Wire.requestFrom(M3200address, 4); // request 4 bytes
int n = Wire.available();
if (n == 4) {
status = 0;
uint16_t rawP; // pressure data from sensor
uint16_t rawT; // temperature data from sensor
rawP = (uint16_t) Wire.read(); // upper 8 bits
rawP <<= 8;
rawP |= (uint16_t) Wire.read(); // lower 8 bits
rawT = (uint16_t) Wire.read(); // upper 8 bits
rawT <<= 8;
rawT |= (uint16_t) Wire.read(); // lower 8 bits
status = rawP >> 14; // The status is 0, 1, 2, or 3
rawP &= 0x3FFF; // keep 14 bits, remove status bits
rawT >>= 5; // the lowest 5 bits are not used
pressure = ((rawP - 1000.0) / (15000.0 - 1000.0)) * maxPressure;
temperature = ((rawT - 512.0) / (1075.0 - 512.0)) * 55.0;
// Serial.println("--- Values from M3200 ---");
// Serial.println(temperature);
// Serial.println(pressure);
} else {
Serial.println("M3200 Pressure Transducer not Detected");
}
}

View File

@@ -0,0 +1,181 @@
/* Latest running code on the Arduino in the Pontiac as of 06.06.2024 */
/* Added watchdog timer, 4 seconds. */
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <SoftwareSerial.h>
#include <avr/wdt.h>
#define i2c_Address 0x3C // OLED Adress.
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
float tempForFanStartup = 85.0; // 175 target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 100.0; // 210 target High temp. above this temperature, the fan will be on at full power
float voltsForFanStartup = 2.0; // Roughly the signal voltage that triggers the slowest speed.
const int fanPwmOutPin = 12; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = 7; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
float fanSpeedPct;
OneWire oneWire1 (tempSensorPin);
DallasTemperature sensorClt1(&oneWire1);
const byte rxPin = 2;
const byte txPin = 3;
SoftwareSerial secondSerial (rxPin, txPin);
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned long previousMillis = 0; // Variable to store the last time the serial data was sent
const long interval = 5000; // Interval between serial data transmissions (in milliseconds)
void setup() {
wdt_enable(WDTO_4S);
Serial.begin(115200); // set up serial port for 115200 baud (optional)
if (!display.begin(i2c_Address)) {
Serial.println(F("SH110X allocation failed"));
for (;;);
}
display.clearDisplay();
secondSerial.begin(9600);
delay(500);
secondSerial.print("F20.0");
delay(20);
secondSerial.print("D000");
sensorClt1.begin();
sensorClt1.requestTemperatures();
currTemperature = sensorClt1.getTempCByIndex(0);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
}
void loop() {
unsigned long currentMillis = millis();
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // uncomment this line for testing and calibration to the laptop.
// Check if it's time to send serial data
if (currentMillis - previousMillis >= interval) {
serial_to_signal_generator(); // Send serial data
previousMillis = currentMillis; // Save the last time serial data was sent
}
displayOutput();
wdt_reset();
}
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
//analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
//analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) +.5); // actual PWM duty is calculated here
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100);
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
//analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() {
// Request temperature readings
sensorClt1.requestTemperatures();
// Read the temperature from the sensor
float tempC = sensorClt1.getTempCByIndex(0);
// Check if the temperature reading is within the valid range
if (tempC > -30 && tempC < 130) {
// If the reading is within the valid range, update the current temperature
currTemperature = tempC;
}
// If the reading is outside the valid range, do not update the current temperature
}
void displayOutput() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
// Display temperature on the screen in Celsius with one decimal place
display.setCursor(0, 0);
display.print("Temp:");
display.setCursor(30, 0);
display.print(currTemperature, 0); // Display one decimal place
// Calculate and display fan speed percentage
if (currTemperature < tempForFanStartup) {
fanSpeedPct = 0; // Set fan speed to 0% if temperature is below startup threshold
} else {
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100); // Calculate fan speed percentage
}
display.setCursor(0, 10);
display.print("Fan%:");
display.setCursor(30, 10);
display.print((int)fanSpeedPct);
// Update the display
display.display();
}
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature C: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
Serial.print(F("Percentage: ")); Serial.println((int)fanSpeedPct);
}
void serial_to_signal_generator() {
// Determine fan speed percentage to send
int speedToSend = (int)fanSpeedPct;
// Ensure fan speed is 0 if temperature is below startup threshold
if (currTemperature < tempForFanStartup) {
speedToSend = 0;
}
// Check the length of fanSpeedPct
if (speedToSend < 10) {
secondSerial.print(F("D00")); // Add "D00" prefix for single-digit fan speed
} else if (speedToSend < 100) {
secondSerial.print(F("D0")); // Add "D0" prefix for double-digit fan speed
} else {
secondSerial.print(F("D")); // Add "D" prefix for triple-digit fan speed
}
secondSerial.print(speedToSend); // Send fan speed
}

View File

@@ -0,0 +1,187 @@
/* Latest running code on the Arduino in the Pontiac as of 06.06.2024 */
/* Added watchdog timer, 4 seconds. */
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <SoftwareSerial.h>
#include <avr/wdt.h>
#include <Fonts/FreeSans9pt7b.h>
#define i2c_Address 0x3C // OLED Adress.
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
float tempForFanStartup = 85.0; // 175 target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 100.0; // 210 target High temp. above this temperature, the fan will be on at full power
float voltsForFanStartup = 2.0; // Roughly the signal voltage that triggers the slowest speed.
const int fanPwmOutPin = 12; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = 7; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
float fanSpeedPct;
OneWire oneWire1 (tempSensorPin);
DallasTemperature sensorClt1(&oneWire1);
const byte rxPin = 2;
const byte txPin = 3;
SoftwareSerial secondSerial (rxPin, txPin);
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned long previousMillis = 0; // Variable to store the last time the serial data was sent
const long interval = 5000; // Interval between serial data transmissions (in milliseconds)
void setup() {
wdt_enable(WDTO_4S);
Serial.begin(115200); // set up serial port for 115200 baud (optional)
if (!display.begin(i2c_Address)) {
Serial.println(F("SH110X allocation failed"));
for (;;);
}
display.clearDisplay();
secondSerial.begin(9600);
delay(500);
secondSerial.print("F20.0");
delay(20);
secondSerial.print("D000");
sensorClt1.begin();
sensorClt1.requestTemperatures();
currTemperature = sensorClt1.getTempCByIndex(0);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
}
void loop() {
unsigned long currentMillis = millis();
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // uncomment this line for testing and calibration to the laptop.
// Check if it's time to send serial data
if (currentMillis - previousMillis >= interval) {
serial_to_signal_generator(); // Send serial data
previousMillis = currentMillis; // Save the last time serial data was sent
}
displayOutput();
wdt_reset();
}
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
//analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
//analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) +.5); // actual PWM duty is calculated here
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100);
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
//analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() {
// Request temperature readings
sensorClt1.requestTemperatures();
// Read the temperature from the sensor
float tempC = sensorClt1.getTempCByIndex(0);
// Check if the temperature reading is within the valid range
if (tempC > -30 && tempC < 130) {
// If the reading is within the valid range, update the current temperature
currTemperature = tempC;
}
// If the reading is outside the valid range, do not update the current temperature
}
void displayOutput() {
display.clearDisplay();
//display.setTextSize(1);
display.setFont(&FreeSans9pt7b);
display.setTextColor(SH110X_WHITE);
// Display temperature on the screen in Celsius with one decimal place
display.setCursor(0, 20);
display.print("Temp:");
display.setCursor(55, 20);
display.print(currTemperature, 1); // Display one decimal place
// Calculate and display fan speed percentage
if (currTemperature < tempForFanStartup) {
fanSpeedPct = 0; // Set fan speed to 0% if temperature is below startup threshold
} else {
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100); // Calculate fan speed percentage
}
display.setCursor(0, 40);
display.print("Fan%:");
display.setCursor(55, 40);
display.print((int)fanSpeedPct);
display.setTextSize(1);
display.setCursor(0, 60);
display.print(" Bolt!");
// Update the display
display.display();
}
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature C: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
Serial.print(F("Percentage: ")); Serial.println((int)fanSpeedPct);
}
void serial_to_signal_generator() {
// Determine fan speed percentage to send
int speedToSend = (int)fanSpeedPct;
// Ensure fan speed is 0 if temperature is below startup threshold
if (currTemperature < tempForFanStartup) {
speedToSend = 0;
}
// Check the length of fanSpeedPct
if (speedToSend < 10) {
secondSerial.print(F("D00")); // Add "D00" prefix for single-digit fan speed
} else if (speedToSend < 100) {
secondSerial.print(F("D0")); // Add "D0" prefix for double-digit fan speed
} else {
secondSerial.print(F("D")); // Add "D" prefix for triple-digit fan speed
}
secondSerial.print(speedToSend); // Send fan speed
}

View File

@@ -0,0 +1,253 @@
/* Latest running code on the Arduino in the Pontiac as of 06.06.2024 */
/* Added watchdog timer, 4 seconds. */
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
//#include <SoftwareSerial.h>
#include <avr/wdt.h>
#define i2c_Address 0x3C // OLED Adress.
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
int M3200address = 0x28; // 0x28, 0x36, or 0x46, depending on the sensor.
float maxPressure = 100; // pressure in PSI for this sensor, 100, 250, 500, ... 10k.
float pressureO;
float temperatureO;
byte status;
float tempForFanStartup = 85.0; // 175 target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 100.0; // 210 target High temp. above this temperature, the fan will be on at full power
float voltsForFanStartup = 2.0; // Roughly the signal voltage that triggers the slowest speed.
const int fanPwmOutPin = 12; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = 7; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
float fanSpeedPct;
OneWire oneWire1 (tempSensorPin);
DallasTemperature sensorClt1(&oneWire1);
/*const byte rxPin = 2;
const byte txPin = 3;
SoftwareSerial secondSerial (rxPin, txPin);*/
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned long previousMillis = 0; // Variable to store the last time the serial data was sent
const long interval = 5000; // Interval between serial data transmissions (in milliseconds)
unsigned long pressureMillis = 0;
const int pressureTiming = 1000; // 500ms every data acquisition
void setup() {
//wdt_enable(WDTO_4S);
Serial.begin(9600); // set up serial port for 115200 baud (optional)
Serial.println("Setup start...");
Wire.begin();
delay(2000);
if (!display.begin(i2c_Address)) {
Serial.println(F("SH110X allocation failed"));
for (;;);
}
display.clearDisplay(); // Clear the display buffer
Serial.println("Starting Dallas DS1820...");
sensorClt1.begin();
sensorClt1.requestTemperatures();
currTemperature = sensorClt1.getTempCByIndex(0);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
//Serial.println("Starting softSerial...");
/*secondSerial.begin(9600);
delay(500);
secondSerial.print("F20.0");
delay(20);
secondSerial.print("D000");*/
Serial.println("Setup done, running loop...");
}
void loop() {
unsigned long currentMillis = millis();
unsigned long pressureMillis = millis();
if (currentMillis - previousMillis >= pressureTiming) {
get_data_from_M3200();
previousMillis = currentMillis;
}
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // uncomment this line for testing and calibration to the laptop.
// Check if it's time to send serial data
/* if (currentMillis - previousMillis >= interval) {
serial_to_signal_generator(); // Send serial data
previousMillis = currentMillis; // Save the last time serial data was sent
}*/
displayOutput();
//wdt_reset();
}
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
//analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
//analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) +.5); // actual PWM duty is calculated here
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100);
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
//analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() {
// Request temperature readings
sensorClt1.requestTemperatures();
// Read the temperature from the sensor
float tempC = sensorClt1.getTempCByIndex(0);
// Check if the temperature reading is within the valid range
if (tempC > -30 && tempC < 130) {
// If the reading is within the valid range, update the current temperature
currTemperature = tempC;
}
// If the reading is outside the valid range, do not update the current temperature
}
void displayOutput() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
// Display temperature on the screen in Celsius with one decimal place
display.setCursor(0, 0);
display.print("Temp:");
display.setCursor(30, 0);
display.print(currTemperature, 1); // Display one decimal place
// Calculate and display fan speed percentage
if (currTemperature < tempForFanStartup) {
fanSpeedPct = 0; // Set fan speed to 0% if temperature is below startup threshold
} else {
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100); // Calculate fan speed percentage
}
display.setCursor(0, 10);
display.print("Fan%:");
display.setCursor(30, 10);
display.print((int)fanSpeedPct);
display.setCursor(0, 30);
display.print("PrsO:");
display.setCursor(30, 30);
display.print(pressureO);
display.setCursor(0, 40);
display.print("TmpO:");
display.setCursor(30, 40);
display.print(temperatureO);
// Update the display
display.display();
}
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature C: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
Serial.print(F("Percentage: ")); Serial.println((int)fanSpeedPct);
}
/*void serial_to_signal_generator() {
// Determine fan speed percentage to send
int speedToSend = (int)fanSpeedPct;
// Ensure fan speed is 0 if temperature is below startup threshold
if (currTemperature < tempForFanStartup) {
speedToSend = 0;
}
// Check the length of fanSpeedPct
if (speedToSend < 10) {
secondSerial.print(F("D00")); // Add "D00" prefix for single-digit fan speed
} else if (speedToSend < 100) {
secondSerial.print(F("D0")); // Add "D0" prefix for double-digit fan speed
} else {
secondSerial.print(F("D")); // Add "D" prefix for triple-digit fan speed
}
secondSerial.print(speedToSend); // Send fan speed
}*/
void get_data_from_M3200() {
Wire.requestFrom(M3200address, 4); // request 4 bytes
int n = Wire.available();
if (n == 4) {
status = 0;
uint16_t rawP; // pressure data from sensor
uint16_t rawT; // temperature data from sensor
rawP = (uint16_t) Wire.read(); // upper 8 bits
rawP <<= 8;
rawP |= (uint16_t) Wire.read(); // lower 8 bits
rawT = (uint16_t) Wire.read(); // upper 8 bits
rawT <<= 8;
rawT |= (uint16_t) Wire.read(); // lower 8 bits
status = rawP >> 14; // The status is 0, 1, 2, or 3
rawP &= 0x3FFF; // keep 14 bits, remove status bits
rawT >>= 5; // the lowest 5 bits are not used
float pressure = ((rawP - 1000.0) / (15000.0 - 1000.0)) * maxPressure;
float temperature = ((rawT - 512.0) / (1075.0 - 512.0)) * 55.0;
temperatureO = temperature;
pressureO = pressure;
Serial.println("--- Values from M3200 ---");
Serial.println(temperature);
Serial.println(pressure);
} else {
Serial.println("M3200 Pressure Transducer not Detected");
}
}

View File

@@ -0,0 +1,247 @@
/* Latest DinoFan 19.06.2024-001
Added watchdog timer, 4 seconds.
Removed SoftSerial since it interferred with Wire.h
Added M3200 sensor for oil temp and pressure. */
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <avr/wdt.h>
#define i2c_Address 0x3C // OLED Adress.
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
int M3200address = 0x28; // 0x28, 0x36, or 0x46, depending on the sensor.
float maxPressure = 100; // pressure in PSI for this sensor, 100, 250, 500, ... 10k.
float pressure;
float temperature;
byte status;
float tempForFanStartup = 85.0; // 175 target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 100.0; // 210 target High temp. above this temperature, the fan will be on at full power
float voltsForFanStartup = 2.0; // Roughly the signal voltage that triggers the slowest speed.
const int fanPwmOutPin = 12; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = 7; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
float fanSpeedPct;
OneWire oneWire1 (tempSensorPin);
DallasTemperature sensorClt1(&oneWire1);
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned long previousMillis = 0; // Variable to store the last time the serial data was sent
const long interval = 5000; // Interval between serial data transmissions (in milliseconds)
unsigned long previous2Millis = 0;
const int pressureTiming = 1000; // 500ms every data acquisition
void setup() {
wdt_enable(WDTO_4S);
Serial.begin(9600);
Wire.begin();
if (!display.begin(i2c_Address)) {
Serial.println(F("SH110X allocation failed"));
for (;;);
}
display.clearDisplay(); // Clear the display buffer
sensorClt1.begin();
sensorClt1.requestTemperatures();
currTemperature = sensorClt1.getTempCByIndex(0);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
delay(500);
Serial.print("F20.0");
delay(20);
Serial.print("D000");
}
void loop() {
unsigned long currentMillis = millis();
unsigned long pressureMillis = millis();
//Pull data from M3200 every second.
if (pressureMillis - previous2Millis >= pressureTiming) {
get_data_from_M3200();
previous2Millis = pressureMillis;
}
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // uncomment this line for testing and calibration to the laptop.
// Check if it's time to send serial data
if (currentMillis - previousMillis >= interval) {
serial_to_signal_generator(); // Send serial data
previousMillis = currentMillis; // Save the last time serial data was sent
}
displayOutput();
wdt_reset();
}
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
//analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
//analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) +.5); // actual PWM duty is calculated here
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100);
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
//analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() {
// Request temperature readings
sensorClt1.requestTemperatures();
// Read the temperature from the sensor
float tempC = sensorClt1.getTempCByIndex(0);
// Check if the temperature reading is within the valid range
if (tempC > -30 && tempC < 130) {
// If the reading is within the valid range, update the current temperature
currTemperature = tempC;
}
// If the reading is outside the valid range, do not update the current temperature
}
void displayOutput() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
// Display temperature on the screen in Celsius with one decimal place
display.setCursor(12, 0);
display.print("Pontiac LeMans '69");
display.drawLine(2, 10, 126, 10, SH110X_WHITE);
display.setCursor(0, 16);
display.print("Water temp:");
display.setCursor(70, 16);
display.print(currTemperature, 1); // Display one decimal place
display.print(" C");
// Calculate and display fan speed percentage
if (currTemperature < tempForFanStartup) {
fanSpeedPct = 0; // Set fan speed to 0% if temperature is below startup threshold
} else {
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100); // Calculate fan speed percentage
}
display.setCursor(0, 26);
display.print("Fan Speed :");
display.setCursor(70, 26);
display.print((int)fanSpeedPct);
display.print(" %");
display.setCursor(0, 46);
display.print("Oil Pressr:");
display.setCursor(70, 46);
display.print(pressure, 1);
display.print(" b");
display.setCursor(0, 56);
display.print("Oil Temp :");
display.setCursor(70, 56);
display.print(temperature, 1);
display.print(" C");
// Update the display
display.display();
}
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature C: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
Serial.print(F("Percentage: ")); Serial.println((int)fanSpeedPct);
}
void serial_to_signal_generator() {
// Determine fan speed percentage to send
int speedToSend = (int)fanSpeedPct;
// Ensure fan speed is 0 if temperature is below startup threshold
if (currTemperature < tempForFanStartup) {
speedToSend = 0;
}
// Check the length of fanSpeedPct
if (speedToSend < 10) {
Serial.print(F("D00")); // Add "D00" prefix for single-digit fan speed
} else if (speedToSend < 100) {
Serial.print(F("D0")); // Add "D0" prefix for double-digit fan speed
} else {
Serial.print(F("D")); // Add "D" prefix for triple-digit fan speed
}
Serial.print(speedToSend); // Send fan speed
}
void get_data_from_M3200() {
Wire.requestFrom(M3200address, 4); // request 4 bytes
int n = Wire.available();
if (n == 4) {
status = 0;
uint16_t rawP; // pressure data from sensor
uint16_t rawT; // temperature data from sensor
rawP = (uint16_t) Wire.read(); // upper 8 bits
rawP <<= 8;
rawP |= (uint16_t) Wire.read(); // lower 8 bits
rawT = (uint16_t) Wire.read(); // upper 8 bits
rawT <<= 8;
rawT |= (uint16_t) Wire.read(); // lower 8 bits
status = rawP >> 14; // The status is 0, 1, 2, or 3
rawP &= 0x3FFF; // keep 14 bits, remove status bits
rawT >>= 5; // the lowest 5 bits are not used
pressure = ((rawP - 1000.0) / (15000.0 - 1000.0)) * maxPressure;
temperature = ((rawT - 512.0) / (1075.0 - 512.0)) * 55.0;
// Serial.println("--- Values from M3200 ---");
// Serial.println(temperature);
// Serial.println(pressure);
} else {
Serial.println("M3200 Pressure Transducer not Detected");
}
}

View File

@@ -0,0 +1,192 @@
/* -- DinoCool --- */
/* Latest running code on the Arduino in the Pontiac as of 06.06.2024 */
/* Added watchdog timer, 4 seconds. */
/* Will add MT3200 oil pressure and temp sensor */
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <SoftwareSerial.h>
#include <avr/wdt.h>
#define i2c_Address 0x3C // OLED Adress.
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
float tempForFanStartup = 85.0; // 175 target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 100.0; // 210 target High temp. above this temperature, the fan will be on at full power
float voltsForFanStartup = 2.0; // Roughly the signal voltage that triggers the slowest speed.
const int fanPwmOutPin = 12; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = 7; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
float fanSpeedPct;
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
OneWire oneWire1 (tempSensorPin);
DallasTemperature sensorClt1(&oneWire1);
const byte rxPin = 2;
const byte txPin = 3;
SoftwareSerial secondSerial (rxPin, txPin);
unsigned long previousMillis = 0; // Variable to store the last time the serial data was sent
const long interval = 5000; // Interval between serial data transmissions (in milliseconds)
void setup() {
//wdt_enable(WDTO_4S);
Serial.begin(9600); // set up serial port for 115200 baud (optional)
Serial.println("Initializing second serial...");
secondSerial.begin(9600);
delay(500);
secondSerial.print("F20.0");
delay(20);
secondSerial.print("D000");
Serial.println("Initializing DS1820 sensors...");
sensorClt1.begin();
sensorClt1.requestTemperatures();
currTemperature = sensorClt1.getTempCByIndex(0);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
Serial.println("Initializing OLED...");
if (!display.begin(i2c_Address)) {
Serial.println(F("SH110X allocation failed"));
for (;;);
}
display.clearDisplay();
display.display();
Serial.println("Setup done...");
}
void loop() {
unsigned long currentMillis = millis();
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // uncomment this line for testing and calibration to the laptop.
// Check if it's time to send serial data
if (currentMillis - previousMillis >= interval) {
serial_to_signal_generator(); // Send serial data
previousMillis = currentMillis; // Save the last time serial data was sent
}
displayOutput();
wdt_reset();
}
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
//analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
//analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) +.5); // actual PWM duty is calculated here
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100);
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
//analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() {
// Request temperature readings
sensorClt1.requestTemperatures();
// Read the temperature from the sensor
float tempC = sensorClt1.getTempCByIndex(0);
// Check if the temperature reading is within the valid range
if (tempC > -30 && tempC < 130) {
// If the reading is within the valid range, update the current temperature
currTemperature = tempC;
}
// If the reading is outside the valid range, do not update the current temperature
}
void displayOutput() {
display.clearDisplay();
display.setTextSize(1);
//display.setFont(&FreeSans9pt7b);
display.setTextColor(SH110X_WHITE);
// Display temperature on the screen in Celsius with one decimal place
display.setCursor(0, 20);
display.print("Temp:");
display.setCursor(55, 20);
display.print(currTemperature, 1); // Display one decimal place
// Calculate and display fan speed percentage
if (currTemperature < tempForFanStartup) {
fanSpeedPct = 0; // Set fan speed to 0% if temperature is below startup threshold
} else {
fanSpeedPct = map(pwmDuty, 0, 255, 0, 100); // Calculate fan speed percentage
}
display.setCursor(0, 40);
display.print("Fan%:");
display.setCursor(55, 40);
display.print((int)fanSpeedPct);
display.setTextSize(1);
display.setCursor(0, 60);
display.print("Bolt");
// Update the display
display.display();
}
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature C: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
Serial.print(F("Percentage: ")); Serial.println((int)fanSpeedPct);
}
void serial_to_signal_generator() {
// Determine fan speed percentage to send
int speedToSend = (int)fanSpeedPct;
// Ensure fan speed is 0 if temperature is below startup threshold
if (currTemperature < tempForFanStartup) {
speedToSend = 0;
}
// Check the length of fanSpeedPct
if (speedToSend < 10) {
secondSerial.print(F("D00")); // Add "D00" prefix for single-digit fan speed
} else if (speedToSend < 100) {
secondSerial.print(F("D0")); // Add "D0" prefix for double-digit fan speed
} else {
secondSerial.print(F("D")); // Add "D" prefix for triple-digit fan speed
}
secondSerial.print(speedToSend); // Send fan speed
}