/*
Project Pinout:
* Digital Pins;
* pin 0 Serial Printing
* pin 1 Serial Printing
* LCD D7 pin to digital pin 2 (intrrupt pin)
* LCD D6 pin to digital pin 3 (intrrupt pin)
* LCD D5 pin to digital pin 4
* LCD D4 pin to digital pin 5
* relay control digital pin 6
* tempSense digital pin 7
* RPM Interupt digital pin 8
* PWM Fan01 digital pin 9
* PWM Fan02 digital pin 10
* LCD Enable pin to digital pin 11
* LCD RS pin to digital pin 12
* Frequency ok, flash lcd pin 13
* LCD R/W pin to ground
* 10K resistor for LED +V
* ends to +5V and ground
* 10K pot to LCD VO pin (pin 3)
* Analog Pins;
pin A0
pin A1
pin A2
pin A3
* Smoke Sensor Buzzer/LED pin A4
* Smoke Sensor pin A5
*/
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
//#include <PWM.h>
#include <PinChangeInterrupt.h>
// Definitions
#define ONE_WIRE_BUS 7 // Data wire is plugged into pin 7 on the Arduino
#define RPM01Pin 8 // Set pin 8 as an interrupt pin
// Instance Setup
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
// Variables
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; // LCD Pinouts
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
float Calc01;
float tempSenseArray[3];
float tempSenseAve = 0;
int NbTopsFan01;
int PWMFan01 = 9;
int PWMFan02 = 10;
//int buzzPin = A4;
int smokePin = A5; // Smoke sensor pin selection
int sensorThres = 400; // Your threshold value
int relayCont = 6; // Relay control pin
int numberOfDevices;
DeviceAddress tempDeviceAddress;
/*
// Structure for Fan RPM read
typedef struct
{ // Defines the structure for multiple fans and their dividers
char fantype;
unsigned int fandiv;
}
fanspec; // Definitions of the fans. This is the varible used to select the fan and it's divider, set 1 for unipole hall effect sensor, and 2 for bipole hall effect sensor
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
char fan01 = 2;
char fan02 = 2;
*/
int32_t frequency = 25000; // 25KHz
// ********************** RPM *************************
// This is the function that the interupt calls for fan RPM read
void rpm01 () {
NbTopsFan01++;
//Serial.println("Fan01 Check");
}
// ******************* END RPM *************************
// ********************* SETUP *************************
void setup() {
// start serial port
//Serial.begin(9600);
Serial.begin(115200);
Serial.println("Fan / Power Control using Temperature and Smoke Sensors");
// Setup Dallas Library
sensors.begin();
// Grab a count of devices on the wire
numberOfDevices = sensors.getDeviceCount();
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(numberOfDevices, DEC);
Serial.println(" devices.");
// Loop through each device, print out address
for(int i=0;i<numberOfDevices; i++){
// Search the wire for address
if(sensors.getAddress(tempDeviceAddress, i)){
Serial.print("Found device ");
Serial.print(i, DEC);
Serial.print(" with address: ");
Serial.print(tempDeviceAddress[i]);
//printAddress(tempDeviceAddress);
Serial.println();
} else {
Serial.print("Found ghost device at ");
Serial.print(i, DEC);
Serial.print(" but could not detect address. Check power and cabling");
}
}
// Setup LCD
lcd.begin(16, 2); // Start LCD, columns and rows for display
lcd.display(); // Turn on the lcd display
lcd.setCursor(0,0); // Sets the location at which subsequent text written to the LCD will be displayed
lcd.print("Fan/PowerControl"); // Print a message to the LCD.
lcd.setCursor(0,1); // Set cursor placement
lcd.print("w/Temp/Smoke Sen"); // Print
delay(2000);
lcd.clear(); // Clear LCD
lcd.setCursor(0, 0); // Reset cursor placement
lcd.print("T-1/T-2/T-3/T-Av"); // Print
lcd.setCursor(0, 1); // Reset cursor placement
lcd.print("Fan RPM / Smoke Sen"); // Print
delay(2000);
// Set Fan PWM frequency
pinMode(PWMFan01,OUTPUT); // Setup Fan PWM to Output
pinMode(PWMFan02,OUTPUT); // Setup Fan PWM to Output
pinMode(13,OUTPUT); // Set Pin 13 as output to light LED
//InitTimersSafe(); // Makes the other pins lock at normal freqs
/*
bool success01 = SetPinFrequency(PWMFan01, frequency); // Set Fan01 PWM pin to 25KHz
if(success01) { // Test then show a blinking LED if its set correctly
// for(int i = 0; i < 2; i++) {
// digitalWrite(13,HIGH);
// delay(500);
// digitalWrite(13,LOW);
// delay(500);
// }
Serial.println("PWM Frequency for Fan 01 is set at 25 kHz");
}
bool success02 = SetPinFrequency(PWMFan02, frequency); // Set Fan02 PWM pin to 25KHz
if(success02) { // Test then show a blinking LED if its set correctly
// for(int j = 0; j < 2; j++) {
// digitalWrite(13,HIGH);
// delay(500);
// digitalWrite(13,LOW);
// delay(500);
// }
Serial.println("PWM Frequency for Fan 02 is set at 25 kHz");
}
*/
// Setup Fan RPM read
pinMode(RPM01Pin, INPUT); // Set inturrupt pin with pullup
attachPinChangeInterrupt(RPM01Pin, rpm01, CHANGE); // Set interrupt to read TACH signal from fan
// Setup Smoke Detector Pin
pinMode(relayCont, OUTPUT); // Set relay Control Pin as output
//pinMode(buzzPin, OUTPUT); // Set buzzer pin as output
pinMode(smokePin, INPUT); // Set smoke sensor pin as input
}
// ***************** END SETUP *************************
void loop() {
Serial.print("Requesting temperatures..."); // Print
sensors.requestTemperatures(); // call sensors.requestTemperatures() to issue a global temperature request to all devices on the bus
Serial.print(" DONE\r\n"); // Print
noInterrupts(); // mask interrupts to ensure both bytes of the int can be set atomicly
NbTopsFan01 = 0; // Reset RPM reading
interrupts(); // re-enable interrupts
//delay(500);
//lcd.clear(); // Clear LCD
lcd.setCursor(0, 0); // Reset cursor placement
// lcd.print("T-1/T-2/T-3/T-Av"); // Print
int crsLoc = 0; // Create variable for cursor placement in for loop below
// Print temp readings on serial and LCD based on index in thermal sensor chain
for(int k = 0; k < 3; k++) {
Serial.print("Temperature is: "); // Print
Serial.println(sensors.getTempCByIndex(k)); // You can have more than one DS18B20 on the same bus. 0 refers to the first IC on the wire
//float tempC = sensors.getTempCByIndex(k);
//Serial.println(tempC);
lcd.setCursor(crsLoc, 0); // Reset cursor placement
lcd.print(long(sensors.getTempCByIndex(k))); // Print temp of sensor k in array
tempSenseArray[k]=sensors.getTempCByIndex(k); // Add values to array
crsLoc = crsLoc + 3;
//delay(10);
}
// Calculate the average of all 3 seonsors
tempSenseAve = (tempSenseArray[0]+tempSenseArray[1]+tempSenseArray[2])/3; // Calculate average temp
//tempSenseAve = 26; // Used for testing RPM calculation
Serial.print("Ave Temperature is: "); // Print
Serial.println(tempSenseAve); // Print ave temperature
lcd.setCursor(crsLoc, 0); // Print
lcd.print(tempSenseAve); // Print ave temperature
//delay(10);
/*/ Set fan speed curves, 30 lowest, 40, 60, 75, 85, 98 max, Speed 400 - 2000 RPM
if(tempSenseAve <= 27){ // @ 80.6 deg F, Duty Cycle: 0%, PWM Value: 0, Actual<> Freq: 14.34 Hz, RPM: 430.2, NbTopsFan01: 126
pwmWrite(PWMFan01,70); // @ > 80.6 deg F, Duty Cycle: 29%, PWM Value: 70, Actual<> Freq: 18 Hz, RPM: 540, NbTopsFan01: 157
pwmWrite(PWMFan02,70);
}
else if (tempSenseAve > 27 && tempSenseAve <= 30){
pwmWrite(PWMFan01,120); // @ 80.6 - 86.0 deg F, Duty Cycle: 39%, PWM Value: 120, Actual<> Freq: 32.5 Hz, RPM: 975, NbTopsFan01: 300
pwmWrite(PWMFan02,120);
}
else if (tempSenseAve > 30 && tempSenseAve <= 32){
pwmWrite(PWMFan01,150); // @ 86.0 - 89.6 deg F, Duty Cycle: 59%, PWM Value: 150, Actual<> Freq: 43.3 Hz, RPM: 1299, NbTopsFan01: 378
pwmWrite(PWMFan02,150);
}
else if (tempSenseAve > 32 && tempSenseAve <= 34){
pwmWrite(PWMFan01,190); // @ 89.6 - 93.2 deg F, Duty Cycle: 75%, PWM Value: 190, Actual<> Freq: 53.4 Hz, RPM: 1602, NbTopsFan01: 470
pwmWrite(PWMFan02,190);
}
else if (tempSenseAve > 34 && tempSenseAve <= 36){
pwmWrite(PWMFan01,217.5); // @ 93.2 - 96.8 deg F, Duty Cycle: 85%, PWM Value: 217.5, Actual<> Freq: 60 Hz, RPM: 1800, NbTopsFan01: 525
pwmWrite(PWMFan02,217.5);
}
else {
pwmWrite(PWMFan01,250); // @ > 98.6 deg F, Duty Cycle: 98%, PWM Value: 250, Actual<> Freq: 67 Hz, RPM: 2010, NbTopsFan01: 585
pwmWrite(PWMFan02,250);
} // @ 98.6 deg F, Duty Cycle: 100%, PWM Value: 255, Actual<> Freq: 67.5 Hz, RPM: 2025, NbTopsFan01: 590
*/
// sei(); //Enables interrupts
// delay(1000);
// cli(); //Disable interrupts
//Serial.print("NbTopsFan01++ : "); // Used for testing RPM calculation
//Serial.println(NbTopsFan01++); // Used for testing RPM calculation
//Calculate Fan speed based on NbTopsFan01 value and equation derived taking readings over the range of fan speeds +/-10%
noInterrupts(); // disable interrupts so calculation sees a stable atomic NbTopsFan value
Calc01 = (3.45175497934708*NbTopsFan01) - 15.7806050419629; // Fan RPM calculation
interrupts(); // re-enable interrupts.
Calc01 = int(Calc01);
// Serial.print(Calc01, DEC); //Prints the number calculated above
Serial.print(Calc01); //Prints the number calculated above
Serial.print(" Fan 1 RPM\r\n"); //Prints " rpm" and a new line
//delay(1500);
// lcd.clear(); // Clear LCD
lcd.setCursor(0, 1); // Reset cursor placement
lcd.print("RPM: "); // Print
lcd.setCursor(5, 1); // Reset cursor placement
lcd.print(Calc01); // Print Fan speed in RPM
lcd.setCursor(8, 1); // Reset cursor placement
lcd.print(" "); // Print
//delay(10);
int analogSensor = analogRead(smokePin); // Read Smoke Sensor
//int analogSensor = 500;
Serial.print("Smoke Sensor: "); // Prints out reading of sensor
Serial.println(analogSensor); // Prints out reading of sensor
lcd.setCursor(8, 1); // Reset cursor placement
lcd.print(" SM: "); // Print
lcd.setCursor(13, 1); // Reset cursor placement
lcd.print(analogSensor); // Print Smoke Sensor Value
if (analogSensor > sensorThres) {
digitalWrite(relayCont,LOW);
//tone(buzzPin, 500, 300); // alarm
//tone(buzzPin, 1000, 600);
//tone(buzzPin, 1500, 1200);
}
else {
digitalWrite(relayCont,HIGH);
//noTone(buzzPin);
}
delay(2000);
}