0
Καλημέρα σε όλους τους φίλους.
Εφτιαξα αυτό το προτζεκτάκι με ενα αρντουίνι που μου χάρισαν. Όλα λειτουργούν καλά εκτός απο την ακρίβεια της θερμοκρασίας.
Όταν φτάσει στην καθορισμένη θερμοκρασία,δεν σταματά αλλα συνεχίζει 40+ βαθμούς επάνω και στο κατέβασμα 10+ βαθμούς κάτω.
Φαντάζομαι ότι κάποια διόρθωση θέλει ο κώδικας. Υπάρχει ελπίδα για κάποια βοήθεια, η να το κάνω καφετιέρα.
επισυνάπτω τον κώδικα καθώς και το σχηματικο.SSID-Schematic2.png
/*
Soldering Iron Controller
To change controler mode press UP and DOWN at the same time !!!
24.4.2014. Milos.
*/
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int analogPin = 0; // potentiometer wiper (middle terminal) connected to analog pin A0 // outside leads to ground and +5V
const int btnMode = 6; // the number of the pushbutton pin
const int btnUp = 7; // the number of the pushbutton pin
const int btnDown = 8; // the number of the pushbutton pin
const int pwmHeater = 10; // the number of the PWM pin
const float fAmplification = 183 ; // measured by series of experiment, for ex.: input 21.2mV, output 3.9V
// const float fKTypeSensitivity = 0.000041; // V/degC this is in theory for K type
// But based on experiment on known melting point for the Multicore Alloy C99 (Liquidus on 240 degC), generate voltage is 15mV, so it correspond to TMelting-TAmb = 240-25 = 215 degC
// so sensitivity is calculated as 0.015/215 = 6.9767e-5
//const float fKTypeSensitivity = 0.000075; //old
const float fKTypeSensitivity = 6.9767e-5;
const float fADResolution = 1024.0; // for 10 bit AD converter
const float fADMax = 5.0; // AD convertor max range
//--PID
const float fKp = 10.0; //proportional gian (Value tested with HQ Soldering Iron = 10 )
const float fKi = 1.0; //integral gian (Value tested with HQ Soldering Iron = 1)
const float fKd = 10.0; //derivative gian (Value tested with HQ Soldering Iron = 10)
//--Graphic
const int iHowManyCyclesToRefreshDisplay = 4; //Printing on Display after specified number of sampling cycles
const int iSerialSend = 1; //0-don't send, 1-send to serial
//calculation
float fTemp = 0.0; // Temperature [C]
float fTAmb = 25.0; // Ambient temperature [C]
float fTSet = 0.0; // Set point [C]
float fVoltage; // Voltage from Ain0
float fLSB = 0.0 ; // one LowSiginificantBit [V], (5/1024=0.0048828125)
float fScaleFactor = 0.0; // [degC/LSB] (0.0048828125/340/0.000041=0.35)
float fTime = 0.0; // Time
//---------
float fTimeSampling;
float fTimeLast;
int iCycleCounter=0; //Counter of cycles for printing on display
int iPID_or_OnOff = 0; //0=PWM, 1=OnOff !!!!! HERE THE INITIAL CONTROLER IS SET !!!!
//--PID
float fEk = 0.0; //current error
float fEk_1 = 0.0; //last error
float fPWM; //output PWM
float fIntegralTerm =0.0;
void setup() {
fLSB = fADMax / fADResolution; // one LowSiginificantBit [V], (5/1024=0.0048828125)
fScaleFactor = ( 1.0 / fAmplification ) / fKTypeSensitivity; // [degC/LSB] (0.0048828125/340/0.000041=0.35)
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
pinMode(pwmHeater, OUTPUT);
pinMode(btnMode, INPUT);
pinMode(btnUp, INPUT);
pinMode(btnDown, INPUT);
Serial.begin(9600);
fTimeLast = millis();
}
float fMeasureOversampling() {
// Iako mozda nema potrebe, uradimo vise merenja za jedno odredjivanje temperature (oversampling), teoretski sa 4^n merenja dobijamo dodatnih n bita.
// It takes about 100 microseconds (0.0001 s) to read an analog input so we can make 1024 measurements = 4^5 to hopfully add 5 bits to reac 10 bits in AD converter, it will took about 0.1s to execute
float fSum = 0.0;
for (int i=1; i <= 1024; i++){
fSum = fSum + analogRead(analogPin);
}
return fSum / 1024 ;
}
float fLimit (float fPromenljiva, float fMax, float fMin){ //Saturation function
if (fPromenljiva > fMax) { fPromenljiva = fMax ; }
if (fPromenljiva < fMin) { fPromenljiva = fMin ; }
return fPromenljiva ;
}
float fSimplePID() {
// calculate PID command, first calculate the coeficients
float fSimplePID;
fIntegralTerm = fIntegralTerm + fKi * fEk * fTimeSampling;
fIntegralTerm = fLimit(fIntegralTerm, 255.0, 0.0);
fSimplePID = fKp * fEk + fIntegralTerm + fKd * (fEk - fEk_1); // SimplePID
fSimplePID = fLimit(fSimplePID, 255.0, 0.0);
return fSimplePID;
}
void RefreshDisplay() {
// 1234567890123456
lcd.setCursor(0, 0);
lcd.print("Set: Temp: ");
lcd.setCursor(4, 0);
lcd.print(fTSet,0);
lcd.setCursor(13, 0);
lcd.print(fTemp,0);
lcd.setCursor(0, 1);
lcd.print("Err: ");
lcd.setCursor(4, 1);
lcd.print(fEk,0);
if (iPID_or_OnOff == 0) { //PID is active controler
lcd.setCursor(8, 1);
lcd.print("%PWM=");
lcd.print(fPWM/2.55 ,0);
}
if (iPID_or_OnOff == 1) { //OnOff is active controler
lcd.setCursor(8, 1);
if (fEk < 0) { lcd.print("Heater:-"); }
else { lcd.print("Heater:A"); }
}
}
void SerialSend() {
Serial.print(fTime,3);
Serial.print(", ");
Serial.print(fTSet,1);
Serial.print(", ");
Serial.print(fTemp,1);
Serial.print(", ");
Serial.print(fEk,1);
Serial.print(", ");
Serial.print(fVoltage,3);
Serial.print(", ");
Serial.print(fTimeSampling,4);
Serial.print(", ");
Serial.print(fEk,3);
Serial.print(", ");
Serial.print(fIntegralTerm,3);
Serial.print(", ");
Serial.print(fPWM,2);
Serial.print(", ");
Serial.println(fIntegralTerm,2);
}
void Buttons() {
if ((digitalRead(btnUp) == HIGH) && (digitalRead(btnDown) ==LOW )) {
fTSet = fTSet + 5.0 ;
if (fTSet > 380.0) { fTSet = 380.0 ; } //LIMIT to 380 degC
}
if ((digitalRead(btnUp) == LOW) && (digitalRead(btnDown) ==HIGH )) {
fTSet = fTSet - 5.0 ;
if (fTSet < 0.0) { fTSet = 0.0 ; } //LIMIT to 0
}
if ((digitalRead(btnUp) == HIGH) && (digitalRead(btnDown) ==HIGH )) {
iPID_or_OnOff++ ; //increment
if (iPID_or_OnOff > 1) { iPID_or_OnOff = 0; } //then reset it to 0
}
if (digitalRead(btnMode) == HIGH) {
fTSet = fTSet + 5.0;
if (fTSet < 150.0) {
fTSet = 150.0 ;
}
if ( (fTSet > 150.0) && (fTSet < 280.0 ) ) { fTSet = 280.0 ; }
if ( (fTSet > 280.0) && (fTSet < 320.0 ) ) { fTSet = 320.0 ; }
if ( (fTSet > 320.0) && (fTSet < 350.0 ) ) { fTSet = 350.0 ; }
if (fTSet > 350.0) { fTSet = 0.0 ; }
}
}
void loop() {
fTime = millis() / 1000.0 ;
fTimeSampling = fTime - fTimeLast;
fTimeLast = fTime ;
fVoltage = fMeasureOversampling() * fLSB; // read the input pin and calculate Voltage
fTemp = fTAmb + fScaleFactor * fVoltage; // calculate the Temperature
fEk = fTSet - fTemp; //error for simple PID
if (iPID_or_OnOff == 1 ) { //On-Off regulator // simple ON-OFF control, works well (about +8 and -2 degC about SetPoint)
if (fEk < 0) { analogWrite(pwmHeater, 0); }
else { analogWrite(pwmHeater, 255); }
}
if (iPID_or_OnOff == 0 ) { //PID regulator
fPWM = fSimplePID(); //calculate PID command
fEk_1 = fEk; //store the last error
analogWrite(pwmHeater, fPWM); //execute the command
}
Buttons(); //read the buttons
if (iSerialSend == 1) { SerialSend() ; } //print on UART, serial port
iCycleCounter++; //increment cycle counter
if (iCycleCounter >= iHowManyCyclesToRefreshDisplay ) { //print od dislplay
RefreshDisplay() ;
iCycleCounter = 0; //reset counter
}
// delay(100); //omitted - goes on approx 0.144 seconds per cycle
}