#define aref_voltage 3.3
int min_temp = 30;
int max_temp = 50;
int led = 13; //Optional output LED
int temp = A0; //Middle pin of tmp36 thermistor
int blinkDuration = 0;
unsigned long lastBlinkTime;
boolean blinkOn = false;
volatile byte half_revolutions;
unsigned int rpm;
long rpmLastTime = 0;
long senseDelay = 0;
int workInterval = 1000;
float tempC;
int fanPWM = 10;
int fanDutyCycle = 0;
int fanTransistor = 7;
/* Bubble Declarations */
int datapin = 4;
int clockpin = 5;
int latchpin = 6;
const int db = 10;
const int CapC = 11;
const int blank = 12;
const int cathodesOn = 4;
const int cathodesOff = 5;
//int cathodes[] = {8, 9, 10, 11};
byte digits[] = {
0b11111100, // 0
0b01100000, // 1
0b11011010, // 2
0b11110010, // 3
0b01100110, // 4
0b10110110, // 5
0b10111110, // 6
0b11100000, // 7
0b11111110, // 8
0b11110110, // 9
0b00000001, // decimal point (11)
0b10011100, // Letter C (12)
0b00000000 // Blank
};
byte cathodes[] = {
0b11111110, // 1
0b11111101, // 2
0b11111011, // 3
0b11110111, // 4
0b11111111, //cathodes on (all led's off)
0b00000000 //cathodes off
};
/* flag to decide whether to show temp or RPM, flips every second */
bool isTemp = true;
void rpm_interrupt() {
half_revolutions++;
//Each rotation, this interrupt function is run twice
}
// the setup routine runs once when you press reset:
void setup() {
analogReference(EXTERNAL); //Sets the AREF pin to 3.3V
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(fanPWM, OUTPUT);
pinMode(fanTransistor, OUTPUT);
pinMode(led, OUTPUT);
//Make A0 the analogue thermistor input
pinMode(temp, INPUT);
// function 'rpm' will be called when the rpm_sense pin goes high
attachInterrupt(0, rpm_interrupt, FALLING);
half_revolutions = 0;
rpm = 0;
// Bubble Setup
pinMode(datapin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(latchpin, OUTPUT);
digitalWrite(datapin, HIGH);
digitalWrite(clockpin, HIGH);
digitalWrite(latchpin, HIGH);
//set the timer variables
rpmLastTime = millis();
lastBlinkTime = millis();
}
// the loop routine runs over and over again forever:
void loop() {
long actualTicks = half_revolutions;
//depending on the speed of the fan, the blink rate is 'mapped' to a different scale
//so when the rate goes from 85-255, the blink millisecond time goes from 500-25
//The faster the fan, the shorter the duration, so the faster the blink effect
blinkDuration = map(fanDutyCycle, 85, 255, 500, 25);
cathodesHigh(); // reset bubble display
//Do the LED flashing
// blinkOn is effectively the same as fanOn - the transistor is open
if (blinkOn) {
if (isTemp) {
displayTemp(tempC);
} else {
displayRPM(rpm);
}
if (millis() - lastBlinkTime >= blinkDuration) {
digitalWrite(led, !digitalRead(led));
lastBlinkTime = millis();
}
} else {
if (digitalRead(led) == HIGH) {
digitalWrite(led, LOW);
}
}
//PWM Sensing
long timeElapsed = (millis() - senseDelay);
if (timeElapsed > workInterval) {
//this code only fires every second
//RPM work
detachInterrupt(0);
rpm = actualTicks * 30; //two ticks per rev
half_revolutions = 0;
attachInterrupt(0, rpm_interrupt, FALLING);
isTemp = !isTemp;
//Do temperature work
//This should possibly be done outside the 1 second block, and averaged to smooth the results
int tempreading = analogRead(temp);
float temp_v = tempreading * aref_voltage; //3.3V
temp_v /= 1024.0;
Serial.write("TEMP_V: ");
Serial.print(temp_v);
Serial.write("V\n");
tempC = (temp_v - 0.5) * 100;
Serial.write("TEMP: ");
Serial.print(tempC);
Serial.write(" degrees C\n");
fanDutyCycle = map(constrain(tempC, min_temp, max_temp), min_temp, max_temp, 80, 255);
// This is the clever bit - because the constrain is mapped to 80 - 255, then
// when the temp is on or below min_temp, then the contrains sets the value to 80, which is NOT enough to get
// into the if > 85 block just below
//Fan Speed
analogWrite(fanPWM, fanDutyCycle);
if (fanDutyCycle >= 85) {
blinkOn = true;
digitalWrite(fanTransistor, HIGH);
Serial.println("Transistor High");
} else {
blinkOn = false;
digitalWrite(fanTransistor, LOW);
Serial.println("Transistor Low");
}
senseDelay = millis();
}
delay(1); // delay in between reads for stability
}
void cathodesHigh()
{
writeByte(cathodes[cathodesOn], digits[blank]);
}
void writeByte(byte cathode, byte data)
{
shiftOut(datapin, clockpin, LSBFIRST, cathode);
shiftOut(datapin, clockpin, LSBFIRST, data);
// toggle the latch pin so that the data appears as an output
digitalWrite(latchpin, HIGH);
digitalWrite(latchpin, LOW);
}
void displayTemp(float temp)
{
//make into whole number
int tempTemp = (round(temp * 10) / 10.0) * 10;
int pos = 1;
while (tempTemp) {
int digit = tempTemp % 10;
if (pos == 2) {
writeByte(cathodes[pos], digits[digit] + 1);
}
else
{
writeByte(cathodes[pos], digits[digit]);
}
tempTemp /= 10;
pos ++;
delay(1);
}
//letter C
writeByte(cathodes[0], digits[CapC]);
delay(1);
}
void displayRPM(int rpm)
{
int rpmTemp = rpm;
int pos = 0;
while (rpmTemp) {
int digit = rpmTemp % 10;
writeByte(cathodes[pos], digits[digit]);
delay(5);
rpmTemp /= 10;
pos ++;
}
}