Arduino Code tweak - Page 1
Forum section: electronics / general

author: lilshawn
author_rank: Regular Contributor
timestamp: August 10, 2017, 11:42:48 pm
content: I'm looking to tweak some code for a temperature control. Right now I have an issue with my set temperature. the temperature reading sometimes fluctuates over the trigger set point causing my output to rapidly cycle on off on off on off as the reading goes from 34.99 to 40. i'll be switching a high current load with a secondary relay and I'll burn out the contacts in no time if it's rapidly switching like this.i'm thinking i have to reorganize everything and do a counted for loop to insert a delay or something.even if I can manage to have it, say turn on until 35c...turn off... but not turn back on until 34.I'm new at programming this code, and don't really know how to go about getting what I need. Thanks in advance for any ideas or solutions!Code:#include <Wire.h>#include <LiquidCrystal_I2C.h>LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address#define THERMISTORPIN A0#define THERMISTORNOMINAL 10000#define TEMPERATURENOMINAL 25#define NUMSAMPLES 20#define BCOEFFICIENT 3950#define SERIESRESISTOR 10000#define TEMPMIN 30#define TEMPMAX 42int TEMPSET = 39;int VALDOWN = 0;int VALUP = 0;int LASTUP = 0;int LASTDOWN = 0;int L = 0;const int relay =11;uint16_t samples;void setup(){pinMode(11, OUTPUT);pinMode(4, INPUT);pinMode(5, INPUT);lcd.begin(16,2);lcd.backlight();lcd.setCursor(0,0);lcd.clear();}void loop(void){uint8_t i;float average;for (i=0; i< NUMSAMPLES; i++) {samples = analogRead(THERMISTORPIN);delay(10);}average = 0;for (i=0; i< NUMSAMPLES; i++) {average += samples;}average /= NUMSAMPLES;average = 1023 / average - 1;average = SERIESRESISTOR / average;float celcius;celcius = average / THERMISTORNOMINAL; // (R/Ro)celcius = log(celcius); // ln(R/Ro)celcius /= BCOEFFICIENT; // 1/B * ln(R/Ro)celcius += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)celcius = 1.0 / celcius; // Invertcelcius -= 273.15; // convert to CVALDOWN = digitalRead(4);if (VALDOWN != LASTDOWN) {LASTDOWN = VALDOWN;if (VALDOWN == LOW) {TEMPSET = TEMPSET-1;}delay(20);}VALUP = digitalRead(5);if (VALUP != LASTUP) {LASTUP = VALUP ;if (VALUP == LOW) {TEMPSET = TEMPSET +1;}delay(20);}lcd.setCursor(0,0);lcd.print("Temp ");lcd.print (celcius);lcd.print((char)223);lcd.print("C ");lcd.setCursor(0,1);lcd.print("Set ");lcd.print (TEMPSET);lcd.print((char)223);lcd.print("C");if(TEMPSET >= TEMPMAX){(TEMPSET = TEMPMAX);}if(TEMPSET <= TEMPMIN){(TEMPSET = TEMPMIN);}if (celcius < TEMPSET){digitalWrite(11, HIGH);} else {}if (celcius > TEMPSET){digitalWrite(11, LOW);} else{}}/* --(end main loop )-- *//* ( THE END ) */

author: Mr.B
author_rank: Unknown
timestamp: August 10, 2017, 11:47:58 pm
content: What you are wanting is called hysteresis...https://arduino.stackexchange.com/questions/9115/how-to-add-hysteresis-to-threshold-values

author: lilshawn
author_rank: Regular Contributor
timestamp: August 11, 2017, 05:33:41 am
content: thanks, I'll have a look at seeing if I can implement this.

author: spongman
author_rank: Newbie
timestamp: August 11, 2017, 06:48:20 am
content: better yet: use a PID and tune for low oscillation.

author: Mr.B
author_rank: Unknown
timestamp: August 11, 2017, 07:06:43 am
content: Quote from: spongman on August 11, 2017, 06:48:20 amMay be overkill to use PID... depends on the OPs process requirements.Using a simple Arduino for PID control is not an easy task.With something like an ATmega328p and its limitations I would opt for simple hysteresis control.

