Show Posts
Pages: [1]
1  Forum 2005-2010 (read only) / News / Re: Arduino PID Library on: January 08, 2011, 11:02:00 am
fiveohhh
Quote
I'm planning on doing the same thing in a few weeks here(with an lm335 though).  What did you do to waterproof the sensor?

I had nothing but trouble with the LM temperature sensors.  I couldn't get stability regardless of the resistors I used.  Averaging might work better for you than me, but I had enough and just gave up.

The one-wire sensors from Maxim are accurate and dead easy with the existing libraries.  

Anyway, I've waterproofed one or the other a few different ways.  The best I've come up with so far is putting the chip in a piece of heatshrink tubing, filing the tubing with silicone sealant, letting the sealant almost set, then heat shrinking the tubing to tighten it all up.  It's the best compromise between waterproof and quick temperature response that I've had so far.  

Good luck!
2  Forum 2005-2010 (read only) / News / Re: Arduino PID Library on: November 18, 2010, 08:37:10 pm
Hey all,

I've finished up the code for a standalone sous vide controller with a small LCD screen and a 3-button interface.  I'm using the one-wire DS18B20 temperature sensor for input and a solid state relay receives the output.  

All the parts are here, and everything works, I just need to put it together now.  I figured I'd post the code for others to critique:

Code:
#include <TimerOne.h>
#include <PID_Beta6.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
#include <Button.h>

#define ONE_WIRE_BUS 9

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int controlPin = 10;

int upButtonPin = 6;
int downButtonPin = 7;
int selButtonPin = 8;

Button upButton = Button(upButtonPin, PULLDOWN);
Button downButton = Button(downButtonPin, PULLDOWN);
Button selButton = Button(selButtonPin, PULLDOWN);

double params[4] = {140, 90,300,0};
char param_char[4] = {'S', 'P', 'I', 'D'};
double increment[4] = {1, 5, 5, 5};

double Input, Output;                            
double Setpoint = params[0];                          
double Bias = 200;

float temperature = 0;                            
int menuPos = 0;
int loopDelay = 0;

PID pid(&Input, &Output, &Setpoint, &Bias, params[1], params[2], params[3]);

void setup()
{
  /*Serial.begin(9600);*/
  pinMode(controlPin, OUTPUT);  
  
  sensors.begin();

  pid.SetOutputLimits(0,1023);  
  Output = 0;
  pid.SetMode(AUTO);

  Timer1.initialize();
  Timer1.pwm(controlPin, Output);
  
 
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("Arduino PID");
  lcd.setCursor(0,1);
  lcd.print("Controller");
  /*Serial.print("Arduino PID Controller\n");*/
  delay(5000);
  lcd.clear();
}

void loop()
{
  sensors.requestTemperatures();
  temperature = sensors.getTempFByIndex(0);

  Input = (double)temperature;
  if(Setpoint - Input > 3){
    Setpoint -= 5;
    pid.Compute();
    Setpoint += 5;
  }
  else{
    pid.Compute();
  }
  
  Timer1.setPwmDuty(controlPin, (int)Output);
  delay(loopDelay);
  
  lcd.setCursor(0,0);
  lcd.print("T:");
  lcd.print(temperature,1);
  lcd.setCursor(9,1);
  lcd.print("O:");
  lcd.print(Output,0);
  lcd.setCursor(0, 1);
  lcd.print("S:");
  lcd.print(Setpoint,0);

  /*Serial.print("T:");
  Serial.print(temperature);
  Serial.print("\t");
  Serial.print("O:");
  Serial.print(Output,0);
  Serial.print("\t");
  Serial.print("S:");
  Serial.print(Setpoint,0);
  Serial.print("\n");*/
  
  if(selButton.uniquePress()) {
    lcd.clear();
    for(menuPos = 0; menuPos < 4; ){
      lcd.setCursor(0,0);
      lcd.print(param_char[menuPos]);
      lcd.print(": ");
      lcd.print(params[menuPos],0);

      /*Serial.print(param_char[menuPos]);
      Serial.print(": ");
      Serial.print(params[menuPos],0);      
      Serial.print("\n");*/

      if (upButton.uniquePress()) {        
        params[menuPos] += increment[menuPos];
      }
      if (downButton.uniquePress()) {        
        params[menuPos] -= increment[menuPos];
      }
      if(selButton.uniquePress()) {
        menuPos++;
        lcd.clear();
      }
    }
    Setpoint = params[0];
    pid.SetTunings(params[1], params[2], params[3]);
    lcd.clear();
  }
}  

