// Include required libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <PWM.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Initialize OLED display object
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Define constants for pins and values
const int FAN_PIN = 9; //Fan output pin
const int TEMP_SENSOR_PIN = A1; //Temp sensor pin
const int POT_PIN = A2; //Potentiometer pin
const int buttonPin = 11; //Momentary switch pin
const int MIN_TEMP = 160; //Minimum duty cycle temperature
const int MAX_TEMP = 210; //Maximum duty cycle temperature
const int MIN_DUTY = 89; //Minimum duty cycle percentage
const int MAX_DUTY = 9; //Maximum duty cycle percentage
const int DUTY_INCREMENT = 1; //Duty cycle percentage increments
const int POT_RANGE = 10000; //Potentiometer resistance
// Define variables for current values
int current_duty = 0; //Current duty cycle
int current_screen = 1; //Current screen (may be deleted)
int current_pot_value = 0; //Current raw potentiometer value
int mapped_pot = 0; //Potentiometer values mapped to range of pMin to pMax
int pMin = -20; //Minimum temperature variation for minimum potentiometer value
int pMax = 20; //Maximum temperature variation for maximum potentiometer value
int current_temp_sensor = 0; //Current raw temperature sensor output
int mapped_temp = 0; //Temperature sensor values mapped to Fahrenheit range
int tuned_MIN_TEMP = 0; //Minimum temp range after modification by potentiometer value
int tuned_MAX_TEMP = 0; //Maximum temp range after modification by potentiometer value
int buttonPushCounter = 0; //Counter for the number of button presses
boolean buttonState = LOW; //Current state of the button
boolean lastButtonState = LOW; //Previous state of the button
// Set PWM Frequency
int32_t frequency = 100; //Frequency (in Hz)
// Define function for updating the duty cycle based on temperature and potentiometer
void update_duty() {
if (mapped_temp < MIN_TEMP) {
current_duty = 0;
} else if (mapped_temp > MAX_TEMP) {
current_duty = MAX_DUTY;
} else {
int pot_adjust = (current_pot_value) / (POT_RANGE / 60);
current_duty = MIN_DUTY + (MAX_DUTY - MIN_DUTY) * (mapped_temp - tuned_MIN_TEMP + pot_adjust) / (tuned_MAX_TEMP - tuned_MIN_TEMP);
current_duty = round(current_duty / DUTY_INCREMENT) * DUTY_INCREMENT;
}
analogWrite(FAN_PIN, round(current_duty * 255.0 / 100.0));
}
void setup() {
// Initialize serial communication
Serial.begin(9600);
// Set up momentary switch as input
pinMode(buttonPin, INPUT_PULLUP);
// Initialize OLED display
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
//Prepare Timers for PWM frequency on FAN_PIN, activate onboard LED (pin 13) if successful
InitTimersSafe();
bool success = SetPinFrequencySafe(FAN_PIN, frequency);
if(success) {
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}
// *DELETE SOON* Set up fan output pin and set initial duty cycle
// pinMode(FAN_PIN, OUTPUT);
// update_duty();
}
void loop() {
// Read current potentiometer value
current_pot_value = analogRead(POT_PIN);
//Map potentiometer data to a range from negative (-)30 to +30, a simple variable added or subtracted to the commanded temperature range
mapped_pot = map(current_pot_value, 1023, 0, pMin, pMax);
tuned_MIN_TEMP = (MIN_TEMP + mapped_pot);
tuned_MAX_TEMP = (MAX_TEMP + mapped_pot);
// Read current temperature sensor value
current_temp_sensor = analogRead(TEMP_SENSOR_PIN); //Raw unmapped temp sensor data
//Map voltages from temp sensor to Fahrenheit. First two numbers are ohms resistance, second two numbers are correlating temp in Fahrenheit
mapped_temp = map(current_temp_sensor, 497, 78, 63, 212);
//Output PWM to FAN_PIN based on calculated duty cycle
pwmWrite(FAN_PIN, round(current_duty * 255.0 / 100.0));
// Read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
Serial.println(current_temp_sensor);
Serial.println(mapped_temp);
switch (buttonPushCounter) // choose what to display based on buttonPushCounter value
{
case 0:
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(0, 10);
display.print("RG:");
display.print(tuned_MIN_TEMP) ;
display.print("-") ;
display.println(tuned_MAX_TEMP);
display.display();
break;
case 1:
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(0, 10);
// Display static text
display.print("C.Temp:");
display.println(mapped_temp);
display.display();
break;
case 2:
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(0, 10);
// Display static text
display.print("C.Duty:");
display.println(current_duty);
display.display();
break;
}
if (buttonState != lastButtonState)
{
if (buttonState == HIGH)
{
// if the current state is HIGH then the button
// went from off to on:
buttonPushCounter++; // add one to counter
display.clearDisplay();
display.display();
if (buttonPushCounter > 2)
{
buttonPushCounter = 0;
}
}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonState;
}
}