author: picandmix
author_rank: Frequent Contributor
timestamp: August 11, 2017, 09:23:58 am
content: Typically a simple delay or similar in your program loop is all thats needed.How long really depends on the type of heater you are using and the environment its heating.You ideally need to match the heater to the area you are covering; example , using a 1kw fan heater in a cubic meter will always be difficult to control.Have used a variety of 60w to 2kw heaters in air and water and find a 90 second between gives good control and keeps things to within 0.1c of the set temp.You can improve your averaging routine by removing the two lowest and two highest readings which could be things caused by spikes in a noisy environment.For similar reasons I would increase the delay time between adc reads to at least 100ms+ rather than the 10ms you have.

author: brucehoult
author_rank: Super Contributor
timestamp: August 11, 2017, 01:33:07 pm
content: Quote from: Mr.B on August 11, 2017, 07:06:43 amNah.I've used an Uno to PID control a 2400W oil column heater for years. Works fantastic. I use a thermistor to sample the temperature, average 100 readings to get effectively 0.01C resolution, and smooth that a bit more. I make a decision whether to turn the heater on or off every 30 seconds, and control it using 433 MHz radio controlled 240V sockets from Jaycar.They're not really designed for this kind of abuse, and do burn out eventually, but they generally tolerate 1 - 2 years of this abuse first. At a cost of three of them for $40 this is not a problem, when the Arduino system is saving me several hundred dollars a year in electricity compared to when I used a Honeywell mechanical thermostat for the same purpose.Between the thermostat hysteresis and the thermal inertia of the heater, the Honeywell gave a room temperature swing of 2 C every cycle. With the Arduino, I get control to (according to its own measurements) within normally 0.02 C, spiking to as much as 0.25 C for a few minutes if another heat source such as cooking suddenly appears or stops.My PID is just simple floating point code I found on the net somewhere. The Uno is not fast at software FP, but 10 us per operation is not a problem in this application!Perhaps the only non-obvious/tricky thing is that I programmed a simple physical model of the heater. adding to its "stored energy" whenever it is turned on, and with the stored energy leaking to the room with a 10 minute time constant. It is the heater energy that is the controlled variable of the PID, not the simple heater on/off state.(I think this is probably equivalent to two chained PIDs, and I thought about reprogramming it that way, but never got around to it)

author: senso
author_rank: Frequent Contributor
timestamp: August 11, 2017, 03:57:33 pm
content: A PID is a couple dozen lines, and there are PID libs for Arduino if you dont want to type/copy paste it..Read this, its a simple intro into PID controllers, easy to understand, and in the end you have working code:http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

author: spongman
author_rank: Newbie
timestamp: August 12, 2017, 05:36:49 am
content: Quote from: Mr.B on August 11, 2017, 07:06:43 amon the contrary, there's nothing really complicated about a PID controller, it's just a bunch of simple math. it's not like it requires fast DMA or complicated matrix math.there are several very good arduino libraries available that do almost everything for you, including auto-tuning. i have used them with great success for simple control systems.

author: Rerouter
author_rank: Super Contributor
timestamp: August 12, 2017, 05:54:53 am
content: PID is as easy or as difficult as you want it to be, for most things it would only need to be a PI, (no derivative which gets unhappy about noisy signals) P is a floating point subtraction and multiplication in most libraries. I is a multiplication of P and a sum, add on some bounds checking and there isn't really much to it.For relays you would then define the on / off hysteresis, how far past set point the temperature has to reach before you will actually switch it. note for most thermal systems, the hysteresis width is inversly proportional to the amount of times the switching element is cycled.because of the lag between switching and a change in measurement, many will have a biased hysteresis, e.g. switch off at 1C over, but switch on at 5C under, because there is a lag between the item being heated and the temp being measured, so by the time the item has heated up to 1C over set point and you switch off the heating element, it will continue raising a bit higher before it settles and begins falling. whereas unless your heating element is quite small, from the moment you turn on the heating element it will likely begin to heat up.

