Tach,
wollt mir ne geregelte Heizplatte zusammenbasteln, hat auch so weit alles gut funktioniert. Allerdings hab ich nu ein Problem bei der Software.
kurze Beschreibung der Hardware:
Heizplatte-----------SolidStateRelais--------------230V
| ^
v |
MAX6675----------------Arduino
Arduino schaltet mit Hilfe vom MAX6675 ermittelten Werte das SolidStateRelais, so war es zumindestens gedacht XD
hab beim testen aber nu gemerkt dass er die Temperatur nur ein einziges mal ausliest und zwar ganz am anfang
wenn ich nu n delay einbau klappts einwandfrei, wollte wegen der Regelung komplett auf delay verzichten
/*
Programm für Geregelte Heizplatte aus Teilen vom alten Bügeleisen,
+ LCD-Display
+ Temperatur Messung mit Thermoelement und MAX6675
+ Rotary-Encoder für Temperatur-Einstellung
*/
// librarys
#include <LiquidCrystal.h>
#include <max6675.h>
#include <PID_v1.h>
// Pins
#define RWPin 10
#define thermoDO 4
#define thermoCS 3
#define thermoCLK 12
#define encoder0PinA 2
#define encoder0PinB 13
#define SCHALTAUSGANG 10
// Variablen
volatile unsigned int encoder0Pos = 20;
double IST = 0;
double SOLL = 0;
// ====================
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters Sachen für REGELUNG
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
int WindowSize = 1000;
unsigned long windowStartTime;
// ====================
// LCD init. lcd(RS, EN, D4, D5, D6, D7) R/W auf GND
LiquidCrystal lcd(9, 11, 8, 7, 6, 5);
// MAX6675 init.
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
// make a cute degree symbol
uint8_t degree[8] = {140,146,146,140,128,128,128,128};
// //////////////////////////////////////// SETUP ////////////////////////////////
void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
pinMode (SCHALTAUSGANG,OUTPUT);
Serial.begin (9600);
attachInterrupt(0, doEncoder, CHANGE);
// ====================
windowStartTime = millis();
//initialize the variables we're linked to
Setpoint = 100;
//tell the PID to range between 0 and the full window size Sachen für REGELUNG
myPID.SetOutputLimits(0, WindowSize);
//turn the PID on
myPID.SetMode(AUTOMATIC);
// ====================
pinMode(RWPin, OUTPUT);
digitalWrite(RWPin, LOW);
// set up the LCD's number of columns and rows:
lcd.begin(16,2);
lcd.createChar(0, degree);
}
// ////////////////////////////////////////// LOOP ////////////////////////////////
void loop() {
// Temperatur einlesen
Input = thermocouple.readCelsius();
Setpoint = encoder0Pos;
myPID.Compute(); // <- Regelungsberechnung
Serial.print(Setpoint);
Serial.print(" / ");
Serial.print(Input);
Serial.print(" / ");
Serial.print(Output);
unsigned long now = millis();
if(now - windowStartTime>WindowSize)
{ //time to shift the Relay Window REGELUNG
windowStartTime += WindowSize;
}
if(Output > now - windowStartTime) {
digitalWrite(SCHALTAUSGANG,HIGH);
Serial.println(" high");
}
else {
digitalWrite(SCHALTAUSGANG,LOW);
Serial.println(" low");
}
// Ausgabe auf LCD
lcd.setCursor(1, 0);
lcd.print("IST: ");
lcd.print(Input);
lcd.print(0, BYTE);
lcd.print("C ");
lcd.setCursor(0, 1);
lcd.print("SOLL: ");
lcd.print(encoder0Pos);
lcd.print(0, BYTE);
lcd.print("C ");
lcd.print(" ");
if (SCHALTAUSGANG == HIGH){
lcd.print("*");
}
//lcd.clear();
delay(500);
}
void doEncoder() {
if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
encoder0Pos++;
} else {
encoder0Pos--;
}
if (encoder0Pos == 19) {encoder0Pos++;} // Begrenzung auf > 0
if (encoder0Pos == 300) {encoder0Pos--;} // Begrenzung auf < 100
}
weiss da zufällig jmd warum dies so ist?
edit:
hab noch mal n bissl rumgetestet und gluab das hängt irgendwie mit der Kommunikation mitn LCD zusammen.
hab das LCD-ausgabe in eine Funktion getan und beim Aufruf jeweils vor und hinter ein delay von 100 getan -> funzt
schon auf jeden fall ne verbesserung zum 500er delay, aber immer noch nicht so wie gewünscht
geänderter Coder:
/*
Programm für Geregelte Heizplatte aus Teilen vom alten Bügeleisen,
+ LCD-Display
+ Temperatur Messung mit Thermoelement und MAX6675
+ Rotary-Encoder für Temperatur-Einstellung
*/
// librarys
#include <LiquidCrystal.h>
#include <max6675.h>
#include <PID_v1.h>
// Pins
#define RWPin 10
#define thermoDO 4
#define thermoCS 3
#define thermoCLK 12
#define encoder0PinA 2
#define encoder0PinB 13
#define SCHALTAUSGANG 10
// Variablen
volatile unsigned int encoder0Pos = 20;
int IST = 0;
int SOLL = 0;
// ====================
//Regelungs-Variablen
double Setpoint, Input, Output;
//Regel-Parameter und Variablen aufzeigen Sachen für REGELUNG
// Kp,Ki,Kd
PID myPID(&Input, &Output, &Setpoint,1,1,4, DIRECT); //REVERSE DIRECT
int WindowSize = 1000;
unsigned long windowStartTime;
// ====================
// LCD (RS, EN, D4, D5, D6, D7) R/W auf GND
LiquidCrystal lcd(9, 11, 8, 7, 6, 5);
// MAX6675 init.
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
// Grad-Symbol für Display
uint8_t degree[8] = {140,146,146,140,128,128,128,128};
// //////////////////////////////////////// SETUP ////////////////////////////////
void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
pinMode (SCHALTAUSGANG,OUTPUT);
Serial.begin (9600);
attachInterrupt(0, doEncoder, CHANGE);
// ====================
windowStartTime = millis();
//initialisierung der Regelungs-Variablen
Setpoint = 100;
//tell the PID to range between 0 and the full window size Sachen für REGELUNG
myPID.SetOutputLimits(60, WindowSize);
//turn the PID on
myPID.SetMode(AUTOMATIC);
// ====================
pinMode(RWPin, OUTPUT);
digitalWrite(RWPin, LOW);
//LCD Initialisieren
lcd.begin(16,2);
lcd.createChar(0, degree);
}
// ////////////////////////////////////////// LOOP ////////////////////////////////
void loop() {
// Temperatur einlesen
Input = thermocouple.readCelsius();
Setpoint = encoder0Pos;
myPID.Compute(); // <- Regelungsberechnung
Serial.print(Setpoint);
Serial.print(" / ");
Serial.print(Input);
Serial.print(" / ");
Serial.print(Output);
unsigned long now = millis();
if(now - windowStartTime>WindowSize)
{ //time to shift the Relay Window REGELUNG
windowStartTime += WindowSize;
}
if(Output > now - windowStartTime) {
digitalWrite(SCHALTAUSGANG,HIGH);
Serial.println(" high");
}
else {
digitalWrite(SCHALTAUSGANG,LOW);
Serial.println(" low");
}
delay(100);
doDisplay(Input,encoder0Pos);
delay(100);
}
void doEncoder() {
if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
encoder0Pos++;
} else {
encoder0Pos--;
}
if (encoder0Pos == 19) {encoder0Pos++;} // Begrenzung auf > 0
if (encoder0Pos == 200) {encoder0Pos--;} // Begrenzung auf < 100
}
void doDisplay(int IST,int SOLL) {
lcd.setCursor(1, 0);
lcd.print("IST: ");
lcd.print(IST);
lcd.print(0, BYTE);
lcd.print("C ");
lcd.setCursor(0, 1);
lcd.print("SOLL: ");
lcd.print(SOLL);
lcd.print(0, BYTE);
lcd.print("C ");
lcd.print(" ");
if (SCHALTAUSGANG == HIGH){
lcd.print("*");
}
//lcd.clear();
}
greetz
akrlfix