Arduino/ATMega based Digital Soldering station

Think you've got a good idea? Share it with us and it might just end up on the show!
Jarod
Site Admin
Posts: 190
Joined: Sat Dec 11, 2010 12:34 am
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by Jarod » Thu Jul 05, 2012 8:19 pm

yea, worst part in my mind is doing the conversion from the analog in values to actual temp values. I only have one real reference point and I'm not sure how to do that, I've thought about putting it in boiling water and then i'd have a 100C reference, but water might short something out.

The hill climbing is completely over my head, i tried reading the article you linked and nearly broke my brain again. :lol:
I'm assuming it'd be to help prevent overshooting and keep the temperature constant so it doesn't swing all over the place?

foxmiles
Posts: 90
Joined: Fri Dec 24, 2010 1:57 pm
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by foxmiles » Thu Jul 05, 2012 8:25 pm

Messed around with some code last night. I integrated analog input averaging and a hill climbing function for output with the analoginoutserial example. I'm sure there are better ways to do this, but here's what I came up with.

Code: Select all



 /*

Modifed to demonstrate a simple averaging and hill climbing control for a soldering station by Foxmiles 7/4/2012

  Analog input, analog output, serial output
 
 Reads an analog input pin, maps the result to a range from 0 to 255
 and uses the result to set the pulsewidth modulation (PWM) of an output pin.
 Also prints the results to the serial monitor.
 
 The circuit:
 * potentiometer connected to analog pin 0.
   Center pin of the potentiometer goes to the analog pin.
   side pins of the potentiometer go to +5V and ground
 * LED connected from digital pin 9 to ground
 
 created 29 Dec. 2008
 modified 30 Aug 2011
 by Tom Igoe
 
 This example code is in the public domain.
 
 */

// These constants won't change.  They're used to give names
// to the pins used:
const int analogInPin = A1;  // Analog input pin that the thermocouple amp is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

int sensorValue = 0;        // value read from the thermocouple
int outputValue = 0;        // value output to the PWM (analog out)
int desiredValue = 678; // this should be set to zero and controlled by the user to set the desired temperature. 
			//678 happens to be where 3.3v is on my arduino (it should stop the hill climbing) 
int hillclimb = 0; // value for the hill climbing algorithm
void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
}

void loop() {
  // read the analog in value:
  sensorValue = avrValue(analogInPin); // read the thermocouple value with averaging
//  sensorValue =  analogRead(analogInPin);
  hillclimb = hill(sensorValue, desiredValue, hillclimb); //compare the desired value to that read by the anolog input and adjust value to compensate
  // map it to the range of the analog out:
  outputValue = map(hillclimb, 0, 1023, 0, 255);  
  // change the analog out value:
  analogWrite(analogOutPin, outputValue);           

  // print the results to the serial monitor:
  Serial.print("sensor = " );                       
  Serial.print(sensorValue);      
  Serial.print("\t output = ");      
  Serial.println(outputValue);     

  // wait 10 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  // after the last reading:
//  delay(10);                     
}

//Most of my added code:

//simple analogRead averaging function. Call it with a pin like avrValue(A0)

int avrValue(const int pin){
int sensorValue = 0;
int  buffer=0;
int  count = 0;
  while (count <= 9){  // change the 9 and the 10 higher values for more samples. Make sure the 9 stays 1 less than the 10 or it will screw thing up.
    sensorValue = analogRead(pin);
    buffer = buffer + sensorValue;
    count++;
delay(10);
  }
  return (buffer / 10);
}


// Simple hill climbing algorithm, just pass it a value you're reading, the desired value and the last value it gave you like: hill(read, want, last) 
// you can change the values for faster adjustment or finer control as needed.

int hill(int av, int sp, int out) {
  

//if the desired value is over 25 points high correct by dropping output value by 10 points
  if (av >= sp+25 && out >= 26){
    out = out - 10;
  }
//if the desired value is over 5 points high correct by dropping output value by 1 points
  else if (av >= sp+5 && out >= 1){
    out = out - 1;
  }
//if the desired value is over 25 points low correct by increasing output value by 10 points
  else if (av <= sp-25 && out <= 998){
    out = out + 10;
  }
//if the desired value is over 5 points low correct by increasing output value by 1 points
  else if (av <= sp-5 && out <= 1023){
    out = out + 1;
  }
  return(out); // return the next value to try.
}
 
Digging with a spoon will accomplish more than leaning on a shovel.

