Serial communications to Web

Written by Ryan Hallarn on December 17, 2011 Categories: Uncategorized

Do you see what this is? This is data being captured from the UNIX command Screen, which reads and buffers serial data in a nice clean happy way WHILE NOTHING ELSE DOES. This is just dummy data for now, from another arduino being sent from an xBee wireless interface ($30 ebay!) for testing purposes, it’s pretty useful for figuring out how to get that data to load into a webpage.

 

So have I figured out the web interface for displaying data yet? No. I’ve been looking into a lot of options, such as the php-serial class that can read serial data, although that doens’t buffer the data nicely and you get a handful of characters at random. I’m currently thinking of having Screen dump its output into a text file, and then just reading the last few lines with a php script. Should be pretty easy, although not the most kind to my server. Ever since it got cold out, I haven’t been paying much attention to this project as the current system has still been operating without faults for quite some time now. The 2nd Arduino I bought for testing will probably go to use in an RFID lock system using electronic door strikes.

If you’re curious, here’s the revised code. It’s a lot easier to understand whats going on (really, its not much) You’ll noticed I removed a couple of useless things like the RGB LED code which used up a lot of memory. Oh, and no pinouts are designated yet until I draw up some cleaner schematics.

 

//Lots of example code used from Sparkfun provided libraries, etc.
//NOTES
//Reserved Pins
//D2, D3, Xbee
#include

//Arduino pinouts
int maxTempPin; //TBD This is for the potentiometer, setting max temp
int heaterOverridePin; //This is a manual on/off switch
int heaterRelayPin; //
int waterPressurePin; //
int thermistorPin = 0; //Analog pin 0
uint8_t pinRx = 2 , pinTx = 3; // xBee Serial pins 2 and 3. This is an option for the sparkfun XBee shields to switch the serial port pins
//Temperature control
double maxTemp;
double temperature;

//Flow Control
//TBD, this is for Jet control, which will be added in the future. Requires rather powerful relays.

//Heater & Heater Overrides
String heaterstatus; //ON or OFF, set in the heaterOn and heaterOff functions.
boolean waterPressure; //Checks to see if heater has water pressure
boolean heaterOverride; //Checks to see if heater manual switch is on or off

//xBee
NewSoftSerial xBeeSerial( pinRx , pinTx );
int sendcounter = 0;

void setup()
{
xBeeSerial.begin(9600);
Serial.begin(9600);
}

void loop()
{
/*
SETTING MAX TEMPERATURE
*/
//Read maximum temperature value set by a 10k pot
maxTemp = analogRead(maxTempPin);
//This formula turns the number into a useable range of around 70-120
maxTemp = sqrt(maxTemp)*4-10;
//No hot tub should ever go above 110, so this changes the above (if greater than 110) to 110
if (maxTemp>=110)
{
maxTemp=110;
}

/*
READING CURRENT WATER TEMPERATURE FROM THERMISTOR
*/
temperature = Thermister(analogRead(thermistorPin));
//Convert temperature to Fahrenheit
temperature = (temperature * 1.8) + 32;

/*
HEATER CONTROL
*/
//
if (temperature<=maxTemp && waterPressure==true && heaterOverride==false)
{
heaterOn();
}
// We add +3 to maxTemp so that the heater is not constantly cycling on/off, it must drop 3 degrees first.
if (temperature>maxTemp +3 || waterPressure==false || heaterOverride==true)
{
heaterOff();
}

/*
SERIAL MESSAGE OUTPUT FOR LCD DISPLAY. Set up for a 4 line display which I am yet to obtain.
*/

Serial.print("Temperature: ");
Serial.println(temperature);

Serial.print("Temperature Max: ");
Serial.println(maxTemp);

Serial.print("Heater Status: ");
Serial.println(heaterstatus);

Serial.print("Water Pressure: ");
Serial.println(waterPressure);

if (sendcounter == 100) //So that we don't have a flood of data, a counter delay is used. This makes the delay around 7 seconds.
{
xBeeSerial.print("Temperature: ");
xBeeSerial.println(temperature);
xBeeSerial.print("Temperature Max: ");
xBeeSerial.println(maxTemp);
xBeeSerial.print("Heater Status: ");
xBeeSerial.println(heaterstatus);
xBeeSerial.print("Water Pressure: ");
xBeeSerial.println(waterPressure);
Serial.println(sendcounter);
sendcounter=0;
}
else
{
sendcounter=sendcounter+1;
}

}

