#include
/* Pressure sensors have an offset that needs to be calibrated against.
* Simply hook up the pressure sensors to nothing and issue a "<1" sequence.
* The calibration value will then be stored in the EEPROM */
// Below are some misc variables and mostly the arduino pins where you have devices hooked up
int outputOffset=0;
int suctionOffset=0;
int caseThermPin = 0; // The analog pin you have the Voutput of your LM34 hooked up to for case temperature
int poolThermPin = 1; // The analog pin you have the Voutput of your LM34 hooked up to for pool water temp
int outputPressurePin=2; // The analog pin you have the voltage output of your MPX5500 pressure sensor
int suctionPressurePin=3; // The analog pin you have the voltage output of your MPX5500 pressure sensor
int state_pump=0, state_light=0, state_misc=0;
bool have_control=false; // Temp variable
int control_relay=0; // Temp variable
void setup()
{
pinMode(8, OUTPUT); // sets the digital pin as output
pinMode(9, OUTPUT); // sets the digital pin as output
pinMode(10, OUTPUT); // sets the digital pin as output
// Prepare the serial ports
Serial.begin(9600);
Serial.flush();
// Load the pressure sensor calibration values from the EEPROM
outputOffset=EEPROM.read(0);
outputOffset<<=8;
outputOffset|=EEPROM.read(1);
suctionOffset=EEPROM.read(2);
suctionOffset<<=8;
suctionOffset|=EEPROM.read(3);
// Use the 5V analog refrence voltage
analogReference(DEFAULT);
// Wait 1 second to allow things to stabilize
delay(1000);
}
void loop()
{
int serial_byte=0;
if (Serial.available()>0)
{
/* Here we wait for the first byte of a two byte control sequence. Send A, B or C to control pump, light, or misc.
Send W, X, Y, or Z to control the sensors
*/
serial_byte=Serial.read();
if (!have_control)
{
have_control=true;
if (serial_byte=='A')
control_relay=8;
else if (serial_byte=='B')
control_relay=9;
else if (serial_byte=='C')
control_relay=10;
else if (serial_byte=='Z')
control_relay=caseThermPin;
else if (serial_byte=='Y')
control_relay=poolThermPin;
else if (serial_byte=='X')
control_relay=outputPressurePin;
else if (serial_byte=='W')
control_relay=suctionPressurePin;
else if (serial_byte=='<')
control_relay=999;
else if (serial_byte==':')
control_relay=888;
else
{
have_control=false;
Serial.flush();
}
}
else
{
// We have the control byte, now lets look for 1 or 0
if (serial_byte=='1')
{
// Turn specified relay on
if (control_relay==8)
state_pump=HIGH;
if (control_relay==9)
state_light=HIGH;
if (control_relay==10)
state_misc=HIGH;
if (control_relay==999)
calibrate_pressure(outputPressurePin, suctionPressurePin);
}
else if (serial_byte=='0')
{
// Turn specified relay off
if (control_relay==8)
state_pump=LOW;
if (control_relay==9)
state_light=LOW;
if (control_relay==10)
state_misc=LOW;
}
else if (serial_byte=='?')
{
// What is the status of the specified relay?
if (control_relay==8)
{
if (state_pump==HIGH)
Serial.print("A1");
else
Serial.print("A0");
}
if (control_relay==9)
{
if (state_light==HIGH)
Serial.print("B1");
else
Serial.print("B0");
}
if (control_relay==10)
{
if (state_misc==HIGH)
Serial.print("C1");
else
Serial.print("C0");
}
// We use the question mark to query the sensors as well
if (control_relay==caseThermPin)
Serial.print(get_temp(caseThermPin));
if (control_relay==poolThermPin)
Serial.print(get_smoothed_temp(poolThermPin));
if (control_relay==outputPressurePin)
Serial.print(get_psi(outputPressurePin, outputOffset));
if (control_relay==suctionPressurePin)
Serial.print(get_psi(suctionPressurePin, suctionOffset));
if (control_relay==999)
{
Serial.println(outputOffset);
Serial.println(suctionOffset);
}
}
else if (serial_byte==':')
{
if (control_relay==888)
{
// Report back all switch and sensor readings
if (state_pump==HIGH)
Serial.print("A1");
else
Serial.print("A0");
if (state_light==HIGH)
Serial.print("B1");
else
Serial.print("B0");
if (state_misc==HIGH)
Serial.print("C1");
else
Serial.print("C0");
Serial.print(get_temp(caseThermPin));
Serial.print(get_smoothed_temp(poolThermPin));
Serial.print(get_psi(outputPressurePin, outputOffset));
Serial.print(get_psi(suctionPressurePin, suctionOffset));
}
}
else
{
Serial.flush();
}
have_control=false;
}
}
// This is where we issue our actual pin state to the arduino digital pins
digitalWrite(8, state_pump);
digitalWrite(9, state_light);
digitalWrite(10, state_misc);
}
/* This function reads the pressure sensor pins. Though the value returned appears to be a float the serial print function will
convert it to an integer. Thus to keep some of the precision we multiply by 100. This would make 12.75psi be 1275. We'll just
multiple the value * .01 on the server side */
int get_psi(int sensor_pin, int offset)
{
// If you look in the documentation, the sensor has a precision of 500kPa over 0.2 to 4.7V range. The offset we calibrate
// takes care of the 0.2 volt beginning and thus the total output range is 4.5V. This means arduino with it's 10bit analog
// to digital converter which has 1024 positions over 5V will have 921.6 positions over 4.5V.
// If you divide 500 kPa over 921.6 positions you have 0.54253472222 kPa per posiiton.
// To convert kPa to PSI you just multiple by 0.145, thus the calc below
float psi=0;
int x = analogRead(sensor_pin);
psi = (x-offset)*0.54253472222*0.145;
return psi*100;
}
int get_temp(int sensor_pin)
{
// LM34 gives a literal mV output based on the Fahrenheit temperature
// 3000mV at 300F
// 750mV at 75F
// -500mV at -50F
// Our reference voltage is actually 4.22V due to the crappy output the USB bus of the NSLU2 is giving the arduino
// We will want to scale our precision based on that rather than 5 volts.
// 422 degrees fit in 1024 precision (based on 4.22 volts)
// This means there is 0.412109375 positions per degree
// This means we multiply our value by 0.412109375 to get our Fahrenheit temp
// Multiply by 10 since it will implicitly convert to integer, we'll multiply by 0.1 later to get the real temp.
float temp = 0;
int x = analogRead(sensor_pin);
temp = x * 0.412109375;
return temp*10;
}
int get_smoothed_temp(int sensor_pin)
{
// The temperature is very jittery on a long cable run. Lets take 10 readings, average them, and then report the result for that situation
int total = 0;
float average = 0;
for (int i=0;i<10;i++)
total+=analogRead(sensor_pin);
float temp = total/10;
temp = temp * 0.412109375;
return temp*10;
}
/* This function reads the current value of idle pressure sensors (pump OFF) and records them into the eeprom). This is basically
resetting the 0 value like you would do with a scale */
void calibrate_pressure(int sensorPin1, int sensorPin2)
{
int x = analogRead(sensorPin1);
int y = analogRead(sensorPin2);
outputOffset=x;
suctionOffset=y;
EEPROM.write(1,x & 0xff);
x>>=8;
EEPROM.write(0,x);
EEPROM.write(3,y & 0xff);
y>>=8;
EEPROM.write(2,y);
}
Recent comments
38 weeks 6 days ago
38 weeks 6 days ago
39 weeks 5 days ago
43 weeks 6 hours ago
1 year 7 weeks ago
2 years 13 weeks ago
3 years 14 weeks ago
3 years 14 weeks ago
3 years 14 weeks ago
3 years 14 weeks ago