author: brucehoult
author_rank: Super Contributor
timestamp: August 12, 2017, 12:54:52 pm
content: Quote from: Rerouter on August 12, 2017, 05:54:53 amBut pretty much the whole point of using PID is that the D term, properly tuned, will turn off the heater *before* you reach the desired temperature, and the lag will just cruise you up nicely to the desired set point, upon which the I term will take over to run the heater enough to keep the error at zero (on average).

author: lilshawn
author_rank: Regular Contributor
timestamp: August 13, 2017, 12:37:21 am
content: Thank you to all who have posted. This quickly went to overwhelming.This circuit will be used to control a secondary relay that will be switching a 240 volt, 4kw heater to heat a large volume of water of about 2 to 3 cubic meters in volume. (think hot tub or spa)There won't really be wild swings of temperature in short time periods due to the sheer volume of water...unless I intentionally add a pile of 4c water to the tank. I'm currently finding it take about an hour of heating to change the volume of water ~1 degree C. so overshooting or lag i believe won't be an issue. I think a 1c resolution is probably fine.

author: picandmix
author_rank: Frequent Contributor
timestamp: August 13, 2017, 08:29:02 am
content: Quote from: lilshawn on August 13, 2017, 12:37:21 amYou might have a problem with those relays causing interference to the Arduino when switching that heavy load, unless you have very good circuit design; another reason to add a delay into your program so it cannot do any ADC reads when the 'slow' relay switching /arcing is in progressPerhaps consider consider using a 30A SSR, a quality one, not the cheapy ebay types which can be over rated.

author: lilshawn
author_rank: Regular Contributor
timestamp: August 13, 2017, 04:19:43 pm
content: Quote from: picandmix on August 13, 2017, 08:29:02 amI figured noise was going to be an issue. I am using pull down resistors on the inputs and outputs to force the lines low so a definite change of state is detected. The relay I will be directly controlling with the arduino is optically isolated. I'll be mounting the arduino itself in a metal enclosure separate from the high voltage side.I'd considered an SSR, but our power system we are using is 2 separate 120v phases...so I'd have to switch 2 lines at the same time. Trying to weed out ebay junk from good stuff when looking for a multiphase SSR was proving difficult. Our local electronics supplier was of no help. I ended up settling on a mitsubishi magnetic contactor I had kicking around since I know for sure it's a known good, quality part...and capable of the job.

author: picandmix
author_rank: Frequent Contributor
timestamp: August 13, 2017, 04:42:29 pm
content: If all you are doing is the temp control, then you could easily use the Watchdog function to restart the program if the relays interference is too bad. Worst case you could always add a slow running astable on the Reset line.

author: Phoenix
author_rank: Frequent Contributor
timestamp: August 14, 2017, 05:07:12 am
content: PID is not practical in this case as the OP only has a relay as the actuactor - full on or full off.A PID controller relies on being able to output a continuous range of output duty cycles. This would mean duty cycle control of the relay at some periodic rate (10x - 100x the thermal time constant). Plus some significant transport delay making tuning much harder.A hysteresis controller seems ideal as it relies on the output actuator being full on or full off and keeps the temperature in acceptable bounds. Much easier to implement and requires no tuning.

author: DBecker
author_rank: Frequent Contributor
timestamp: August 14, 2017, 04:56:47 pm
content: A second on the simple hysteresis control.People too quickly say "use PID", when it's often not the best solution. And when it's a good solution, you typically want a PI controller (the derivative term set to 0) so that you don't have to analyze instabilities when the plant doesn't match the model.You'll want a 'contactor' to switch the final load. A contactor is simply a heavy duty relay rated for power control and continuous use, typically with a full line voltage coil. They are surprisingly inexpensive -- $10 for a Packard style on FleaBay. One rated at 40 amps can carry 40 amps all day long, or switch dozens of times a day, for years, A 40 amp FleaBay SSR will last only a few seconds or minutes with the same use.