void heaterOn() //Turns the heater ON
{
analogWrite(heaterRelayPin,255);
heaterstatus="ON";
}
void heaterOff() //Turns the heater OFF
{
analogWrite(heaterRelayPin,0);
heaterstatus="OFF";
}
double Thermister(int RawADC) //Code to get value from Thermister in a CELCIUS. It is converted in the code above.
{
double Temp;
// See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
Temp = log(((10240000/RawADC) - 10000));
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15; // Convert Kelvin to Celcius
return Temp;
}

1 Comment

A word in safety..

Written by Ryan Hallarn on December 1, 2011 Categories: Uncategorized

A lot of concerns were brought up about the project, that being said, you shouldn’t ever do this, as you will probably kill everyone you’ve ever met.

Here is a basic list of modifications that have actually been done to the hot tub.

  • The wires going to the burnt out relay with a cooked wire are now going to a bigger, solid state relay
That’s about it. It has been running without fault now for over a month, has never exceeded maximum temperature, and the arduino has never been reset. High voltage is at play here, so be careful, especially around water.
No Comments

Spaduino: Where is it going?

Written by Ryan Hallarn on November 13, 2011 Categories: Uncategorized

My to-do list for the project is as follows

  1. Xbee! Being able to check current temperature through a simple php page on your phone would be great for when you’re out.
  2. Clean up and simplify the wiring, maybe invest in a protoshield.
  3. Add a manual override switch with an LED indicating heater status in place of the pressure sensor.
  4. More relays! Hopefully control both jets, and the air blower.
  5. Integrate into existing hot tub controls! The control panel is encased in epoxy, so I can’t easily trace all the connections, but it has a large ribbon cable that probably contains everything I need.
  6. Additional safety precautions. There is a water pressure sensor that is supposed to turn the heater off while the jets are not running. Because of the location of the thermistor, the heater core would be turned off by the temperature regulation before it ever got too hot.
I want to thank #codelove on slashnet.org for their contributions in code cleanup and solving one or two quirks.
2 Comments

Spaduino, part 3. Lets look at code.

Written by Ryan Hallarn on  Categories: Uncategorized

I’d love to have written this as I was writing the code, just to show you how bad it once was, but I’m going to save you the pain. It was really a lot of guess work, considering I’ve only ever taken two CS101 courses (once in highschool, once in college) and I’m really out of the loop(). This is currently revision 4 for me. I don’t keep strict track of revisions, but I’ve named it 4. There is a lot of future changes planned.

I don’t feel like explaining it all in this post, so here’s the dirty. I’ll try to expand on it later.

 

int fsrAnalogPin = 1; // FSR is connected to analog 1
int fsrReading; // the analog reading from the FSR resistor divider
int coverON = 0;

int tempAdjustPin = 5;
int tempAdjustValue = 0;

String heatstatus;
int red=9, //digital 9, these connect to the RGB led
green=10, //digital 10
blue=11, //digital 11
power=3, //digital 3 for our relay
i=0,
j=0,
color[]={
red, green, blue}
, // since array counts start a 0, color[0]=9, color[1]=10, color[2]=11
intensity[]={
0,0,0}; // one for each color

int temperature;

void setup()
{
Serial.begin(9600);
backlightOn();
clearLCD();
pinMode(red,OUTPUT);
pinMode(green,OUTPUT);
pinMode(blue,OUTPUT);

// turn off all colors on the LED
analogWrite(red,0);
analogWrite(green,0);
analogWrite(blue,0);
}