Jarod
Site Admin
Posts: 190
Joined: Sat Dec 11, 2010 12:34 am
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by Jarod » Mon Jul 16, 2012 8:33 pm

I had a go at getting this all working last night, got it working fairly well, ladder climbing algorithm still needs more tweaking, started out wandering by around 30C, I got it down to around a 10C wander, but its could still get a lot better than that.

Heres my code so far.
its pretty poor and hacked together quite badly. I separated the lcd section in hopes to make it more readable with slower updates while still keeping the speed needed for the hillclimbing to work well.

Code: Select all

/*
  LiquidCrystal Library - Hello World
 
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 This sketch prints "Hello World!" to the LCD
 and shows the time.
 
  The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 
 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe
 
 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
long interval = 50;           // interval at which to take readings
long previousMillis = 0;        // will store last time LED was updated

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 3; // Analog output pin that the LED is attached to

int potValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)

int sensorPin = 5;
int sensorvalue = 0;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

int hillclimb = 0; // value for the hill climbing algorithm

void setup() {
  // set up the LCD's number of columns and rows: 
  pinMode(sensorPin, INPUT);
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
  for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;     
  Serial.begin(9600);  //Start the serial connection with the computer
}

void loop() {

// subtract the last reading:
  potValue = analogRead(analogInPin);            
  // map it to the range of the analog out:
//  outputValue = map(potValue, 0, 1023, 0, 255); 
  hillclimb = hill(average, potValue, hillclimb); //compare the desired value to that read by the anolog input and adjust value to compensate
  outputValue = map(hillclimb, 0, 1023, 0, 255);
  // change the analog out value:
  analogWrite(analogOutPin, outputValue); 
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

  total= total - readings[index];        
  // read from the sensor:  
  readings[index] = analogRead(sensorPin);
  // add the reading to the total:
  total= total + readings[index];      
  // advance to the next position in the array:  
  index = index + 1;                    

  // if we're at the end of the array...
  if (index >= numReadings)              
    // ...wrap around to the beginning:
    index = 0;                          

  // calculate the average:
  average = total / numReadings;     
  }
  
  

  display(average, outputValue, potValue);
  
  
//  Serial.println(sensorvalue);
}

int display(int average, int outputValue, int potValue) {
     // converting that reading to voltage, for 3.3v arduino use 3.3
 float voltage = average * 5.0;
 voltage /= 1024.0; 
 
 // print out the voltage
 //Serial.print(average); Serial.println(" volts");
 
 // now print out the temperature
 float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((volatge - 500mV) times 100)
 Serial.print(temperatureC); Serial.println(" degrees C");
 
 // now convert to Fahrenheight
 float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
 //Serial.print(temperatureF); Serial.println(" degrees F");
  // send it to the computer as ASCII digits
 // Serial.println(average);  
  
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print("                   ");
    lcd.setCursor(0, 1);

  lcd.print(average);
  lcd.setCursor(4, 1);
  //lcd.print(temperatureC);
  lcd.print(outputValue);
  lcd.setCursor(10, 1);
  lcd.print(potValue);
  
}

int hill(int av, int sp, int out) {
 

//if the desired value is over 25 points high correct by dropping output value by 10 points
  if (av >= sp+80 && out >= 26){
    out = out - 10;
  }
//if the desired value is over 5 points high correct by dropping output value by 1 points
  else if (av >= sp+40 && out >= 1){
    out = out - 3;
  }
//if the desired value is over 5 points high correct by dropping output value by 1 points
  else if (av >= sp+5 && out >= 1){
    out = out - 1;
  }
//if the desired value is over 25 points low correct by increasing output value by 10 points
  else if (av <= sp-150 && out <= 998){
    out = out + 10;
  }
//if the desired value is over 25 points low correct by increasing output value by 10 points
  else if (av <= sp-40 && out <= 998){
    out = out + 2;
  }
//if the desired value is over 5 points low correct by increasing output value by 1 points
  else if (av <= sp-5 && out <= 1023){
    out = out + 1;
  }

  return(out); // return the next value to try.
}

foxmiles
Posts: 90
Joined: Fri Dec 24, 2010 1:57 pm
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by foxmiles » Mon Jul 16, 2012 9:08 pm

I think I know the problem. I had a 10 point sweet spot in the hill climbing function. I suggest changing:
sp+5 to sp+1
and
sp-5 to sp-1
maybe try something like:

Code: Select all

int hill(int av, int sp, int out) {
 

//if the desired value is over 125 points high correct by dropping output value by 20 points
  if (av >= sp+125 && out >= 20){
    out = out - 20;
  }
//if the desired value is over 50 points high correct by dropping output value by 10 points
  else if (av >= sp+50 && out >= 10){
    out = out - 10;
  }
//if the desired value is over 1 points high correct by dropping output value by 1 points
  else if (av >= sp+1 && out >= 1){
    out = out - 1;
  }
//if the desired value is over 125 points low correct by increasing output value by 20 points
  else if (av <= sp-125 && out <= 1002){
    out = out + 20;
  }
//if the desired value is over 50 points low correct by increasing output value by 10 points
  else if (av <= sp-50 && out <= 1012){
    out = out + 10;
  }
//if the desired value is over 1 points low correct by increasing output value by 1 points
  else if (av <= sp-1 && out <= 1023){
    out = out + 1;
  }

  return(out); // return the next value to try.
}
Digging with a spoon will accomplish more than leaning on a shovel.

Jarod
Site Admin
Posts: 190
Joined: Sat Dec 11, 2010 12:34 am
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by Jarod » Mon Jul 16, 2012 9:57 pm

still seems to have huge swings, the temperature doesn't update immediately, so it overshoots by about 30C then drops below by about 30C, then slowly evens off about right after a few minutes, adjusting the temp starts that cycle all over again.

Jarod
Site Admin
Posts: 190
Joined: Sat Dec 11, 2010 12:34 am
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by Jarod » Mon Jul 16, 2012 11:00 pm

I think what it needs is a way to ramp off before it hits the desired temp. so on the way up it starts slowly decreasing the value before it hits the desired temp and on the way down it starts raising the value before it hits the desired temp.

I'll have to work on it more tomorrow, headed to bed, work at 4:45 and then chopping firewood for a while after that.

foxmiles
Posts: 90
Joined: Fri Dec 24, 2010 1:57 pm
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by foxmiles » Mon Jul 16, 2012 11:46 pm

Perhaps this would work better?
As much as I hate wasting cycles this may help. It makes smaller changes and adds a 50ms delay to big changes and a 100ms delay to small changes. There will be a "ringing" with this, but it should (we want it to, idk if it will) stabilize fairly quickly. You could do a preheat cycle on power-up, run at 50% for 10 seconds or so then start the program? idk. You could map a smaller space for it instead of 0-254 you could do 32-160? (wherever it normally stabilises)

Code: Select all

int hill(int av, int sp, int out) {
 
//if the desired value is over 50 points high correct by dropping output value by 5 points
  if (av >= sp+50 && out >= 5){
    out = out - 5;
  }
//if the desired value is over 1 point high correct by dropping output value by 1 points
 else if (av >= sp+1 && out >= 1){
    out = out - 1;
    delay(50);
  }
//if the desired value is over 50 points low correct by increasing output value by 5 points
  else if (av <= sp-50 && out <= 1000){
    out = out + 5;
  }
//if the desired value is over 1 point low correct by increasing output value by 1 points
  else if (av <= sp-1 && out <= 1023){
    out = out + 1;
    delay(50);
  }
delay(50);
  return(out); // return the next value to try.
}
Digging with a spoon will accomplish more than leaning on a shovel.

trisonic
Posts: 2
Joined: Sun Oct 21, 2012 3:32 pm

Re: Arduino/ATMega based Digital Soldering station

Post by trisonic » Sun Oct 21, 2012 3:35 pm

Hi

Im very interested to your idea.

How is accurate your arduino-station?

regards

Jarod
Site Admin
Posts: 190
Joined: Sat Dec 11, 2010 12:34 am
Contact:

Re: Arduino/ATMega based Digital Soldering station

Post by Jarod » Sat Nov 10, 2012 7:48 pm

I'm not sure, it seems accurate to within 10F or thereabouts, more tweaking could be done to improve the accuracy.

I need to etch a board to put the components on as my breadboard gives me issues with poor conductivity. (Its kinda old)

By the way I apologize for taking forever to approve your post. I'm trying to combat spam and forgetting to check for new legit posts.

trisonic
Posts: 2
Joined: Sun Oct 21, 2012 3:32 pm

Re: Arduino/ATMega based Digital Soldering station

Post by trisonic » Sat Nov 10, 2012 11:58 pm

Jarod wrote:I'm not sure, it seems accurate to within 10F or thereabouts, more tweaking could be done to improve the accuracy.
Have you ever read this project? http://dangerousprototypes.com/forum/vi ... =56&t=2457
may it could help you...

regards

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests