LA
Offline
Jr. Member
Karma: 0
Posts: 51
Arduino rocks
|
 |
« on: June 22, 2009, 08:12:30 pm » |
Hey all I am currently playing with some of the PID scripts and my arduino.
I've got it hooked up to two things, a heater to heat to the set temp and a thermocouple to take the readings and adjust accordingly.
My questions are about the script...
I've got the following script uploaded to my board:
/******************************************************** * PID Simple Example * Reading analog input 0 to control analog PWM output 3 ********************************************************/
#include <PID_Beta6.h>
//Define Variables we'll be connecting to double Setpoint, Input, Output;
//Specify the links and initial tuning parameters PID myPID(&Input, &Output, &Setpoint, 2,5,1);
void setup() { //initialize the variables we're linked to Input = analogRead(0); Setpoint = 150; //turn the PID on myPID.SetMode(AUTO); myPID.SetSampleTime(250); myPID.SetTunings(2,3,1); }
void loop() { Input = analogRead(0); myPID.Compute(); analogWrite(3,Output); }
Now, when the board is turned on, it starts heating to the setpoint and does a magnificent job of keeping it there.
What I am trying to achieve is adding a on/off button to trigger the board to start heating the element ONLY when the signal from the button is received Also, I would like to add two buttons that adjust the temperature UP or DOWN, and a LCD readout of the Setpoint, and the ACTUAL temperature VIA a single serial wire.
Can anyone point me to the direction where I might find an example of this? Or simply throw the code down in a post? I would imagine the first two things I am trying to achieve are relatively simple in terms of coding. The simple on/off thing and temp up/down in response to the buttons.
Thanks in advance for all your responses!
|
|
|
|
|
Logged
|
|
|
|
|
LA
Offline
Jr. Member
Karma: 0
Posts: 51
Arduino rocks
|
 |
« Reply #1 on: June 23, 2009, 01:01:10 pm » |
Okay... So i've got 3 SPST pushbutton switches (Normally Open) hooked up to +5v and the outputs of each going to digital pins 4--- (Trigger or operation button) 5---(Increase temp by 1 degree) and 6----(Decrease temp)
As far as the On/off operation goes.. Am I kind of on the right track??... I'd like to keep the code as simple as possible.
void setup() { //initialize the variables we're linked to Input = analogRead(0); Input = digitalRead(4); Input = digitalRead(5); Input = digitalRead(6); Setpoint = 150; //turn the PID on myPID.SetMode(AUTO); myPID.SetSampleTime(250); myPID.SetTunings(2,3,1); myPID.SetOutputLimits(0, 178.5); }
void loop() { Input = analogRead(0); myPID.Compute(); if(digitalRead(4),HIGH); analogWrite(3,Output); }else{ I dont know what to put here?? }
How's this going?
Did I do okay introducing the new inputs? Should it be digital or analog?
|
|
|
|
« Last Edit: June 23, 2009, 01:01:32 pm by dacr0n »
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Online
Shannon Member
Karma: 116
Posts: 10142
|
 |
« Reply #2 on: June 23, 2009, 07:09:00 pm » |
I may be able help with one item on your list. This PID algorithm appears to include mode (myPID.SetMode). If mode works with this implementation the way I've seen it work with other implementations (the way it should work) you can use it to "turn off" and "turn on" the PID loop. Setting mode to manual should... - Leave the output value at the current value
- Stop updating the internal values from the input
Setting mode back to auto should... - Reset the internal values
- Provide a "bumpless" transition from the current (old) output value to the next (new) output value
- Seamlessly resume calculations
Good luck, Brian
|
|
|
|
|
Logged
|
|
|
|
|
Boston
Offline
Full Member
Karma: 0
Posts: 101
Arduino rocks
|
 |
« Reply #3 on: June 25, 2009, 11:55:38 am » |
coding badly is correct. (that is a sentence I never thought I'd write!) that is to say, Brian is correct.
you can have your on/off button toggle the Auto/Manual state of the pid using the SetMode(..) function. when in manual mode, the pid will stay out of things, and you can write whatever you want to the output variable.
for ease of coding you're still free to all Call myPID.Compute(). it will see that the current mode is manual and will immediately return without calculating.
glad to hear that the library is working for you!
Brett
|
|
|
|
« Last Edit: June 25, 2009, 12:17:25 pm by br3ttb »
|
Logged
|
|
|
|
|
LA
Offline
Jr. Member
Karma: 0
Posts: 51
Arduino rocks
|
 |
« Reply #4 on: June 30, 2009, 02:46:03 pm » |
Okay... So I have done a bit of tinkering and moving the code around. I've taken small portions of code from the "button library" to see if I can get this going.....
It complied Okay in the arduino program, but I am wondering if anyone see's anything that is wrong right off the bat.
I've put my goals to hook up the LCD untill later when I get the buttons working and doing what I want.
I think I have the on/off thing going... I just need someone to give me some pointers on how to make "buttonPin2" and "buttonPin3" to increase and decrease the setpoint by 1 degree.
Here's what I've got so far.
/******************************************************** * PID Simple Example * Reading analog input 0 to control analog PWM output 3 ********************************************************/
#include <PID_Beta6.h>
//Define Variables we'll be connecting to double Setpoint, Input, Output;
const int buttonPin1 = 1; // the number of the RUNpushbutton pin const int buttonPin2 = 2; // the number of the UPpushbutton pin const int buttonPin3 = 3; // the number of the DOWNpushbutton pin // variables will change: int buttonState = 0; // variable for reading the pushbutton status
//Specify the links and initial tuning parameters PID myPID(&Input, &Output, &Setpoint, 2,5,1);
void setup() { // initialize the pushbuttons as inputs: pinMode(buttonPin1, INPUT); pinMode(buttonPin2, INPUT); pinMode(buttonPin3, INPUT); //initialize the variables we're linked to Input = analogRead(0); Setpoint = 100; //set initial tunings myPID.SetSampleTime(250); myPID.SetTunings(2,3,1); myPID.SetOutputLimits(0, 220); }
void loop() { // read the state of the pushbutton value: buttonState = digitalRead(buttonPin1);
// check if the RUNpushbutton is pressed. // if it is, the buttonState is HIGH: if (buttonState == HIGH) { // Perform action: Input = analogRead(0); myPID.Compute(); analogWrite(3,Output); } else { // Turn PID OFF myPID.SetMode(MANUAL); } }
|
|
|
|
|
Logged
|
|
|
|
|
Boston
Offline
Full Member
Karma: 0
Posts: 101
Arduino rocks
|
 |
« Reply #5 on: June 30, 2009, 03:08:37 pm » |
the basic way to increase the setpoint would be if(digitalRead(buttonPin2)==HIGH) { Setpoint+=1; } the problem with this is that since loop excecutes so quickly, this code may be hit several times in the time it takes to press and release the button. what I have done in similar situations is instead of looking at the current state of the button, I looked for a CHANGE in the state of the button. so something like: int lastState = LOW; void loop() { int currentState = digitalRead(buttonPin2); if(currentState == HIGH && lastState ==LOW) //only go in if we were off last time, and on this time { Setpoint+=1; //increment the setpoint } lastState = currentState; //remember the button state for next time } Hope that helps. Brett
|
|
|
|
« Last Edit: June 30, 2009, 03:09:48 pm by br3ttb »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 7
Arduino rocks
|
 |
« Reply #6 on: June 30, 2009, 04:58:08 pm » |
That code could still trigger multiple events due to contact bouncing. I would suggest setting a minimum elapsed time before letting the button trigger another event. For example: unsigned long lastTime; if(digitalRead(buttonPin2)==HIGH) { if (lastTime+250<millis()) { Setpoint+=1; lastTime=millis(); } }
That way, you can click the button once, and it'll increase one degree, or hold it down to increase at a rate of 4 per second. With a bit more coding, you could have it count how long the button stays down, and after say, 2 seconds, have it increase the rate of change.
|
|
|
|
|
Logged
|
|
|
|
|
Boston
Offline
Full Member
Karma: 0
Posts: 101
Arduino rocks
|
 |
« Reply #7 on: June 30, 2009, 05:12:30 pm » |
That code could still trigger multiple events due to contact bouncing That's a good point goose. I like your way better. Brett
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Online
Shannon Member
Karma: 116
Posts: 10142
|
 |
« Reply #8 on: June 30, 2009, 05:14:03 pm » |
Given that this system is still under development and that you're trying to control something that could be dangerous (heaters have been know to cause burns  ), I suggest starting the PID loop in manual. This gives you an opportunity to look things over before letting the (potentially buggy) code take control... void setup() { // stuff already in your setup... myPID.SetMode(MANUAL); }
If the PID code supports writes to the output (some sort of command like myPID.WriteOutput or myPID.SetOutput), you should move these two lines of code... myPID.Compute(); analogWrite(3,Output); ...to the bottom of loop so they always execute. This will provide output clamping in one place (the PID code). Even if the PID code does not support writes to the output, there is no harm in moving the two lines of code. When the loop is in manual, Output won't change. - Brian
|
|
|
|
« Last Edit: June 30, 2009, 05:16:17 pm by bcook »
|
Logged
|
|
|
|
|
LA
Offline
Jr. Member
Karma: 0
Posts: 51
Arduino rocks
|
 |
« Reply #9 on: June 30, 2009, 07:35:21 pm » |
Thanks for all the tips everyone!
I am just finishing up wiring the thing and I will apply the changes to the code that have been recommended.
Now... Since I don't have the LCD hooked up at present... Is there a way to monitor the "setpoint" as I change it up and down with the buttons? Like to make sure that they're doing what they're supposed to? I notice on the arduino program there is a serial monitor button...
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Online
Shannon Member
Karma: 116
Posts: 10142
|
 |
« Reply #10 on: June 30, 2009, 07:37:37 pm » |
goose2283: This... if (lastTime+250<millis()) { ...doesn't work quite the way you expect when millis is close to wrapping. Let's say that the previous time through loop, lastTime was set to 0xFFFFFFFF - 249. This time through the loop we have... if ( (0xFFFFFFFF - 249)+250<millis()) { if ( 1<millis()) { For the 250ms until millis() wraps back to zero the condition is always true. Generally, it's better to calculate the delta then compare... if (millis()-lastTime>=250) { - Brian
|
|
|
|
|
Logged
|
|
|
|
|
Left Coast, CA (USA)
Offline
Brattain Member
Karma: 279
Posts: 15314
Measurement changes behavior
|
 |
« Reply #11 on: June 30, 2009, 07:41:29 pm » |
Yes, the Arduino's serial command is the simplest way to debug or use as a temporary user interface to test out the basic application, then later you can can add the LCD UI stuff. You can use the Arduino's serial monitor or a PC serial terminal program to monitor system performance and even send setpoint and mode commands to the your Arduino sketch.
Lefty
|
|
|
|
|
Logged
|
|
|
|
|
LA
Offline
Jr. Member
Karma: 0
Posts: 51
Arduino rocks
|
 |
« Reply #12 on: July 01, 2009, 05:15:25 pm » |
Well... I have cleaned up a bit to take things one step at a time.. So... All I want is for the PID code to send the PWM output signal ONLY then the button is ON. //******************************************************** * PID Simple Example * Reading analog input 0 to control analog PWM output 3 ********************************************************/
#include <PID_Beta6.h>
//Define Variables we'll be connecting to double Setpoint, Input, Output;
//Specify the links and initial tuning parameters PID myPID(&Input, &Output, &Setpoint,2,5,1); const int onPin = 1; // choose the input pin to trigger heater const int upPin = 2; // choose the input pin to increase temp const int downPin = 3; // choose the input pin to decrease temp int buttonState = 0; // variable for reading the pin status
void setup() { // Declare inputs pinMode(onPin, INPUT); // declare pushbutton as input pinMode(upPin, INPUT); // declare pushbutton as input pinMode(downPin, INPUT); // declare pushbutton as input //initialize the variables we're linked to Input = analogRead(0); Setpoint = 100; myPID.SetSampleTime(250); myPID.SetTunings(2,3,1); myPID.SetOutputLimits(0, 220); }
void loop() { // read the state of the pushbutton value: buttonState = digitalRead(onPin); // check if the pushbutton is pressed. // if it is, the buttonState is HIGH: if (buttonState == HIGH) { // turn PID on: WHAT CODE HERE?; } else { // turn PID off: WHAT CODE HERE?; } Input = analogRead(0); myPID.Compute(); analogWrite(3,Output); } Did I do all the declarations and stuff right?
|
|
|
|
« Last Edit: July 01, 2009, 05:26:55 pm by dacr0n »
|
Logged
|
|
|
|
|
LA
Offline
Jr. Member
Karma: 0
Posts: 51
Arduino rocks
|
 |
« Reply #13 on: July 01, 2009, 06:01:08 pm » |
in regards to "myPID.SetMode(MANUAL);"
doesn't the mode refer to auto or manual tuning? Not operation...
From what I understand that Coding Baldy said MANUAL mode is OFF?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Online
Shannon Member
Karma: 116
Posts: 10142
|
 |
« Reply #14 on: July 01, 2009, 06:56:41 pm » |
doesn't the mode refer to auto or manual tuning? No. MANUAL mode is OFF? Yes.
The terms are historical. Long ago, closed-loop control was performed by a human. The person would walk about, write instrument readings on paper, perform calculations, then adjust valves. In other words, control was performed manually. Automatic means a machine is performing the closed-loop control. - Brian
|
|
|
|
« Last Edit: July 01, 2009, 07:45:34 pm by bcook »
|
Logged
|
|
|
|
|
|