void loop()
{
tempAdjustValue = analogRead(tempAdjustPin);
tempAdjustValue = sqrt(tempAdjustValue)*4-10; //The *4-10 just seems to work for a 10k pot. Puts the value into a good hot tub range.
fsrReading = analogRead(fsrAnalogPin);

if (tempAdjustValue>=110) //We don’t want it to go above 110
{
tempAdjustValue=110;
}

double fTemp;
double temp = Thermister(analogRead(0)); // Read sensor
fTemp = (temp * 1.8) + 32.0; // Convert to USA
temperature=fTemp;

// Clear the LEDs
analogWrite(green,0);
analogWrite(blue,0);
analogWrite(red,0);

//This is for LED color control
if (temperature >= 107) Blink();
else if (temperature >= 100) Red();
else if (temperature >= 93) Orange();
else if (temperature >= 86) Yellow();
else if (temperature >= 79) Green();
else if (temperature >= 73) Turqoise();
else analogWrite(blue,255);

//Readings from pressure sensor
coverON = (fsrReading>800); //Suggestion, replaces IF similar to the one below.

//Heat Limiter, Variable Adjust
if (temperaturetempAdjustValue + 3 || !coverON) //This is a measure put in to prevent the heater from being cycled on and off. It makes the temp go 3 above the set max before turning off, so that it has to cool down 3 degrees before coming back on.
{
heaterOff();
}

clearLCD();
Serial.print(“Temp:”);
Serial.print(temperature);
Serial.print(“MAX:”);
Serial.print(tempAdjustValue);
selectLineTwo();
Serial.print(“HEATER: “);
Serial.print(heatstatus);
//Serial.print(“FSR:”);
//Serial.print(fsrReading);
delay(80);

}

double Thermister(int RawADC)
{
double Temp;
// See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
Temp = log(((10240000/RawADC) – 10000));
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp – 273.15; // Convert Kelvin to Celcius
return Temp;
}

void Blue() //These are the color calls for the RGB LED
{
analogWrite(blue,255);
}
void Turqoise()
{
analogWrite(blue,255);
analogWrite(green,155);
}
void Green()
{
analogWrite(green,255);
}
void Yellow()
{
analogWrite(red,255);
analogWrite(green,100);
}
void Orange()
{
analogWrite(red,255);
analogWrite(green,20);
}
void Red()
{
analogWrite(red,255);
}
void White()
{
analogWrite(red,255);
analogWrite(green,255);
analogWrite(blue,255);
}
void Blink() //This is a red/white blink used to indicate a very high temp.
{
analogWrite(red,255);
delay(400);
analogWrite(red,255);
analogWrite(green,255);
analogWrite(blue,255);
delay(400);
}
void heaterOn()
{
analogWrite(power,255);
heatstatus=”ON”;
}
void heaterOff()
{
analogWrite(power,0);
heatstatus=”OFF”;
}
void selectLineOne(){ //puts the cursor at line 0 char 0.
Serial.print(0xFE, BYTE); //command flag
Serial.print(128, BYTE); //position
delay(10);
}
void selectLineTwo(){ //puts the cursor at line 0 char 0.
Serial.print(0xFE, BYTE); //command flag
Serial.print(192, BYTE); //position
delay(10);
}
void goTo(int position) { //position = line 1: 0-15, line 2: 16-31, 31+ defaults back to 0
if (position Serial.print(0xFE, BYTE); //command flag
Serial.print((position+128), BYTE); //position
}
else if (position Serial.print(0xFE, BYTE); //command flag
Serial.print((position+48+128), BYTE); //position
}
else {
goTo(0);
}
delay(10);
}

// Resets the display, undoing any scroll and removing all text
void clearLCD() {
serCommand();
Serial.print(0×01, BYTE);
}

// Turns the backlight on
void backlightOn() {
serCommand();
Serial.print(157, BYTE);
}

