Controller
I chose to use a shield (add-on board) to house all the parts for this project that allows the use of any standard Arduino and settled on a Seeeduino V3.0 and a Freetronics prototype shield as an inexpensive solution.
I used the controller and shield to for the previous variable wiper speed project for the car (“Wipe that classic windscreen,” Shed, Apr/May 2012). This second part uses the same controller and shield to do both tasks. The reader can either make one or both. The shield construction includes the extra parts (two resistors, one transistor, and one diode) and uses the “Start” button to do the “Normal” calibration.
Here are the two sketches (software) in these The Shed website’s two posts.
- one combining water temperature light and variable wiper functions into one controller; and
- one that just does the water temperature light.
Sketche One
Automotive series, Intermittant Wiper
console.log( 'Code is Poetry' );
/*
Automotive Series
Intermittant Wiper
Flags for the various modes in Intelligent Temp Light are used, to allow the controller to service the other functions.
Pin assignments
Pin 0 Rx
Pin 1 Tx
Pin 2 Wiper Relay Ouput
Pin 3
Pin 4
Pin 5 Stop Button Input
Pin 6 Start Button Input
Pin 10
Pin 13 Led
Pin A0
Pin A4
Created Dec 2011
by Mark Beckett
Version
1.0 Initial Code completed Dec 2011
---------------------------------------------------
To Do :
*/
// General Purpose
int IntWipe = 0; // Flag to show we mode we are in. 0= off, 1= first press, 2= 2nd press.
int LedState = LOW; // ledState used to set the LED
unsigned long WipeInterval = 0; // Time between wipes as set by start/stop action [x secs]
unsigned long LastWipeTime =0; // Time the last wipe was started.
unsigned long TimerTime =0; // used in Timer(), = millis()-LastWipeTime.
int ButtonTimeout = 30; // Timeout if no button is pressed. Note wipe interval is lower than this. [30 seconds]
int RelayOnTime = 1500; // Time the relay is held on to perform a single wipe. [1.5 secs]
boolean WiperRelayState = LOW; // Relay Output state
// Button handling variables
unsigned long LastButtonCheck = 0; // Time the Buttons were last checked.
unsigned long ButtonPressTime = 0; // Time the last button was pressed.
boolean StartButtonState = HIGH; // records the StartButton State
int StartCount = 0; // Start Button counter
boolean StopButtonState = HIGH; // records the StopButton State
int StopCount = 0; // Stop Button counter
//inputs
int StartButton = 4;
int StopButton = 5;
int CalButton = 6;
int val = 0;
//Outputs
int WiperRelay = 2; // Wiper relay output
const int LEDPin = 13; // Pin 13 LED Output
//Settings
/*
Default values for the intermittant wiper
Button timeout = 30 secs
ON time for relay = 1.5 secs
*/
//-------------------------------------------------------------------------
void setup()
{
Serial.begin(115200);
//Define the inputs
pinMode (StartButton, INPUT);
digitalWrite (StartButton, HIGH);
pinMode (StopButton, INPUT);
digitalWrite (StopButton, HIGH);
//Define the outputs
pinMode(LEDPin, OUTPUT);
pinMode(WiperRelay, OUTPUT);
ButtonTimeout = ButtonTimeout *1000; // Convert secs to milliseconds
//RelayOnTime = RelayOnTime *1000; // Convert secs to milliseconds
}
void loop()
{
Check_Buttons(); //used for Int wiper
Timer(); //See what is needed to be done
}
void Timer()
{
// This controls the various routines and calls them as necessary
TimerTime = millis() - LastWipeTime;
if (((millis()-ButtonPressTime) > ButtonTimeout) && (IntWipe == 1)) // 30 Sec timeout for no button press, but only after stopped, or 1 start.
{
IntWipe = 0;
LastWipeTime = 0;
WipeInterval = 0;
}
// The SingleWipe() will be called when the start button is pressed, we need to turn the relay off.
if ((TimerTime > RelayOnTime) && WiperRelayState == true) // RelayOnTime has been exceeded AND WipeRelay is HIGH
{
SingleWipe(); // It will turn off the relay and not modify any variables
}
// Time to wipe but only if there is a WipeInterval AND the relay is off.
if ((TimerTime > WipeInterval) && (IntWipe == 2) && WiperRelayState == false)
{
SingleWipe();
}
}
void Check_Buttons()
{
if (millis() - LastButtonCheck > 5) // Reads button state every 5mS and then updates button counts
{
StartButtonState = digitalRead(StartButton);
StopButtonState = digitalRead(StopButton);
LastButtonCheck = millis();
if (StartButtonState == LOW)
{
StartCount ++; // Increment the Count by 1
if (StartCount > 10) // the button should be LOW for 10x5mS = 50mS
{
ButtonPressTime = millis(); // used for the Button press Timeout
StartCount = 0;
if (WiperRelayState == false) // No point in returning until its finished doing a wipe.
{
switch (IntWipe)
{
case 0:
// not been pressed or fully stopped.
IntWipe =1;
SingleWipe();
break; // Escape from the switch, so we don't do the next one
case 1:
// single press or stop button pressed.
IntWipe = 2;
WipeInterval = (millis() - LastWipeTime); // Time will be in mS
SingleWipe();
break; // Escape from the switch, so we don't do the next one
case 2:
// 2nd press
WipeInterval = (millis() - LastWipeTime); // Time will be in mS
SingleWipe();
break; // Escape from the switch, so we don't do the next one
}
}
}
}
else // StartButton is HIGH
{
StartCount =0;
}
if (StopButtonState == LOW)
{
StopCount ++;
if (StopCount >10) // the button should be LOW for 50mS
{
ButtonPressTime = millis(); // used for the Button press Timeout
IntWipe = 1;
StopCount = 0;
WipeInterval = 0;
LastWipeTime = millis(); // Set the wipe timer, so when the start is pressed the interval will be right
}
}
else // StopButton is HIGH
{
StopCount =0;
}
}
}
void SingleWipe()
{
if (WiperRelayState == false) // Not much point in wiping if we already doing a wipe.
{
LastWipeTime = millis();
WiperRelayState = true;
digitalWrite(WiperRelay, HIGH);
}
else
{
WiperRelayState = false;
digitalWrite(WiperRelay, LOW);
}
return;
}
Sketche Two
Automotive series, Temperature light
Sketche Three
Combined wiper and temperature light,
console.log( 'Code is Poetry' );
/*
WATER TEMPERATURE LIGHT (vehicles)
This uses a common sender (Facet 7.3005) to detect the Water Temperature.
It uses the value to detect if the sender is 'shorted' or 'open' and flashes an error code.
It controls the Water Temperature Light to show :-
Below NORMAL Fades up
NORMAL Off
HOT (90deg) Flashes
BOIL (100deg) ON
A calibrate feature is incorporated to set the NORMAL temperature
There are no delays used, so it can run a second function.
Automotive Series
1. Water Temperature Light
2. Variable Wiper
3. Electric Fan Controller (using the same hardware parts).
Flags for the various modes in Intelligent Temp Light are used, to allow the controller to service the other functions.
Pin assignments
Pin 0 Rx
Pin 1 Tx
Pin 2 Wiper Relay Output
Pin 3 Temp Light Output
Pin 4 Start Button Input
Pin 5 Stop Button Input
Pin 6 Cal Button Input
Pin 10
Pin 13 Led
Pin A0 Temp Sender Input (Uses a Facet 7.3005 fed with 150 Ohm from 5v.)
Pin A4
Series created 1 Aug 2011
by Mark Beckett
Sender is a Facet 7.3005 from Auto Agencies, Rangiora see http://www.autoagencies.co.nz/
Version
0.1 Initial Code started 01 Feb 2012
---------------------------------------------------
To Do :
******************************************
I make no apologies for the code used in the sketch below.
The series is designed to help introduce novice programmers (including me), and as such code that can be followed is more important.
The sketch takes very little space, and is mostly waiting for something to happen, so speed is not required.
Also I fix things for a living, rather than write software, so to all you programmers ....sorry
Mark Beckett
*****************************************
*/
#include
// General Purpose
unsigned long LastChange =0; // Used in flashing/toggling the Temp light
unsigned long LastTempLightOn = 0; // Time the Temp Light was turned On.
unsigned long LastTempLightOff = 0; // Time the Temp light was turned Off.
unsigned long LightTimerTime = 0; // Used in Timer(), for Fading Temp Light.
unsigned long LastTempRead = 0; // Time the Temp was read.
int FadeValue = 0; // used to set the fade level.
int LastErrorCount = 0; // Error counter.
int FlashCount = 0; // used in DisplayMODE to count flashes.
int TempLightOffTime = 2000; // Time the Temp Light is Off [2 seconds]
int TempLightOnTime = 500; // Time the Temp Light is On [0.5 seconds]
int ledState = LOW; // ledState used to set the LED
int Mode = 0; // Mode for function 0= normal, 2= cal, 3= Open, 4= Shorted
int NORMAL = 598; // 65 deg (or from the EEPROM later)
int HOT = 424; // 90 deg
int BOIL = 377; // 100 deg
int n1=0; // used to hold 100's of the TempSender value before writing to EEPROM
int n2=0; // used to hold 10's of the TempSender value before writing to EEPROM
int n3=0; // used to hold 1's of the TempSender value before writing to EEPROM
// Button handling variables
unsigned long LastButtonCheck = 0; // Time the Buttons were last checked.
unsigned long ButtonPressTime = 0; // Time the last button was pressed.
boolean StartButtonState = HIGH; // records the StartButton State
boolean CalButtonState = HIGH; // records the CalibrateButton State
int StartCount = 0; // Start Button counter
//inputs
int StartButton = 4;
int StopButton = 5;
int CalButton = 6;
int TempSender = 0;
int val = 0;
//-----------------------------------------------
//Outputs
int TempLight = 3; // PWM
//int Wiper = 2;
const int LEDPin = 13; // Pin 13 LED Output
//------------------------------------------------
//Settings
/*
Default values are
NORMAL (65 deg) = 2.92v [598]
HOT (90 deg) = 2.07v [424]
BOIL (100 deg) = 1.84v [377]
Mode
0 = normal
1 = Power On Self Test (POST)
2 = Cal
3 = Open circuit sensor [> 1000]
4 = Shorted sensor [< 50]
5 = Value set
*/
//-------------------------------------------------------------------------
void setup()
{
Serial.begin(57600);
//Define the inputs
pinMode (CalButton, INPUT);
digitalWrite (CalButton, HIGH);
pinMode (StartButton, INPUT);
digitalWrite (StartButton, HIGH);
pinMode (StopButton, INPUT);
digitalWrite (StopButton, HIGH);
//Define the outputs
pinMode(LEDPin, OUTPUT);
pinMode(TempLight, OUTPUT);
//Set the default values
PowerUp();
}
void PowerUp()
/* This runs once at power up.
Checks to see if the CAL Button is pressed.
Checks to see if there is an Error in reading the Sender value.
Turns output ON for 5 secs, if everything is okay.
*/
{
CalButtonState = digitalRead(CalButton);
if (CalButtonState == LOW)
{
delay(100); //check to see the button is pressed by waiting 100mS (We can accept a delay here)
CalButtonState = digitalRead(CalButton);
if (CalButtonState == LOW)
{
Mode = 2; // Cal mode
Calibrate(); // Go and do the calibrate proceedure
}
}
//check EEPROM address to see if a figure is written there
val = 100 * (EEPROM.read(1)); //check value at address 1
val = val + 10 * (EEPROM.read(2)); //check value at address 1
val = val + (EEPROM.read(3)); //check value at address 1
if (val !=0)
{
NORMAL = val;
}
ReadTemp(); // Go and check the Temp Sender for Errors. (Mode = 0 for normal)
if (Mode == 0) // checking for Errors (Mode = 0 is normal)
{
digitalWrite(LEDPin, HIGH);
digitalWrite(TempLight, HIGH);
ledState = HIGH;
LastTempLightOn = millis(); // Note when we turned On
Mode = 1; // set this to allow detection of POST mode
}
do // While Mode is 1, we keep checking the time. Normally we should do something else, but not during POST
// We don't want to read the Temperature while the car may be getting started.
{
if ((millis() - LastTempLightOn) > 5000) // should be 5 secs
{
digitalWrite(LEDPin, LOW);
digitalWrite(TempLight, LOW);
ledState = LOW;
LastTempLightOff = millis(); // Note when we turned Off
Mode = 0; // set this back to normal
}
} while (Mode == 1); // use the == otherwise Mode gets set to 1.
if (Mode == 3) // checking for Errors (Mode = 3 Open circuit sensor [> 1000])
{
DisplayMODE();
}
if (Mode == 4) // checking for Errors (Mode = 4 Short circuit sensor [< 50])
{
DisplayMODE();
}
}
void loop()
{
// ***** used in Variable Wiper sketch DON'T MIX UP THE VARIABLES *****
// Check_Buttons(); //used for Int wiper
Timer(); //See what is needed to be done
}
void Timer()
{
if (Mode == 0) // use the == otherwise Mode gets set to 0.
{
if ( (millis() - LastTempRead) > 500) // only need to check every 0.5 secs
{
ReadTemp();
}
LastErrorCount = 0; //No more errors so reset it.
DisplayTemp();
}
else
{
DisplayMODE();
}
}
void ReadTemp()
{
/*
The Temp Sender is fed via a 150 ohm resistor from the 5v line. This results in a voltage between 1.7 and 3.6 v.
If the voltage is 4v or 1v, then an error is displayed.
A power off is required to reset an error condition.
Default values are used if the EEprom hasn't been written to with Calibrated/Altered values.
************** NOTE loading a new sketch doesn't overwrite the EEPROM values ***********
*/
TempSender = analogRead(A0);
if (TempSender > 1000) // Temp Sender open circuit
{
LastErrorCount ++;
if (LastErrorCount == 4);
{
Mode = 3;
}
}
if (TempSender < 50) // Temp Sender short circuit
{
LastErrorCount ++;
if (LastErrorCount == 4);
{
Mode = 4;
}
}
LastTempRead = millis(); // Note the time since we only need to check every 0.5 secs at the most.
return;
}
void Calibrate()
{
/* This process allows the 'Normal' value to be altered and stored in the EEprom.
Default values are based on a Facet 7.3005 sender (Auto Agencies, Rangiora see http://www.autoagencies.co.nz/)
CAL is held low and the unit is powered up.
The Temp Light (and LED) is flashed 2 times, pause for 2-3 secs, then repeated to show CAL mode until a mode is set.
Press START sets the NORMAL temp.
The unit will change to flash 5 times, pause for 1 sec and repeat to show its saved the new value.
(It will ignore any further button pressing.)
Note An error will prevent the Cal mode being set.
We assume that the user knows when the temperature has reached the thermostat opening temperature, and when it
reaches that temp the user press'es the Start button to set it.
You only get to set the new temperature ONCE. Simply power down to attempt again.
****** NOTE: If the EEPROM has been written to, it doesn't clear when you load a new sketch. !!! ************
*/
while(Mode == 2)
{
if (millis() - LastButtonCheck > 5) // Reads button state every 5mS and then updates button counts
{
StartButtonState = digitalRead(StartButton);
LastButtonCheck = millis();
if (StartButtonState == LOW)
{
StartCount ++; // Increment the Count by 1
if (StartCount > 10) // the button should be LOW for 10x5mS = 50mS
{
StartCount = 0;
Mode =5; // change Mode to drop out the while loop
//write the TempSender value to EEPROM
ReadTemp(); // ReadTemp() has a return at the end, so we should come back to here, unless there is a fault.
// Below is not an elegant way of breaking the number up, but a novice programmer can follow it
n1 = (TempSender/100);
n2 = (TempSender -(n1*100))/10;
n3 = (TempSender -(n2*10)) - (n1*100);
EEPROM.write(1, n1);
EEPROM.write(2, n2);
EEPROM.write(3, n3);
}
}
}
if(millis() - LastChange > 300)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=2)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >2)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
}
while (Mode ==5)
{
if(millis() - LastChange > 300)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=5)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >5)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
}
}
void DisplayMODE()
/*
Flashes the Temp Light to show an error.
It should stay in this mode, apart from the other purposes for the controller.
*/
{
do
{
if(millis() - LastChange > 300)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=3)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >3)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
}
while (Mode ==3);
do
{
if(millis() - LastChange > 300)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=4)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >4)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
}
while (Mode ==4);
}
void DisplayTemp()
{
/*
The Temp Light continually fades up until the NORMAL value is reached, when it goes Off.
When the Temp reaches 90 deg it flashes.
If the Temp reaches 100 deg it stays ON.
*/
// below NORMAL temp
if (TempSender > NORMAL) // value is greater than NORMAL value (65 deg or calibrate setting)
{
if ((millis() - LightTimerTime) > 25)
{
if (FadeValue < 255)
{
FadeValue ++;
//FadeValue ++; //uncomment this if you want the Light to brighten quicker (steps two steps each cycle)
}
else
{
FadeValue = 0;
}
LightTimerTime = millis();
analogWrite(TempLight, FadeValue);
}
}
else
{
// NORMAL temp
if (TempSender <= NORMAL && TempSender >= HOT) // value is greater than HOT but less than NORMAL value
{
ledState = LOW;
FadeValue = 0;
}
// HOT temp
if (TempSender > BOIL && TempSender <= HOT) // greater than HOT (90 deg)
{
if(millis() - LastChange > 150) // change every 150mS which should be a xxHz flash
{
LastChange = millis(); // save the last time you blinked the LED
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
}
}
// BOIL temp
if (TempSender <= BOIL) // value is less than BOIL
{
ledState = HIGH;
}
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
}
}
console.log( 'Code is Poetry' );
/*
This sketch combines both previous sketches into one, to allow both functions to run on the same hardware.
NOTE during calibration the Variable Wiper doesn't run.
The display error codes requires the unit to stay in the loop, however it tis necessary to ensure the Wipera are
not still wiping.
As I finish the sketch whether the Variable Wiper runs under an error condition will also be decided.
WATER TEMPERATURE LIGHT (vehicles)
This uses a common sender (Facet 7.3005) to detect the Water Temperature.
It uses the value to detect if the sender is 'shorted' or 'open' and flashes an error code.
It controls the Water Temperature Light to show :-
Below NORMAL Fades up
NORMAL Off
HOT (90deg) Flashes
BOIL (100deg) ON
A calibrate feature is incorporated to set the NORMAL temperature
There are no delays used, so it can run a second function.
VARIABLE WIPER
This sketch controls a relay via a transistor, which is connected across the park contact on a Windscreen Wiper.
Pressing the Start button, gives a single wipe, and if the button is pressed again within 30 secs, will continue at the interval between button press's.
Pressing the Start button after a wipe cycle will change the interval to the time between wipe and press.
Pressing of the Stop button halts the cycle, unless the start button is pressed within 30 secs.
Wipe interval will be the interval between Stop and Start button being pressed.
Delays have been removed to allow a secondary function to run at the same time.
------------------------------------------------------------------------
The full article is in the Apr/May and June/July issue of The Shed magazine
http://www.theshedmag.co.nz/online/
Cadenza Publishing Ltd
PO Box 99652
Newmarket
Auckland
New Zealand
1149
T: +64 9 302-3172
F: +64 9 302-3174
Subscriptions and distribution.
subscriptions@theshedmag.co.nz
--------------------------------------------------------------------------
Automotive Series
1. Water Temperature Light
2. Variable Wiper
3. Electric Fan Controller (using the same hardware parts).
Pin assignments
Pin 0 Rx
Pin 1 Tx
Pin 2 Wiper Relay Output
Pin 3 Temp Light Output
Pin 4 Start Button Input
Pin 5 Stop Button Input
Pin 6 Cal Button Input
Pin 10
Pin 13 Led
Pin A0 Temp Sender Input (Uses a Facet 7.3005 fed with 150 Ohm from 5v.)
Pin A4
Series created 1 Aug 2011
by Mark Beckett
Sender is a Facet 7.3005 from Auto Agencies, Rangiora see http://www.autoagencies.co.nz/
Version
0.1 Initial Code started 01 Feb 2012 (Water Temp Light)
1.0 Initial Code completed Dec 2011
Code finalised Feb 2012 (Variable Wiper)
Combined code completed May 2012
---------------------------------------------------
To Do :
******************************************
I make no apologies for the code used in the sketch below.
The series is designed to help introduce novice programmers (including me), and as such code that can be followed is more important.
The sketch takes very little space, and is mostly waiting for something to happen, so speed is not required.
Also I fix things for a living, rather than write software, so to all you programmers ....sorry
Mark Beckett
*****************************************
*/
// Thi sis needed in order to store the new 'normal' setting
#include
// General Purpose (Water Temp Light)
unsigned long LastChange =0; // Used in flashing/toggling the Temp light
unsigned long LastTempLightOn = 0; // Time the Temp Light was turned On.
unsigned long LastTempLightOff = 0; // Time the Temp light was turned Off.
unsigned long LightTimerTime = 0; // Used in Timer(), for Fading Temp Light.
unsigned long LastTempRead = 0; // Time the Temp was read.
int FadeValue = 0; // used to set the fade level.
int LastErrorCount = 0; // Error counter.
int FlashCount = 0; // used in DisplayMODE to count flashes.
int TempLightOffTime = 2000; // Time the Temp Light is Off [2 seconds]
int TempLightOnTime = 500; // Time the Temp Light is On [0.5 seconds]
//*** check the use of int LedState in Variable Wiper ****
int ledState = LOW; // ledState used to set the LED
int Mode = 0; // Mode for function 0= normal, 2= cal, 3= Open, 4= Shorted
int NORMAL = 598; // 65 deg (or from the EEPROM later)
int HOT = 424; // 90 deg
int BOIL = 377; // 100 deg
int n1=0; // used to hold 100's of the TempSender value before writing to EEPROM
int n2=0; // used to hold 10's of the TempSender value before writing to EEPROM
int n3=0; // used to hold 1's of the TempSender value before writing to EEPROM
// Button handling variables
boolean CalButtonState = HIGH; // records the CalibrateButton State
boolean StartButtonState = HIGH; // records the StartButton State
boolean StopButtonState = HIGH; // records the StopButton State
// General Purpose (Variable Wiper)
int IntWipe = 0; // Flag to show we mode we are in. 0= off, 1= first press, 2= 2nd press.
int LedState = LOW; // ledState used to set the LED
unsigned long WipeInterval = 0; // Time between wipes as set by start/stop action [x secs]
unsigned long LastWipeTime =0; // Time the last wipe was started.
unsigned long TimerTime =0; // used in Timer(), = millis()-LastWipeTime.
int ButtonTimeout = 30000; // Timeout if no button is pressed. Note wipe interval is lower than this. [30 seconds]
int RelayOnTime = 1500; // Time the relay is held on to perform a single wipe. [1.5 secs]
boolean WiperRelayState = LOW; // Relay Output state
//common
// Button handling variables
unsigned long LastButtonCheck = 0; // Time the Buttons were last checked.
unsigned long ButtonPressTime = 0; // Time the last button was pressed.
int StartCount = 0; // Start Button counter
int StopCount = 0; // Stop Button counter
//inputs
int StartButton = 4;
int StopButton = 5;
int CalButton = 6;
int TempSender = 0;
int val = 0;
//Outputs
int TempLight = 3; // PWM
int WiperRelay = 2; // Wiper Relay output
const int LEDPin = 13; // Pin 13 LED Output
//------------------------------------------------
//Settings
/*
Default values are
NORMAL (65 deg) = 2.92v [598]
HOT (90 deg) = 2.07v [424]
BOIL (100 deg) = 1.84v [377]
Mode
0 = normal
1 = Power On Self Test (POST)
2 = Cal
3 = Open circuit sensor [> 1000]
4 = Shorted sensor [< 50]
5 = Value set
*/
//-------------------------------------------------------------------------
void setup()
{
Serial.begin(57600);
//Define the inputs
pinMode (CalButton, INPUT);
digitalWrite (CalButton, HIGH);
pinMode (StartButton, INPUT);
digitalWrite (StartButton, HIGH);
pinMode (StopButton, INPUT);
digitalWrite (StopButton, HIGH);
//Define the outputs
pinMode(LEDPin, OUTPUT);
pinMode(TempLight, OUTPUT);
pinMode(WiperRelay, OUTPUT);
//Set the default values
PowerUp();
}
void PowerUp()
/* This runs once at power up.
Checks to see if the CAL Button is pressed.
Checks to see if there is an Error in reading the Sender value.
Turns output ON for 5 secs, if everything is okay.
*/
{
CalButtonState = digitalRead(CalButton);
if (CalButtonState == LOW)
{
delay(100); //check to see the button is pressed by waiting 100mS (We can accept a delay here)
CalButtonState = digitalRead(CalButton);
if (CalButtonState == LOW)
{
Mode = 2; // Cal mode
Calibrate(); // Go and do the calibrate proceedure
}
}
//check EEPROM address to see if a figure is written there
val = 100 * (EEPROM.read(1)); //check value at address 1
val = val + 10 * (EEPROM.read(2)); //check value at address 1
val = val + (EEPROM.read(3)); //check value at address 1
if (val !=0)
{
NORMAL = val;
}
ReadTemp(); // Go and check the Temp Sender for Errors. (Mode = 0 for normal)
if (Mode == 0) // checking for Errors (Mode = 0 is normal)
{
digitalWrite(LEDPin, HIGH);
digitalWrite(TempLight, HIGH);
ledState = HIGH;
LastTempLightOn = millis(); // Note when we turned On
Mode = 1; // set this to allow detection of POST mode
}
do // While Mode is 1, we keep checking the time. Normally we should do something else, but not during POST
// We don't want to read the Temperature while the car may be getting started.
{
if ((millis() - LastTempLightOn) > 5000) // should be 5 secs
{
digitalWrite(LEDPin, LOW);
digitalWrite(TempLight, LOW);
ledState = LOW;
LastTempLightOff = millis(); // Note when we turned Off
Mode = 0; // set this back to normal
}
} while (Mode == 1); // use the == otherwise Mode gets set to 1.
if (Mode == 3) // checking for Errors (Mode = 3 Open circuit sensor [> 1000])
{
DisplayMODE();
}
if (Mode == 4) // checking for Errors (Mode = 4 Short circuit sensor [< 50])
{
DisplayMODE();
}
}
void loop()
{
Check_Buttons(); //used for Int wiper
Timer(); //See what is needed to be done
}
void Timer()
{
//function used in Variable Wiper
TimerTime = millis() - LastWipeTime;
if (((millis()-ButtonPressTime) > ButtonTimeout) && (IntWipe == 1)) // 30 Sec timeout for no button press, but only after stopped, or 1 start.
{
IntWipe = 0;
LastWipeTime = 0;
WipeInterval = 0;
}
// The SingleWipe() will be called when the start button is pressed, we need to turn the relay off.
if ((TimerTime > RelayOnTime) && WiperRelayState == true) // RelayOnTime has been exceeded AND WipeRelay is HIGH
{
SingleWipe(); // It will turn off the relay and not modify any variables
}
// Time to wipe but only if there is a WipeInterval AND the relay is off.
if ((TimerTime > WipeInterval) && (IntWipe == 2) && WiperRelayState == false)
{
SingleWipe();
}
//functions used in Water Temp Light
if (Mode == 0) // use the == otherwise Mode gets set to 0.
{
if ( (millis() - LastTempRead) > 500) // only need to check every 0.5 secs
{
ReadTemp();
}
LastErrorCount = 0; //No more errors so reset it.
DisplayTemp();
}
else
{
DisplayMODE();
}
}
void ReadTemp()
{
/*
The Temp Sender is fed via a 150 ohm resistor from the 5v line. This results in a voltage between 1.7 and 3.6 v.
If the voltage is 4v or 1v, then an error is displayed.
A power off is required to reset an error condition.
Default values are used if the EEprom hasn't been written to with Calibrated/Altered values.
************** NOTE loading a new sketch doesn't overwrite the EEPROM values ***********
*/
TempSender = analogRead(A0);
if (TempSender > 1000) // Temp Sender open circuit
{
LastErrorCount ++;
if (LastErrorCount == 4);
{
Mode = 3;
}
}
if (TempSender < 50) // Temp Sender short circuit
{
LastErrorCount ++;
if (LastErrorCount == 4);
{
Mode = 4;
}
}
LastTempRead = millis(); // Note the time since we only need to check every 0.5 secs at the most.
return;
}
void Check_Buttons()
{
if (millis() - LastButtonCheck > 5) // Reads button state every 5mS and then updates button counts
{
StartButtonState = digitalRead(StartButton);
StopButtonState = digitalRead(StopButton);
LastButtonCheck = millis();
if (StartButtonState == LOW)
{
StartCount ++; // Increment the Count by 1
if (StartCount > 10) // the button should be LOW for 10x5mS = 50mS
{
ButtonPressTime = millis(); // used for the Button press Timeout
StartCount = 0;
if (WiperRelayState == false) // No point in returning until its finished doing a wipe.
{
switch (IntWipe)
{
case 0:
// not been pressed or fully stopped.
IntWipe =1;
SingleWipe();
break; // Escape from the switch, so we don't do the next one
case 1:
// single press or stop button pressed.
IntWipe = 2;
WipeInterval = (millis() - LastWipeTime); // Time will be in mS
SingleWipe();
break; // Escape from the switch, so we don't do the next one
case 2:
// 2nd press
WipeInterval = (millis() - LastWipeTime); // Time will be in mS
SingleWipe();
break; // Escape from the switch, so we don't do the next one
}
}
}
}
else // StartButton is HIGH
{
StartCount =0;
}
if (StopButtonState == LOW)
{
StopCount ++;
if (StopCount >10) // the button should be LOW for 50mS
{
ButtonPressTime = millis(); // used for the Button press Timeout
IntWipe = 1;
StopCount = 0;
WipeInterval = 0;
LastWipeTime = millis(); // Set the wipe timer, so when the start is pressed the interval will be right
}
}
else // StopButton is HIGH
{
StopCount =0;
}
}
}
void SingleWipe()
{
if (WiperRelayState == false) // Not much point in wiping if we already doing a wipe.
{
LastWipeTime = millis();
WiperRelayState = true;
digitalWrite(WiperRelay, HIGH);
digitalWrite(LEDPin, HIGH);
}
else
{
WiperRelayState = false;
digitalWrite(WiperRelay, LOW);
digitalWrite(LEDPin, LOW);
}
return;
}
void Calibrate()
{
/* This process allows the 'Normal' value to be altered and stored in the EEprom.
Default values are based on a Facet 7.3005 sender (Auto Agencies, Rangiora see http://www.autoagencies.co.nz/)
CAL is held low and the unit is powered up.
The Temp Light (and LED) is flashed 2 times, pause for 2-3 secs, then repeated to show CAL mode until a mode is set.
Press START sets the NORMAL temp.
The unit will change to flash 5 times, pause for 1 sec and repeat to show its saved the new value.
(It will ignore any further button pressing.)
Note An error will prevent the Cal mode being set.
We assume that the user knows when the temperature has reached the thermostat opening temperature, and when it
reaches that temp the user press'es the Start button to set it.
You only get to set the new temperature ONCE. Simply power down to attempt again.
****** NOTE: If the EEPROM has been written to, it doesn't clear when you load a new sketch. !!! ************
*/
while(Mode == 2)
{
if (millis() - LastButtonCheck > 5) // Reads button state every 5mS and then updates button counts
{
StartButtonState = digitalRead(StartButton);
LastButtonCheck = millis();
if (StartButtonState == LOW)
{
StartCount ++; // Increment the Count by 1
if (StartCount > 10) // the button should be LOW for 10x5mS = 50mS
{
StartCount = 0;
Mode =5; // change Mode to drop out the while loop
//write the TempSender value to EEPROM
ReadTemp(); // ReadTemp() has a return at the end, so we should come back to here, unless there is a fault.
// Below is not an elegant way of breaking the number up, but a novice programmer can follow it
n1 = (TempSender/100);
n2 = (TempSender -(n1*100))/10;
n3 = (TempSender -(n2*10)) - (n1*100);
EEPROM.write(1, n1);
EEPROM.write(2, n2);
EEPROM.write(3, n3);
}
}
}
if(millis() - LastChange > 300)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=2)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >2)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
}
while (Mode ==5)
{
if(millis() - LastChange > 300)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=5)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >5)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
}
}
void DisplayMODE()
/*
Flashes the Temp Light to show an error.
*/
{
if((millis() - LastChange > 300) && Mode == 3)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=3)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >3)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
if((millis() - LastChange > 300) && Mode == 4)
{
LastChange = millis(); // save the last time you blinked the LED
if (FlashCount <=4)
{
if (ledState == LOW) // if the LED is off turn it on and vice-versa:
{
ledState = HIGH;
FlashCount ++;
}
else
{
ledState = LOW;
}
}
if (FlashCount >4)
{
ledState = LOW;
FlashCount ++;
}
// set the LED and Temp Light with the ledState of the variable:
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
if (FlashCount >=10)
{
FlashCount =0;
}
}
}
void DisplayTemp()
{
/*
The Temp Light continually brightens from Off to On, until the NORMAL value is reached, when it goes Off.
When the Temp reaches 90 deg it flashes.
If the Temp reaches 100 deg it stays ON.
*/
// below NORMAL temp
if (TempSender > NORMAL) // value is greater than NORMAL value (65 deg or calibrate setting)
{
if ((millis() - LightTimerTime) > 25)
{
if (FadeValue < 255)
{
FadeValue ++;
//FadeValue ++; //uncomment this if you want the Light to brighten quicker (steps two steps each cycle)
}
else
{
FadeValue = 0;
}
LightTimerTime = millis();
analogWrite(TempLight, FadeValue);
}
}
else
{
// NORMAL temp
if (TempSender <= NORMAL && TempSender >= HOT) // value is greater than HOT but less than NORMAL value
{
ledState = LOW;
FadeValue = 0;
}
// HOT temp
if (TempSender > BOIL && TempSender <= HOT) // greater than HOT (90 deg)
{
if(millis() - LastChange > 150) // change every 150mS which should be a xxHz flash
{
LastChange = millis(); // save the last time you blinked the LED
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
}
}
// BOIL temp
if (TempSender <= BOIL) // value is less than BOIL
{
ledState = HIGH;
}
digitalWrite(LEDPin, ledState);
digitalWrite(TempLight, ledState);
}
}