All the commented out serial stuff is from testing before my LCD came.  Let me know if you have any questions or advice on something I could do better.

PS - I just realized scanning my code here that the menu loop keeps the PID from calculating, so if it was left in that mode the output would never change.  I guess I'll work a button timer in there to jump back to the main loop if you don't do anything for 5 seconds or so.


3  Forum 2005-2010 (read only) / News / Re: Arduino PID Library on: July 10, 2010, 06:15:23 am
I'm not sure about the sampletime issue, the author is in probably a better position to answer that, but for a long PWM frequency like that, it's probably best you just write a window-like function similar to the one in the second example on the PID library page (he uses a 4 second frequency I think).  It doesn't matter how fast it samples, only how fast the output is switched.

Set outputlimits to 0 to 59 and declare a windowstarttime = millis()/60000 to get it in minutes.

Then
Code:

if((millis()/60000)-windowstarttime > 60) windowstarttime += 60;

if(Output > (millis()/60000)-windowstarttime) digitalWrite(pin, HIGH);
else digitalWrite(pin, LOW);

 

I think that should do it.
4  Forum 2005-2010 (read only) / News / Re: Arduino PID Library on: July 07, 2010, 09:40:10 am
Thanks for the quick reponse!

Yeah, I understand about the tuning parameters, I guess I'll just have to eyeball things until I get them set up right.  Like I said, nothing is built just yet, it's still diagrams and connections floating around in my head.  I've heard it'll probably take a long time (hours? days?) to tune due to the slow response of my systems (I'm thinking the smoker will probably be faster than the water bath though).  

The Timer1 library is something I stumbled upon while trying to figure out how to slow down the arduino PWM.  I think I understood the software "window" method that you wrote into the second example on the PID library page, but it seemed like there must be a better way.  I don't claim to understand it completely, but it seems like just the ticket for what I'm trying to do:

http://www.arduino.cc/playground/Code/Timer1

Thanks again!

-zv
5  Forum 2005-2010 (read only) / News / Re: Arduino PID Library on: July 07, 2010, 09:14:43 am
Brett,

I am building a simple temperature controller and I'm attempting to use your PID library.  The arduino reads the temperature from an LM35 and then outputs a slow PWM pulse to a solid state relay which will switch a standard electrical output.  I figure I'll plug in either a water bath heater or an electric smoker to the outlet, it seems like it should work just as well for either application.  Anyhow, I don't have much of the hardware yet (it's all on order), but I put together the code and I wanted to make sure I was utilizing the PID library correctly.  As you can see, I'm using the Timer1 library to run a 1 second PWM pulse.  I wouldn't think a heating element would need anything faster than that.  The PID output adjusts the duty cycle of the pulse:

Code:
#include <TimerOne.h>      
#include <PID_Beta6.h>

double Input, Output;                                  //PID variables
double Setpoint = 140;                               //PID setpoint in Farenheit
 
int thermPin = 0;                                    //input read pin for LM35 is Analog Pin 0
int controlPin = 9;                                           //Output PWM pin to Solid State Relay
                            
int val;

PID pid(&Input, &Output, &Setpoint, 3,4,1);            //Setup the PID calculation

void setup()
{

         pinMode(controlPin, OUTPUT);              //Setup the pin to control the relay

         pid.SetOutputLimits(0,1023);             //tell the PID to range the output from 0 to 1023
         Output = 1023;                                     //start the output at its max  and let the PID adjust it from there
         pid.SetMode(AUTO);                               //turn on the PID

      Timer1.initialize();                              //turn on the Timer, default 1 second frequency
      Timer1.pwm(controlPin, (int)Output);      //start PWM on pin 9 with a 100% duty cycle
  
}