// Turns the backlight off
void backlightOff() {
serCommand();
Serial.print(128, BYTE);
}

// Initiates a function command to the display
void serCommand() {
Serial.print(0xFE, BYTE);
}

No Comments

Spaduino, part 2. PCB Adventure.

Written by Ryan Hallarn on  Categories: Uncategorized

I could of kept it simple. I could have kept it clean. Nope. There was too much on my mind. I could not simply have an on/off switch for the heater. I need to have everything.

I had four days before parts started to arrive, and I wanted to have the hot tub operational that same day. Better get started!

One of my first concerns to address came from a bit I recalled from either a website or a manufacturer manual, stating how the heater turns OFF when both Jets 1 & 2 are running, because the wiring cannot support that amount of load. This could be tested in person too, the heat LED on the control panel would turn off if both jets were on (if you could get that heat light to come on.) There are several ways to address this issue.

  • Add a manual switch to disengage heater
  • A pressure pad sensor, to turn heater off whenever the cover to the hot tub is removed (such as when people get in it, and then turn the jets on)
  • Detect jet status. This is difficult.
I will tell you now, the pressure sensor was an awful idea as it didn’t seem to engage properly…ever. On the bright side, the code measures resistance, so with no modifications a switch can be put right in place of it. This hasn’t been implemented at this time.
Further ideas also came to mind. Just to keep it short, I’m going to give a quick summary of each objects purpose in the below image (created in Fritzing)
  • The RGB LED – Cycles through different colors to indicate current hot tub temperature.
  • Thermistor –  Attached directly to the heater core tube and insulated with lots of thermal tape, provides us with a close estimate of the current water temperature.
  • Pressure Sensor – uhh, yeah. A primitive on/off override.
  • Relay – Controlling power to the Heater
  • Potentiometer – Adjust the maximum temperature possible
  • LCD Screen – Hey, why not? I had it laying around.

 

I'm far from an electrical engineer. My wire planning is probably much less than ideal.

Well, the plan looks good. Now I have to make it work.

You can get the Fritzing file here.

2 Comments

Spaduino, part 1.

Written by Ryan Hallarn on  Categories: Uncategorized

Spaduino. The marvelous mating between an Arduino and a Sundance hot tub.

Back story

One day, the roommates and I decided we would like to have a hot tub. Done. Go to craigslist, buy used hot tub.

Cold tubs don't sell as well in most of the U.S.

I've sailed the seas in this bad boy

Looks good, doesn’t it? The jets appear to be working and the water physics are acting as normal. However, the heater is not. The circuitry in this thing should be pretty damn simple, until you realize they have been using the same control board since 1993. It was simple actually, just not as simple as I could of made it myself.

TEST TIME

Multimeter + hot wire + ground wire should = 220v. Nope. 0v. A pair of bad, hideously undersized relays have gone out, and who knows what else is wrong with the board. Oh well, we’re young and we want this thing hot, so lets wire it directly into the heater for now.

1.21 gigawatts more and we would of had it

It didn't really go down like this.

It actually worked for a while, until it didn’t. This is when a new option was needed. I had an arduino laying around from a previous project, and was sure I could simply control the heater. Lets see how much power that heater actually draws…

Marty, we're going to need some plutonium from the Libyans.

This is the heater tube on the hot tub. Inside of it is a removable heating element. These tubes are used on I want to say a majority of all hot tubs, and most of the elements are about the same size (but different ratings)

5.5KW is a tad outside the range of my Arduino. It isn’t however too much for a 60A Solid State Relay with optical isolation. These things are incredibly cool, cooler than my non-working hot tub. The optical isolation means the unit is triggered on and off by an LED, so there is almost no risk of it frying your Arduino. Also, unlike a mechanical relay, these things can be triggered off of logic level voltage. That means, you can turn this thing on and off with a pwm pin on your Arduino! Now its important to mention that you need a heatsink for these too, and you can get ones matched for it for around $15. Not too shabby.

2 Comments