While I will probably do that (I'll try 6 degrees C), I do want to get this figured out so I can use it on future projects. I plan on making a similar controller for the solar hot water setup I am building and I'd like to get it figured out so I don't have issues with it once its up. It is going to have some very long sensor wire runs which will probably make the problem even worse.
|
Use the ds18b20 sensors. They are dirt cheap, and they don't drift around like the linear sensors can. Long wire runs are no problem either. The main thing I like about them is that they either work or they don't, rather than drifting or giving spiky readings.
|
Quote:
I didn't realize that you had done any projects with 1-wire. What kind of stuff have you done? -AC |
Well, lately, my youngest son has been in Lego League. The Lego brick controllers are built for a 5th grader, and he's in high school. So we rigged up the uno to do lego stuff. He can make his machines do anything for cheap, unlike the lego brick stuff, which is severely limited and highly expensive.
1-wire sensors are awesome. Depending on the device, they send and receive data just like an industrial plc unit (without all the extra wires). When the system powers up, they announce their presence. When they are told something, they do it. When they have something to tell, they ask permission. The processor is the master and everything else is a slave. The interface has collision prevention and detection built in, so data integrity is not a problem. And there are only 2 wires that go out remotely: power+data and ground. I have prototyped up so much stuff with arduinos and 1-wire sensors, its hard to know where to start. Temperature and level sensors, addressable switches, light/proximity switches, etc. are all easy as pie. Need 12 temp and 2 level sensors (fuel gauge + rain gauge) plus a hysteresis temp control? No problem: use 12 ds18b20 thermometers, a ds2450 quad a/d converter, and a ds28ea00 digital thermometer with control logic. Tell the sensors how to act, monitor what you want to. Done. The 1-wire sensors and bus are not really made for high-speed communications. If you want to exchange significant amounts of data, I2C or rs-232 or usb does that better. The bus and protocol are made for simplicity, so trying to load the 1 data wire with too much data will bog down everything. That being said, a lot of 8 bit data can be moved as readings and control signals, so don't be afraid the thing isn't going to react quickly enough to feedback or control signals. |
Quote:
Seems that they got a good idea going and just stopped. -AC |
The interface isn't made to handle lots of traffic. Error detection and correction isn't exactly robust. The interface was not made to control elaborate or complex functions. It was made so that micro-controllers could easily identify unique sensors and read their unique serial numbers. Data flow and control are just beneficial side effects, probably built out of headroom in a small instruction set.
That doesn't mean you can't make it do it, though. Dallas alone has a few devices made that can translate data to and from devices on the slave end. To interface with an array of analog sensors, they make a 4 channel a/d converter. The cool thing about this chip is that the analog inputs not used can be used as addressable switch outputs. They also make counters, to grab wind speed, motor rpm, and the like. |
Quote:
And there are 1-wire ready counters? And there are 1-wire wind speed sensors? And there are 1-wire rpm sensors? In what catalogs can these things be found? Reason I'm interested is that as you already know, having already done countless Arduino applications, the 1-wire library only needs to be loaded once in a sketch, and then it could be used for very many devices. At my local geek-lore repository, DorkbotPDX, absolutely nobody knows of any other 1-wire sensors. This is very interesting news. Where can I find these other 1-wire sensors? -AC |
Quote:
HTTP://www.hobby-boards.com/store/pa...re-Basics.html Looking at the stuff now, some of these devices have been discontinued. Here's a thread discussing current trends: Weather Toys Discussion Forum • View topic - DIY 1-Wire Slaves |
|
I updated the code to add some additional smoothing functionality. Now, the program will compare each of the 10 sensor readings to the average of the last set of sensor readings. If the temperature varies more then 2 degrees Celsius, it sets that reading back to the average. After all the sensor readings have been evaluated, a new average is calculated. Seeing as how this sensor is in the attic, I don't think the temp swings should be that drastic. However, on the off chance that the temperature actually did jump up more than two degrees C, I added code to bypass the smoothing function and calculate the new average. This is also keeping in mind that this programming will be used in the future for other purposes that might have faster temperature swings.
I'll see how this new code works over the next few days. |
Just stumbled across this thread and I have a question.
What is the purpose of dividing by 2: "Ssensor = analogRead(SsensorPin) / 2;" "Tsensor = analogRead(TsensorPin) / 2;" I am using LM34s and anticipating degF readings; I am getting strange results. |
Hello nluck. Welcome to the site. :thumbup:
The LM34 will output 10mV per degree F (the LM35 does the same, but in degrees C). Each 'step' (aka the number returned by the analog read function) on the arduino is roughly 5mV. So, 2 steps = 1 degree. Thus, I divide steps by 2 and your variables Ssensor and Tsensor are now in degrees. |
Haha, I totally forgot to update this thread. The new software smoothing worked very well. It still wasn't completely flawless, but it was much better. I'll have to grab that code when I'm home and post it up.
|
Aha, found it after all.
Code:
/* Thermal Differential Controller |
Hmm, thanks for the update. I am fairly new to C++ and trying to figure out some of the commands. At the moment, my pump relay (RelayPin) remains ON. Only made a few minor changes to your code (at least I think minor):
// Pins int SsensorPin = A0; // the pin to read solar panel temperature int TsensorPin = A1; // the pin to read water tank temperature int RelayPin = 2; // the pin to control the pump relay int ledPin = 13; // led pin to verify relay on condition // Variables int Ssensor = 0; // holds the value from SsensorPin int SensorOnDiff = 0; // holds the Ssensor value plus on differential (OnDiff) int SensorOffDiff = 0; // holds the Ssensor value plus off differential (OffDiff) int Tsensor = 0; // holds the value from TsensorPin int SensorReadings = 10; // number of sensor readings to take int Counter = 0; // sensor readings loop counter int OnDiff = 4; // temp diff that must exist to turn pump on (dec F) int OffDiff = 2; // temp diff that must exist to turn pump on (deg F) void setup() { pinMode(SsensorPin, INPUT); pinMode(TsensorPin, INPUT); pinMode(RelayPin, OUTPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); digitalWrite(RelayPin, LOW); // turn pump off } void loop() { // read sensor inputs, convert to degrees, and assign to variables Counter = 0; while(Counter < SensorReadings) { Ssensor = analogRead(SsensorPin) / 2; Tsensor = analogRead(TsensorPin) / 2; Counter++; digitalWrite(ledPin, HIGH); delay(250); digitalWrite(ledPin, LOW); delay(250); Serial.print(Ssensor); Serial.print(", "); Serial.print(Tsensor); Serial.print("\n"); delay(250); } // calculate average temp from sensor inputs Ssensor = Ssensor / SensorReadings; Tsensor = Tsensor / SensorReadings; // add temperature difference to Ssensor value SensorOnDiff = Ssensor - OnDiff; SensorOffDiff = Ssensor - OffDiff; // if heat source is warmer than heat sink sensor, enable relay if (SensorOnDiff > Tsensor) { digitalWrite(RelayPin, HIGH); digitalWrite(ledPin, HIGH); delay(3000); } // if heat source sensor is cooler than heat sink sensor, disable relay if (SensorOffDiff < Tsensor) { digitalWrite(RelayPin, LOW); digitalWrite(ledPin, LOW); delay(1000); } } Any help is appreciated. Thanks. |
Well, I see one issue:
Quote:
It should be: // read sensor inputs, convert to degrees, and assign to variables Counter = 0; while(Counter < SensorReadings) { Ssensor += analogRead(SsensorPin) / 2; Add the += here Tsensor += analogRead(TsensorPin) / 2; Add the += here Counter++; digitalWrite(ledPin, HIGH); delay(250); digitalWrite(ledPin, LOW); delay(250); Serial.print(Ssensor); Serial.print(", "); Serial.print(Tsensor); Serial.print("\n"); delay(250); } // calculate average temp from sensor inputs Ssensor = Ssensor / SensorReadings; Tsensor = Tsensor / SensorReadings; The while loop adds all of the readings together and then afterwards, the readings get divided by the number of readings taken (SensorReadings). In your code, you're not adding the readings together. Your code is just using the last reading taken, and the dividing it by the readings taken. So, if you take 3 readings and read 30, 40, 50. Your code will use 50 degrees and divide by 3 (giving 17) instead of adding 30 + 40 + 50 and dividing by 3 (giving 40). If fixing that doesn't help, I'd move the serial output after the line: Ssensor = Ssensor / SensorReadings; Tsensor = Tsensor / SensorReadings; This will show you the values that are actually being compared vs the values that are being read by the temperature sensors. |
Almost everything works well, except the relayPin starts HIGH. The temp readings are uniformly higher by about 12-15 degF than they should be. Any suggested corrections? Thanks for the help. My code follows:
// Pins int SsensorPin = 4; // the pin to read solar panel temperature int TsensorPin = 5; // the pin to read water tank temperature int RelayPin = 2; // the pin to control the pump relay int ledPin = 13; // led pin to verify relay on condition // Variables int Ssensor = 0; // holds the value from SsensorPin int SensorOnDiff = 0; // holds the Ssensor value plus on differential (OnDiff) int SensorOffDiff = 0; // holds the Ssensor value plus off differential (OffDiff) int Tsensor = 0; // holds the value from TsensorPin int SensorReadings = 10; // number of sensor readings to take int Counter = 0; // sensor readings loop counter int OnDiff = 4; // temp diff that must exist to turn pump on (dec F) int OffDiff = 2; // temp diff that must exist to turn pump off (deg F) void setup() { pinMode(SsensorPin, INPUT); pinMode(TsensorPin, INPUT); pinMode(RelayPin, OUTPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); digitalWrite(RelayPin, LOW); // turn pump off } void loop() { // read sensor inputs, convert to degrees, and assign to variables Counter = 0; while(Counter < SensorReadings) { Ssensor += analogRead(SsensorPin) / 2; Tsensor += analogRead(TsensorPin) / 2; Counter++; digitalWrite(ledPin, LOW); delay(250); digitalWrite(ledPin, LOW); delay(250); } // calculate average temp from sensor inputs Ssensor = Ssensor / SensorReadings; Tsensor = Tsensor / SensorReadings; // add temperature difference to Ssensor value SensorOnDiff = Ssensor - OnDiff; SensorOffDiff = Ssensor - OffDiff; Serial.print("Solar temp= "); Serial.println(Ssensor); Serial.print("Tank temp= "); Serial.println(Tsensor); // if heat source is warmer than heat sink sensor, enable relay if (SensorOnDiff > Tsensor) { digitalWrite(RelayPin, HIGH); digitalWrite(ledPin, HIGH); delay(3000); } // if heat source sensor is cooler than heat sink sensor, disable relay if (SensorOffDiff < Tsensor) { digitalWrite(RelayPin, LOW); digitalWrite(ledPin, LOW); delay(500); } } |
Got the output working, now to adjust the temp readings.
|
It doesn't really matter if both sensors are off as long as they're off the same amount and its consistent. You're only measuring the differential temperature, so they only need to be accurate to each other. If this bugs you, you can do some sort of manual calibration to dial them in closer.
When I tested mine, I put a short lead on them, put them right next to each other for a half hour and read the serial output. They were probably within a degree C of each other and that was close enough for my application. |
Yes, I agree with the differential being the important item. Just prefer an accurate representation of the actual temp readings as it seems important to me. I will try to tweak them. Thanks for the reply.
|
I find it odd that your sensors are so far off. When I tested mine, they were pretty accurate.
|
You might want to increase the turn on dT to about 6-8C. Turn off can be 4c. The reason is quite simple, the panel will start at a perceived temp but within in few seconds of flow that temp will change, either up or down depending on conditions. With a small dT, the pump will be on and off too often and it will be hard to get a constant flow.
|
What I ended up doing is modifying the readings:
Ssensor += analogRead(SsensorPin) / 2.5; and the temps are where I would expect them to be. |
nkuck, I would suggest a static offset to correct things. Say your sensor reading is off by 10F, just add 10 to the Ssensor variable. With the current way you're doing it, it may read normal at the temperatures you're reading, but as you get farther from those temperatures your readings will get farther and farther off.
Here is what I would do: Code:
// read sensor inputs, convert to degrees, and assign to variables This is just an example. Replace the 10 and 13 with whatever the readings seem to be off by. This will create a linear offset that won't drift as the temperature varies. |
Good idea. Thank you. Happy New Year.
|
Here is my current sketch and most everything is working fine, except:
When I activate the external relay (a Reeed Relay Shield) both the Ssensor and the Tsensor temps rise 10-20 degrees and stay high until the relay disengages. Could there be some internal heat being generated by the load? Doesn't seem like it would be high enough to make a difference. Thanks for all of your support and patience. // Pins int SsensorPin = 4; // the pin to read solar panel temperature int TsensorPin = 5; // the pin to read water tank temperature int RelayPin = 7; // the pin to control the pump relay int ledPin = 13; // led pin to verify relay on condition int vref; // Variables int Ssensor = 0; // holds the value from SsensorPin int SensorOnDiff = 0; // holds the Ssensor value plus on differential (OnDiff) int SensorOffDiff = 0; // holds the Ssensor value plus off differential (OffDiff) int Tsensor = 0; // holds the value from TsensorPin int SensorReadings = 5; // number of sensor readings to take int Counter = 0; // sensor readings loop counter int OnDiff = 4; // temp diff that must exist to turn pump on (dec F) int OffDiff = 2; // temp diff that must exist to turn pump off (deg F) // initialize the library with the numbers of the interface pins #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() { pinMode(SsensorPin, INPUT); pinMode(TsensorPin, INPUT); pinMode(RelayPin, OUTPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); digitalWrite(RelayPin, LOW); // turn pump off // set up the LCD's number of columns and rows: lcd.begin(16,2); } void loop() { // read sensor inputs, convert to degrees, and assign to variables Counter = 0; while(Counter < SensorReadings) { Ssensor += analogRead(SsensorPin) / 2; delay(50); Tsensor += analogRead(TsensorPin) / 2; delay(50); Counter++; digitalWrite(ledPin, LOW); delay(250); } // calculate average temp from sensor inputs //Ssensor = (500.0 * Ssensor / SensorReadings) / 1024; // Tsensor = (500.0 * Tsensor / SensorReadings) / 1024; Ssensor = Ssensor / SensorReadings; Tsensor = Tsensor / SensorReadings; // calibrate sensors Ssensor = Ssensor - 15; Tsensor = Tsensor - 16; // add temperature difference to Ssensor value SensorOnDiff = Ssensor - OnDiff; SensorOffDiff = Ssensor - OffDiff; // Print temps to the Computer Serial.print("Solar temp= "); Serial.println(Ssensor); Serial.print("Tank temp= "); Serial.println(Tsensor); // Print temps to the LCD // set the cursor to column 0, line 1 // (note: line 1 is the second row, since counting begins with 0): lcd.setCursor(0, 0); lcd.print("Solar="); lcd.print(Ssensor); delay(50); lcd.print((char) 223); lcd.print("F"); lcd.setCursor(12, 0); lcd.print("Pump"); lcd.setCursor(0, 1); lcd.print("Tank ="); lcd.print(Tsensor); delay(50); lcd.print((char) 223); lcd.print("F"); // if heat source is warmer than heat sink sensor, enable relay if (SensorOnDiff > Tsensor) { digitalWrite(RelayPin, HIGH); digitalWrite(ledPin, HIGH); lcd.setCursor(13, 1); lcd.print("ON "); delay(500); } // if heat source sensor is cooler than heat sink sensor, disable relay if (SensorOffDiff < Tsensor) { digitalWrite(RelayPin, LOW); digitalWrite(ledPin, LOW); lcd.setCursor(13, 1); lcd.print("OFF"); delay(500); } } |
That sounds like a very odd problem. It also sounds more like a wiring problem. Can you describe your setup and possibly provide a wiring diagram?
|
I don't have a drawing worked up, but I'm thinking...is there a possibility that the way I am using the digital pins and analog pins, with the serial and lcd display, that there is a conflict going on? The wiring is OK per the pins that I have selected. Thank you for looking at this.
|
Quote:
Have I read that correctly? If so, are you sure you can do that? Do you really have it wired up that way? |
That's precisely my question. I am tryi g to use the analog pins 4 & 5 for the temp inputs amd the digitals for the lcd, but I am not sure if I am setting them up properly and calling them correctly. That may be the reason for my weird readings
|
With my limited knowledge I don't see anything wrong with your use of those pins for the sensors or for the LCD but using them for both purposes at the same time sets off alarm bells to me. Have you seen anything documented to say it is possible to share the pins in that way? It looks unlikely to me and I would avoid it if at all possible.
|
I agree that what I am doing is not correct, but I don't know how to write the sketch properly and to wire it so that the lcd pins use the digital pins on the Arduino and the analog pins on the Arduino are just used for the LM34 temp sensors. I need to do more research. Thanks.
|
As long as you're not physically wiring the pins together, the arduino software is smart enough to differentiate the digital pins from the analog pins. That shouldn't cause any issues. If you want to test it, just comment out your LCD code and disconnect the LCD.
Do you have a link to the relay shield you're using? Are there any known issues with it? |
Quote:
Agree about commenting out and disconnecting the LCD as a quick test. |
in post number 66, you define your sensor pins here:
Code:
int SsensorPin = 4; // the pin to read solar panel temperature Code:
#define SsensorPin 1//Arduino analog pin where the Sensor1 is connected if you want to keep them connected to the same pins, just change the 1 and 2 to 4 and 5. it should work better then. defining pin locations as variable integers is risky business. you want to define them as constants to prevent murphy's law. |
Thanks for the response. It does seem to add stability, but I am not sure why the #define function works better than the int function. I will dig in!
|
I found a small inaccuracy with the code today. I wasn't resetting the variable that is used to hold the sensor readings. So, for example, on the first run through it starts as 0, takes 10 readings, averages them to eliminate any noise over the lines. The second time through it reads that averaged number going into it, then adds 10 more values, then averages them. This definitely throws the true readings off. However, since its a differential controller, its not horribly important because both sensors will be off relatively the same amount. However, it is fixed now.
I've been having some issues with the attic fan not turning off like it should, so I've been troubleshooting. Here is the latest code. Code:
/* Thermal Differential Controller |
All times are GMT -5. The time now is 10:00 PM. |
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Ad Management by RedTyger