void loop()
{
    
         val = analogRead(thermPin);                                                        //read the value of LM35
         Input = ((5.0 * val * 100.0 / 1023.0) * 9.0 / 5.0) + 32.0;       //convert voltage to temperature(F)

         pid.Compute();                                                      //give the PID the opportunity to compute if needed

      Timer1.setPwmDuty(controlPin, (int)Output);            //Set the duty cycle of the PWM according to the PID output

}
 

Any comments or tips would be very much appreciated.

-zv
6  Forum 2005-2010 (read only) / News / Re: Processing Front-End for the PID Library on: July 08, 2010, 06:27:33 pm
Hi there,

I am attempting to get the frontend working for the PID library and I've hit something of a snag.  I am getting the following error when I run the program in Processing:

Code:
error, disabling serialEvent() for /dev/ttyUSB0
java.lang.reflect.InvocationTargetException
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:616)
      at processing.serial.Serial.serialEvent(Unknown Source)
      at gnu.io.RXTXPort.sendEvent(RXTXPort.java:732)
      at gnu.io.RXTXPort.eventLoop(Native Method)
      at gnu.io.RXTXPort$MonitorThread.run(RXTXPort.java:1575)
Caused by: java.lang.NullPointerException
      at PID_FrontEnd_v02.serialEvent(PID_FrontEnd_v02.java:436)
      ... 8 more

The graphical display comes up but no data is passed to or received from the arduino.  Nothing comes up on the graph or in the data fields to the left.

I was able to eliminate the error by removing the setValue() and setText() commands in serialEvent().  If I comment out those lines, like this:

Code:
//take the string the arduino sends us and parse it
void serialEvent(Serial myPort)
{
  
  String read = myPort.readStringUntil(10);
  if(outputFileName!="") output.print(str(millis())+ " "+read);
  String[] s = split(read, " ");
  if (s.length ==8)
  {
    Setpoint = float(s[1]);           // * pull the information
    Input = float(s[2]);              //   we need out of the
    Output = float(s[3]);             //   string and put it
    //SPLabel.setValue(s[1]);           //   where it's needed
    //InLabel.setValue(s[2]);           //
    //OutLabel.setValue(trim(s[3]));    //
    //PLabel.setValue(trim(s[4]));      //
    //ILabel.setValue(trim(s[5]));      //
    //DLabel.setValue(trim(s[6]));      //
    //AMCurrent.setValue(trim(s[7]));   //

    if(justSent)                      // * if this is the first read
    {                                 //   since we sent values to
      //SPField.setText(trim(s[1]));    //   the arduino,  take the
      //InField.setText(trim(s[2]));    //   current values and put
      //OutField.setText(trim(s[3]));   //   them into the input fields
      //PField.setText(trim(s[4]));     //
      //IField.setText(trim(s[5]));     //
      //DField.setText(trim(s[6]));     //
      mode = trim(s[7]);              //
      //AMLabel.setValue(mode);         //
      justSent=false;                 //
    }                               //

    if(!madeContact) madeContact=true;
  }
}

Again, the graphical window comes up, but some data starts coming from the arduino (the led starts blinking), and it begins drawing the setpoint, input, and output lines.  The data fields to the left do not show anything.  However, I can change the setpoint, "Send to Arduino" and the green line will reflect the change.

I've read around a bit about this error, but I still don't understand what's going on.  

Do you have any thoughts?

BTW I'm running on Ubuntu, if that makes any difference.

EDIT:  I just tried this on a windows laptop and it worked with no errors.  It must be specific to Linux or Ubuntu versions of processing.

EDIT2: This thread is the closest I've come to a similar error, but its from 2007, and they don't have a solution:

http://processing.org/discourse/yabb2/YaBB.pl?num=1183525352
Pages: [1]