Pages: 1 ... 3 4 [5]   Go Down
Author Topic: SSR relais mit pwm steuern  (Read 4860 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Sr. Member
****
Karma: 2
Posts: 261
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also soll das eine Leistungsregelung werden, bei der Du die einzuhaltende Leistung in Watt vorgibst?

Du hast also am Ende irgendwelche Einstellelemente (von denen Du bisher noch gar nichts geschrieben hast) und gibst damit eine einzuhaltende Leistung manuell vor?

Genau es soll eine Wattzahl gehalten werden.  zB. für 1h  1000W.

Quote
Sagen wir mal Du hast einen "Drehgeber", den drehst Du rechts und ein Sollwert für die Leistung steigt. Und Du drehst den Drehgeber links und der Sollwert sinkt.

der sollwert ist entweder die wattzahl die manuell gegeben wird oder der sollwert hängt von einem anderen sensor ab, denn gebe ich einen ungefähren leistungswert, also heizen(50); und der sollwert hängt den von einer anderen sensormesseung ab die durch die heizung beeinflusst wird.

Quote
Ein LCD-Display zeigt die eingestellte "Soll-Heizleistung" und die aktuell gemessene "Ist-Heizleistung".

Ich würde gerne wenn die wattzahl manuell steueren( also wenn gerade kein algorythmus läuft) mit einem poti der die der in % auf dem LCD angezeigt wird.
Und der gemessene ist-wert soll angezeigt werden.
Deswegen könnte ich ja eine variable mit dem poti skalieren und das dann bei heizen() einsetzen habe ich mir gedacht.
So ungefähr habe ich mir das gedacht:
Code:
int fade = analogRead (poti2);
    fade = map(fade, 0, 1023, 0, 100);
    heizen(fade);
    lcd.print(fade);


Logged

Gruß

strohhirn

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2440
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Genau es soll eine Wattzahl gehalten werden.  zB. für 1h  1000W.

Das ist ja schön, dass Du nach gefühlt einem halben Jahr endlich damit rüber kommst, was tatsächlich gemacht werden soll!

Nachdem Du hier monatelang nur falsche Fährten gelegt hast, so dass wegen des Begriffs "Heizung" hier die meisten von einer Temperaturregelung ausgegangen sind.

Oder aufgrund des Schwerpunkt "Leistungsmessung" vermuteten, dass einer bestimmten manuell vorgegebenen Einstellung (PWM-Wert vom Kemo bzw. Poti-Stellung) nur die momentane Leistung gemessen und angezeigt werden soll.

Wenn die Katze auch nun noch nicht vollends aus dem Sack ist, so kann man sie doch schon im Sack erkennen.

der sollwert ist entweder die wattzahl die manuell gegeben wird oder der sollwert hängt von einem anderen sensor ab

OK, also hast Du irgendwo eine Manuell-Automatik Umschaltung (z.B. einen Kippschalter mit den zwei Schaltstellungen "Manuell" und "Automatik") und je nach Schaltstellung gibst Du die Soll-Leistung manuell vor, oder sie wird von einem Sensor vorgegeben. In beiden Fällen bekommt also der Arduino einen "Sollwert in Watt" vorgegeben und er soll die Heizung so regeln - trotz gravierender Spannungsschwankungen im 230V-Netz - dass der "Istwert in Watt" möglichst gut mit der Sollwert-Vorgabe übereinstimmt.

denn gebe ich einen ungefähren leistungswert, also heizen(50); und der sollwert hängt den von einer anderen sensormesseung ab die durch die heizung beeinflusst wird.

Nein, das funktioniert nicht, Du kannst nicht beides als Sollwert vorgeben, wenn Du tatsächlich eine dynamische Regelung möchtest:
- Sollwert für die Heizleistung in Watt
- Sollwert für die Reglerstellung in Prozent der maximalen Heizleistung
Dies entspricht einer "Regelung nach Kennlinie", also dass Du GENAU weißt, welche Reglerstellung welcher Heizleistung entspricht. Dann fährst Du die Regelung nach Kennlinie. Genau das möchtest Du aber gerade wegen der stark schwankenden Netzspannung und der daraus resultierenden schwankenden Heizleistung bei gleichbleibender Reglerstellung NICHT. Du möchtest eine dynamische Leistungsregelung nach der tatsächlich gemessenen Leistung. (Falls ich Dich nun richtig verstanden habe, was Du machen möchtest.)

Wenn Du eine Regelung möchtest, dann gibst Du die Zielgröße vor (Heizleistung in Watt) und die Stellgröße (Reglerstellung in Prozent) wird von der Regelung festgelegt. Und zwar in einem Feedback-Kreislauf aus der Messung der Regelabweichung (Differenz zwischen vorgegebener Soll-Heizleistung und gemessener Ist-Heizleistung) wird ständig eine neue Reglerstellung ermittelt und eingestellt.

Quote
Ein LCD-Display zeigt die eingestellte "Soll-Heizleistung" und die aktuell gemessene "Ist-Heizleistung".
Ich würde gerne wenn die wattzahl manuell steueren( also wenn gerade kein algorythmus läuft) mit einem poti der die der in % auf dem LCD angezeigt wird.
Und der gemessene ist-wert soll angezeigt werden.

Du kannst die Wattzahl nicht direkt steuern, wenn die Wattzahl tatsächlich von der Netzspannung abhängt, die gerade anliegt. Du kannst nur einen Stellwert vorgeben. Und je nach Netzspannung ist die tatsächliche Wattzahl dann höher (bei höherer Netzspannung) oder tiefer (bei niedrigerer Netzspannung) bei gleichbleibender Reglerstellung. Wenn Du tatsächlich nicht die Reglerstellung (0 bis 100% Reglerstellung) vorgeben möchtest, sondern eine "Wattzahl", dann muss immer eine dynamische Regelung als Algorithmus laufen. Ohne die dynamische Regelung der Reglerstellung mit Berücksichtung des aktuellen Messwertes der tatsächlichen Heizleistung läßt sich bei schwankender Eingangsspannung die Heizleistung nicht konstant halten.

Deswegen könnte ich ja eine variable mit dem poti skalieren und das dann bei heizen() einsetzen habe ich mir gedacht.
So ungefähr habe ich mir das gedacht:
Code:
int fade = analogRead (poti2);
    fade = map(fade, 0, 1023, 0, 100);
    heizen(fade);
    lcd.print(fade);

Nein, das ist keine "Heizleistungs-Regelung", sondern das ist eine "Heizleistungseinstellung nach Kennlinie". Eine 50% Poti-Stellung führt zu 50% Heizleistung, und diese Heizleistung beträgt bei 237 V dann 1750 Watt. Aber wenn die Netzspannung auf 210 Volt fällt, beträgt die Heizleistung bei derselben Potistellung 1750*(210/237)2 = 1374 Watt. Das ist KEINE Regelung mit so einem Code!

Am besten also nochmal genau nachdenken was Du möchtest:

a) Du gibst eine Einstellung in Prozent zum Heizen vor (manuell oder per Sensor). Die tatsächliche Heizleistung richtet sich nach Deiner Vorgabe UND der schwankenden Netzspannung, sie schwankt mit der Netzspannung und wird lediglich angezeigt.

b) Du gibst als Einstellung eine Wattzahl vor (manuell oder per Sensor). Die Heizleistung wird dynamisch so auf mehr oder weniger heizen geregelt, dass trotz der schwankenden Netzspannung die Wattzahl möglichst konstant bleibt.

Nach Deinem oben klar geäußerten Statement "es soll eine Wattzahl gehalten werden.  zB. für 1h  1000W" gehe ich eigentlich von b) aus, aber Dein Code sagt eher, dass Du a) für den Arduino programmieren möchtest.

Du kannst es beim Umschalten von Automatik- auf manuellen Betrieb auch umschalten:
- Manueller Betrieb ==> Vorgabe der Heizleistung in Prozent der maximalen Heizleistung
- Automatischer Betrieb ==> Vorgabe der Heizleistung in Watt mit automatischer Regelung

Ein Arduino-Programm macht immer das, was Du programmierst.

Und wenn Du etwas programmieren möchtest, ist es extrem hilfreich zu wissen, was eigentlich programmiert werden soll.

Und dazu solltest Du am Anfang erstmal in einfachen und klaren Worten die Programmlogik und den Programmablauf beschreiben können. In sich schlüssig und ohne logische Fehler. Wenn die Beschreibung des Programmablaufs dann schon unklar oder unlogisch ist, kann das Programm nicht besser werden als die Programmbeschreibung.
Logged

Forum Moderator
BZ (I)
Offline Offline
Brattain Member
*****
Karma: 234
Posts: 20193
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Die Nebel haben sich etwas gelichtet aber für mich ist immernoch nicht verständlich, wieso die Leistung eingestellt werden muß, und nicht ein Ausgangsparameter der gemessen wird. Die Regelung kann unabhängig davon nicht digital (Ein/Aus) sondern proportional oder mittels PID-Regler die Leistungsregelung ansteuern.
Wenn Du Auto fährst dann interessiert Dich auch nicht wieviel Leistung der Motor gerade an die Räder abgibt sondern wie schnell Dein Auto fährt.

Grüße Uwe
Logged

D-49565 Bramsche
Offline Offline
Sr. Member
****
Karma: 6
Posts: 477
Geht nich ? Gipp's nich !
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ein Karma für jurs für scheinbar unendliche Geduld und gute Fragen.

Ich kapier das ehrlich immer noch nicht, was dass eigentlich werden soll ?!
Grübele schon seit geraumer Zeit, welche "Anwendung" es erforderlich macht, die zugeführte Leistung in Abhängigkeit der (Netz-) Spannung konstant zu halten.

Es kann sich eigentlich nur um so etwas wie eine Messapparatur handeln - aber was misst die / soll die messen ?
Wenn selbige irgendwas mit Temperatur zu tun haben sollte, dann wäre doch die (konstante) Temp die Referenz und nicht die zugeführte Leistung.
Irgendwas mit Kraft oder Drehzahl kann es ja auch nicht sein, weil das dann ja die einzuhaltenden Paramter wären, welche nicht nur von der zugeführten Leistung abhängen.

Oder hat strohhirn einen ausserirdischen Auftrag bekommen, den PoWeR-AbSoRbEr des Raumschiffs induktiv mit exakt 3kWh zu versorgen, weil die Burschen mit der einfachen irdischen Technik nicht klar kommen ? (kleiner Scherz ...  smiley-mr-green)

Großes Rätselraten ! Das wird hier noch mal was für eine abendfüllende Sendung mit reaktiviertem Robert Lembke -> welches Schweinderl isses denn nun ?  smiley-cool

Herzallerliebstes strohhirn: Erklär uns doch bitte einfach mal so halbwegs oder auch im Detail, was dass da bei dir überhaupt werden soll.
Vielleicht gehst du von völlig falschen Vorraussetzungen / Annahmen aus und deine bisherigen Gedankengänge sind eigentlich alle für'n Eimer ?

.... mir fällt absolut nichts ein, was ausschliesslich nur eine konstante Leistung benötigt und sonst KEINE weiteren Parameter benötigt, welche die Leistungszuführung auch nur ansatzweise beeinflussen .

Lass es uns endlich wissen, welche Eingebung du für was hast !

Logged

To young to die - never to old for rock'n roll

Offline Offline
Sr. Member
****
Karma: 2
Posts: 261
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mir ist die aufgabe gegeben, das die Heizung eine bestimmte Leistung halten soll nicht Temperatur, ich kann auch nicht sagen wofür.
Das hat alles seine Richtigkeit und ist so gewollt, zerbrecht euch nicht den Kopf darum.

Quote
OK, also hast Du irgendwo eine Manuell-Automatik Umschaltung (z.B. einen Kippschalter mit den zwei Schaltstellungen "Manuell" und "Automatik") und je nach Schaltstellung gibst Du die Soll-Leistung manuell vor, oder sie wird von einem Sensor vorgegeben. In beiden Fällen bekommt also der Arduino einen "Sollwert in Watt" vorgegeben und er soll die Heizung so regeln - trotz gravierender Spannungsschwankungen im 230V-Netz - dass der "Istwert in Watt" möglichst gut mit der Sollwert-Vorgabe übereinstimmt.

Genau im gesamten sketch habe ich nacher 3 programme(algorythmen die einmal ablaufen) die ich per knopfdruck an und ausschalten kann. Dabei wird automatisch die Leistung geregelt zB für 1h 1000W, dabei möchte ich schnellstmöglich den sollwert erreichen, da es mit dem befehl ++ zu lange dauert, und danach soll anhand von den messungen vom ACS712, die durch Netzschwankungen sich verändern können, der Istwert möglichst nah an den Sollwert korigiert werden. Der sollwert kann aber auch eine messung von einem anderen sensor sein, sodass zum beispiel bei einem Drucksensor ein bestimmter druck gehalten wird.

Wenn keins der programme läuft möchte ich die heizleistung trozdem mit einem poti regulieren können. Und mit dem ACS712 den Istwert messen können.
Also soll eigentlich immer gemessen werden. Und bei Netzschwankungen kann ich selbst anhand der messung, am poti die leistung korrigieren.

Quote
Wenn Du eine Regelung möchtest, dann gibst Du die Zielgröße vor (Heizleistung in Watt) und die Stellgröße (Reglerstellung in Prozent) wird von der Regelung festgelegt. Und zwar in einem Feedback-Kreislauf aus der Messung der Regelabweichung (Differenz zwischen vorgegebener Soll-Heizleistung und gemessener Ist-Heizleistung) wird ständig eine neue Reglerstellung ermittelt und eingestellt.

genau sowas will ich, wenn eins der automatischen programme läuft.

bei der manuellen steuerung ist es denk ich mal einfacher wenn ich per hand den gewollten wert korrigiere.
Aber wenn es auch hier möglich ist mit dem poti einen sollwert vorzugeben, das zb solange der poti an einer bestimmten stelle steht auch die leistung entsprechend dem sollwert gehalten wird, dann ist mir natürlich diese variante lieber.
Aber das ist schwieriger zu programmieren zumindest weiß ich nicht wie das gehen soll.

Und ich danke dir jurs natürlich das du so geduldig mir hilfst, und bitte um Verzeihung falls ich mich dumm anstelle.
Logged

Gruß

strohhirn

Offline Offline
Sr. Member
****
Karma: 2
Posts: 261
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wenn es hilft hier ist ein programm wie ich es mit dem kemo umsetzen wollte, aber da ist ja das problem mit dem falschen messungen:
Code:
void programm3() {
 if (sensors.getTempC(Sensor[0]) <= 25.0 && status ==30){  
  digitalWrite(k[0], HIGH);
  
  status = 31;
 }
 else if (sensors.getTempC(Sensor[0]) >= 70 && status == 31) {
   digitalWrite(k[0], LOW);
   status = 32;
   nextMillis = millis() + 5000L;
 }
 else if( (status == 32 && millis() > nextMillis) || (sensors.getTempC(Sensor[0]) >= 25.0 && status ==30) ) {
   digitalWrite(k[1], HIGH);
   digitalWrite(k[2], HIGH);
   digitalWrite(k[3], HIGH);
  
   status = 33;
 }
 else if (mb >= 60 && status == 33) {
   Watt = 950;
   int A = 0;
  if(A==0){  // damit man in der nähe des sollwertes ist, da es mit ++ zu lange dauert
   fade = 100;
   analogWrite(ledPin, fade);
   A++;
  }
    if(W > Watt){ //hier ein der versuch den sollwert zu halten oder an ihn ranzukommen
      fade--;
      analogWrite(ledPin, fade);
    }
    if(W < Watt){ //W ist der gemessene istwert
      fade++;
      analogWrite(ledPin, fade);
    }
  status = 34;
 }
else if ((900 <=W < 1000) && status == 34 ) {
   mbar = 50;
   if (mb > mbar){ // mb ist der gemessene istwert
     fade--;
     analogWrite(ledPin, fade);
   }
   if (mb < mbar){
     fade++;
     analogWrite(ledPin, fade);  
   }
   status = 35;
 }
 else if (sensors.getTempC(Sensor[0]) >= 93 && status == 35) {
  alarmbuzzer();
   status = 36;
 }
 else if (sensors.getTempC(Sensor[0]) >= 97 && status == 36) {
   digitalWrite(k[1], LOW);
   status = 37;
   nextMillis = millis() + 300000L;
 }
 else if( status == 37 && millis() > nextMillis) {
  digitalWrite(k[2], LOW);
    digitalWrite(k[3], LOW);
    analogWrite(ledPin, 0);
    nextMillis = 0;
    fade = 0;
    status = 10; //aus
    lcd.setCursor(10, 3);
    lcd.print("Pr: AUS");
  
 }
}
« Last Edit: September 28, 2013, 12:01:48 pm by strohhirn » Logged

Gruß

strohhirn

D-49565 Bramsche
Offline Offline
Sr. Member
****
Karma: 6
Posts: 477
Geht nich ? Gipp's nich !
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mir ist die aufgabe gegeben, das die Heizung eine bestimmte Leistung halten soll nicht Temperatur, ich kann auch nicht sagen wofür.
Das hat alles seine Richtigkeit und ist so gewollt, zerbrecht euch nicht den Kopf darum.
AHA ! .... wir sollen uns nicht den Kopf machen - machen wir aber seit Monaten betreff Sinn und Zweck deines immer noch unbekannten und anscheinend so was von dermaßen geheimen Vorhabens !

Was bitte (mit Verlaub: Verdammt noch mal) ist denn so schrecklich geheim oder gar bahnbrechend physikalisch neu, dass du uns nicht sagen kannst (willst !?), an welcher Art Perpetuum Mobile du da werkelst ? ? ?
Stehen dir NSA, CIA, NASA, NYPD, die vielen CSI's, der heimisch merkwürdige Bundes-Innnen-Aussen-Schutzdienst für irgendwas ohne Ahnung & Plan oder gar radikale Islamisten auf den Hacken ? ? ?
Neue Weltformel durch Konstantstromleistung ?
.... du meine Güte, was muss das doch so was von dermaßen schrecklich geheim sein, was dir da aufgebenen wurde.

Das hat alles seine Richtigkeit und ist so gewollt.....
Bist du dir da wirklich ganz sicher ?

Erst mal muss man den Sinn und Zweck der eigentlichen "Tat" verinnerlichen.
Danach kann man mit der Erkenntnis daraus sich in endlose Sketche ergiessen ....
« Last Edit: September 28, 2013, 12:33:36 pm by TERWI » Logged

To young to die - never to old for rock'n roll

Offline Offline
God Member
*****
Karma: 9
Posts: 721
42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich roll mich gerade auf dem Boden vor Lachen! Ich hab mir jetzt den ganzen Thread durchgelesen und bewundere besonders Jurs budhistische Ruhe...

Ich glaube, strohhirn sollte es lieber sein lassen. Diese Geheimniskrämerei gepaart mit absoluter Beratungsresistenz und fundamentalem Unverständnis von Physik und Elektrotechnik sind keine passende Ausgangssituation für ein Projekt. Was auch immer es werden soll...
Logged


D-49565 Bramsche
Offline Offline
Sr. Member
****
Karma: 6
Posts: 477
Geht nich ? Gipp's nich !
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Es muss was wichtiges sein !
Irgendwann werden wir es wissen, wie die Physik überlistet wird.
Logged

To young to die - never to old for rock'n roll

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2440
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Anbei mal ein Sketch, bei dem die ACS712 Leistungsmessung mit der Intervall-Heizfunktion über eine Proportional-Regelung verheiratet wurden.

Am Ende der Loop ist sogar auch bereits eine Abschaltfunktion vorgesehen und auskommentiert für eine programmgesteuerte Abschaltung der Regelung. Falls man in Abhängigkeit von Kippschalter- und Potistellungen auch eine automatische Abschaltung der Heizfunktion nach bestimmter Zeit vorsehen möchte, könnte man an der Stelle die Vorgaben für die Abschaltung auswerten und die Abschaltfunktion aufrufen.

Code:
// Code ist UNGETESTET und wahrscheinlich FEHLERHAFT! Keine Garantien!
#define HEIZLEISTUNG 3500.0 // in Watt, gemessen mit Energiemessgerät
#define NETZSPANNUNG 237.0  // in Volt, gemessen mit Energiemessgerät
#define HEIZLEISTUNG_NENNWERT 3000.0 // in Watt, Nennwert laut Typenschild
// Wg. P=U*I und U=R*I ==> I=U/R
// ist P=U*U/R und R=U*U/P
#define HEIZWIDERSTAND NETZSPANNUNG*NETZSPANNUNG/HEIZLEISTUNG

#define ACS712PIN A3           // Anschlusspin des ACS712
#define BETRIEBSSPANNUNG 5.14  // VSS des Arduino-Boards in Volt
#define SENSITIVITY 100        // Empfindlichkeit des ACS712 in mV/A
#define MEDIAN 512             // ADC-Wert für Nullpunkt des ACS712

// Pin für Potentiometer zum Einstellen des Heizleistungs-Sollwerts
#define POTI2 A4

// Pin für SSR-Relais zum Schalten der Heizung
#define HEIZUNGPIN 13

volatile long long sumMesswerteRMS;
volatile unsigned long countMesswerte;

int LeistungInWatt(boolean showDebugMessage)
// Wenn Parameter showDebugMessage==true, Ausgabe von Debug-Meldungen
// Rückgabewert: gemessene Leistung in Watt
{
  char buffer[45];
  float messwert;
  long spannungMV,stromMA, leistungW;
  noInterrupts(); // Interrupts sperren zur Auswertung
  messwert= sqrt((float)sumMesswerteRMS/countMesswerte); // Effektivwert =  quadratischer Mittelwert
  sumMesswerteRMS=0; // Rücksetzen der Variablen für nächste Messung
  countMesswerte=0;  // Rücksetzen der Variablen für nächste Messung
  interrupts(); // Interrupts wieder freigeben
  spannungMV= messwert / 1023.0 * BETRIEBSSPANNUNG  * 1000L; // Spannung in Millivolt am ACS712
  stromMA=spannungMV*1000/SENSITIVITY;  // Entsprechender Strom am ACS712
  leistungW= HEIZWIDERSTAND * (stromMA/1000.0) * (stromMA/1000.0);
  if (showDebugMessage) // Ausgeben einer Zeile als Debug-Meldung über Serial
  {
    snprintf(buffer,sizeof(buffer),"%d - %ld mV - %ld mA - %ld W",(int)messwert,spannungMV,stromMA, leistungW);
    Serial.println(buffer);
  }  
  return leistungW;
}


void initTimer2()
{ // Timer-Interrupt für eine Rate von 980 Interrupts pro Sekunde initialisieren
  TCCR2B = (1<<WGM22) | (1<<CS22);
  OCR2A = 254;
  // enable Timer 2 interrupts
  TIMSK2 = (1<<OCIE2A);
}

ISR(TIMER2_COMPA_vect)
{  // Bei Timer-Interrupt einen Messwert am ACS712 erfassen
  long newValue=analogRead(ACS712PIN)-MEDIAN;
  sumMesswerteRMS += newValue*newValue;
  countMesswerte++;
}


void setup() {
  Serial.begin(9600);
  pinMode(POTI2,INPUT); // Poti Pin als Input
  pinMode(HEIZUNGPIN,OUTPUT); // Heizungspin zum Schalten SSR Relais
  Serial.println();
  Serial.println("Getaktete Heizleistungsregelung by 'jurs' for German Arduino Forum");
  Serial.println();
  initTimer2();
}

boolean heizen(byte prozent, byte pin, unsigned long letztesIntervallStart)
// Parameter Prozent der Heizleistung 0 bis 100 (für 0% bis 100% Heizleistung)
// wobei <10 die Heizung komplett aus- und >90 komplett eingeschaltet ist
{
  unsigned long jetztMillis=millis();
  if (prozent<10) // unter 10% Heizanforderung Heizung abschalten
  {
    digitalWrite(HEIZUNGPIN, LOW);
    return LOW;
  }
  else if (prozent>90) // über 90% Heizanforderung Heizung voll einschalten
  {
    digitalWrite(HEIZUNGPIN, HIGH);
    return HIGH;
  }
  else if (jetztMillis-letztesIntervallStart<100*prozent) // zwischen 10% und 90% des Intervalls heizen
  {
    digitalWrite(HEIZUNGPIN, HIGH);
    return HIGH;
  }  
  else  // Rest des Intervalls Heizung aus
  {
    digitalWrite(HEIZUNGPIN, LOW);
    return LOW;
  }  
}


int sollwertEinstellung()
// Rückgabewert: Sollwert in Watt
// wird in Abhängigkeit einer Potentiometerstellung ermittelt
// verteilt auf Schritte, die dem Heizleistungsnennwert/100 entsprechen
{
  int value=analogRead(POTI2);
  return HEIZLEISTUNG_NENNWERT/100*lround(value/10.23);
}


boolean newIntervallStarted=false;

unsigned long tenSecondIntervallStartMillis()
// Rückgabewert: Stand des millis() Zählers beim Start des
// laufenden 10-Sekunden-Intervalls
{
  static unsigned long oldIntervallstart=0;
  unsigned long now=millis();
  if (now-oldIntervallstart>=10000)
  {
    oldIntervallstart=now;
    newIntervallStarted=true; // Flag setzen, dass ein neues 10s-Intervall angefangen hat
  }
  return oldIntervallstart;  
}

void abschaltenNach(long sekunden)
// Abschaltfunktion nach Zeit mit Eintritt in Endlosschleife
{
  if (millis()>sekunden*1000) // nach mehr als sekunden * 1000 Millisekunden Programmlaufzeit
  {
    heizen(0,HEIZUNGPIN,millis()); // Heizung abschalten
    Serial.println("Heizung aus - Warten auf Reset.");
    while (1); // Und eine Endlosschleife bis zum nächsten Reset ausführen
  }
}


int HeizleistungIST=0;
int HeizleistungSOLL=0;
int reglerProzent=0;

void loop()
{
  // Zuerst die Einstellung des Sollwerts aktualisieren,
  // und bei Änderungen den neuen Sollwert anzeigen
  static int lastHeizungSOLL=0;
  HeizleistungSOLL=sollwertEinstellung();
  if (HeizleistungSOLL!=lastHeizungSOLL)
  { // Änderung des Sollwerts anzeigen
    Serial.print("Neuer Sollwert: ");
    Serial.print(HeizleistungSOLL);
    Serial.println(" Watt");
    lastHeizungSOLL=HeizleistungSOLL;
  }
  
  // Prüfen ob und ggf. wann ein neues 10-Sekunden-Intervall begonnen hat
  unsigned long intervallStart=tenSecondIntervallStartMillis();
  if (newIntervallStarted) // alle 10 Sekunden
  {
    newIntervallStarted=false; // Flag zurücksetzen
    HeizleistungIST=LeistungInWatt(true); // die neu ermittelte Ist-Heizleistung
    Serial.print("Aktuelle Leistung: ");
    Serial.print(HeizleistungIST);
    Serial.println(" Watt");
    // Jetzt die neue Reglerstellung ermitteln
    int heizLeistungDifferenz=HeizleistungSOLL-HeizleistungIST;
    // Und am Regler 82% der vorhandenen Differenz pro Intervall ausregeln
    int reglerDifferenz=lround(heizLeistungDifferenz*100.0/HEIZLEISTUNG_NENNWERT*0.82);
    reglerProzent += reglerDifferenz;
    // Prüfen, ob Wert zwischen 0% und 100% liegt und ggf. begrenzen
    if (reglerProzent>100) reglerProzent=100;
    else if (reglerProzent<0) reglerProzent=0;
    if (reglerDifferenz==0)
      Serial.print("Reglerstellung bleibt gleich: ");
    else  
      Serial.print("Reglerstellung gesetzt auf: ");
    Serial.print(reglerProzent);
    Serial.println(" %");  
  }
  
  // Heizfunktion mit der aktuellen Reglerstellung aufrufen
  heizen(reglerProzent,HEIZUNGPIN,intervallStart);
//  abschaltenNach(3600); // Bei Bedarf entkommentieren: Abschalten nach 3600 Sekunden
}

Da ich nichts von der Hardware hier habe (keine Heizung mit SSR-Relais, kein ACS712) kann ich von dem Code praktisch nichts im Zusammenspiel testen.

Das Finden und Beseitigen der Fehler wäre Dir überlassen - viel Spass dabei!

Ich kann nur garantieren, dass der Code so kompilierbar ist und dass ich mir Mühe gegeben habe, Deine etwas kryptischen Vorgaben in Code umzusetzen. Eine Funktionsgarantie kann ich dabei nicht übernehmen. Also pass auf, was Du machst!

P.S.: Und wenn Du was aus dem Seriellen Monitor im Forum posten möchtest, brauchst Du keine Fotos machen. So geht es unter Windows: Automatisches Scrollen im seriellen Monitor abschalten, mit der Maus den gewünschten Textbereich markieren, dann die Tastenkombination Strg-C drücken. Dann ist der Text in der Windows-Zwischenablage und kann je nach Programm aus dem Menü über "Bearbeiten - Einfügen" oder in Texteingabefeldern (Forum im Web-Browser!) mit der Tastenkombination "Strg-V" oder mit der Maus "rechte Maustaste - Einfügen" an Ort und Stelle wieder als Text eingefügt werden.
« Last Edit: September 29, 2013, 11:41:01 am by jurs » Logged

Offline Offline
Sr. Member
****
Karma: 2
Posts: 261
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Auf jeden Fall ein großes DANKE für deine mühe. Und vielen dank das du das so gründlich kommentiert hast.
Ich habe natürlich versucht mich damit auseinanderzusetzen wie du das ganze programiert hast, dabei bin ich auf viel befehle gestoßen bin, die ich googeln musste.
Einige habe ich aber habe ich nicht gefunden. Könntest du mir bitte ihre funktion erklären:

Code:
volatile long long sumMesswerteRMS;

Bringt das doppelte long die dopelte speicherkapazität also 64 bits?

Code:
char buffer[45];

Was ist das? was macht es?

Code:
snprintf(buffer,sizeof(buffer),"%d - %ld mV - %ld mA - %ld W",(int)messwert,spannungMV,stromMA, leistungW);
    Serial.println(buffer);

da sind einige sachen drin die ich nicht verstehe wie snprintf.

Code:
+=

Was macht dieser operator?

Code:
lround()

was bewirkt dieser befehl?

Code:
void initTimer2()
{ // Timer-Interrupt für eine Rate von 980 Interrupts pro Sekunde initialisieren
  TCCR2B = (1<<WGM22) | (1<<CS22);
  OCR2A = 254;
  // enable Timer 2 interrupts
  TIMSK2 = (1<<OCIE2A);
}
Code:
ISR(TIMER2_COMPA_vect)

Davon verstehe ich garnichts. Ich weiß ja das ich unerfahren bin mit dem Arduino und mit C++ aber sowas habe ich noch garnicht gesehen. Soweit ich verstanden habe sind diese Interrupts dafür da um aufgaben im hintergrund zu erledigen.

Code:
while (1); // Und eine Endlosschleife bis zum nächsten Reset ausführen

Meinst du mit reset den ganzen arduino reseten, also das ich den heizen() befehl erst nach einem kompleten arduino reset verwenden kann ?

Hab ich das richtig verstanden das dieser sketch auch abweichungen von Sollwert korrigiert?
Also zieht er automatisch bei abweichungen automatisch prozente ab oder fügt welche hinzu.
Also wenn der vom poti eingestelter sollwert 1500W ist der Istwert aber 1600 ist so werden -2,7333333333333333333333333333333% abgezogen richtig?
Oder habe ich da was falsch verstanden mit der regelung?

Nochmal danke das dir für irgendjemanden Zeit nimmst und mit deinem programmierwissen hilfst.
« Last Edit: September 29, 2013, 01:24:03 pm by strohhirn » Logged

Gruß

strohhirn

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2440
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Einige habe ich aber habe ich nicht gefunden. Könntest du mir bitte ihre funktion erklären:

Sehr schön, dass Du nachfragst!
Offenbar versuchst Du, den Code zu verstehen.
Was ja nicht das schlechteste ist, wenn Du den Code selbst erweitern möchtest.

Code:
volatile long long sumMesswerteRMS;

Bringt das doppelte long die dopelte speicherkapazität also 64 bits?

Exakt. Eine "long" Variable hat 32 Bits, eine "long long" Variable hat 64 Bits.
Zur Zeit habe ich zwar "nur" 980 Messungen pro Sekunde am ACS12 programmiert, da sollte es mit 32-Bit Variablen zwar noch ausreichen. Bei einem angenommenen maximalen durchschnittlichen Messwert von 512/sqrt(2)= 362 würden innerhalb von 10 Sekunden ja nur addiert werden:
10 * 980 * 3622 = 1284231200, was weit unter den 4294967295 liegt, bis zu denen ein "unsigned long" aufaddieren kann. Aber falls man die Interrupt-Rate des Timers doch nochmal verdoppeln oder vervierfachen möchte, zwecks Erhöhung der Messauflösung, ist man von der Variablendeklaration dann schon mal gut vor und gegen Variablenüberlauf abgesichert.

Code:
char buffer[45];

Was ist das? was macht es?

Deklaration eines char-Arrays (C-String) zur Aufnahme von Strings bis zu 44 Zeichen maximaler Länge (plus \0 Endezeichen).

Code:
snprintf(buffer,sizeof(buffer),"%d - %ld mV - %ld mA - %ld W",(int)messwert,spannungMV,stromMA, leistungW);
    Serial.println(buffer);

da sind einige sachen drin die ich nicht verstehe wie snprintf.

Die Funktion "snprintf" ist die gegen Pufferüberläufe sichere Variante der Funktion "sprintf".
Sie dient zur Formatierung von Strings. In diesem Fall der Debug-Zeile, die auf Serial ausgegeben wird.

Im Prinzip gibst Du im Formatierungsstring ("%d - %ld mV - %ld mA - %ld W") mit Platzhaltern vor, was ausgegeben werden soll. Der Platzhalter "%d" steht dabei für eine Integer-Zahl, "%ld" für einen long-Wert. Die Parameterliste hängt hinten dran.

Code:
+=

Was macht dieser operator?

Das ist eine Kurzform Schreibweise.

var1 += var2;
ist exakt dasselbe wie
var1 =  var1 + var2;

Dieselbe Kurzform gibt es für alle anderen Grundrechenarten und auch bitweise Verknüpfungen.

Code:
lround()

was bewirkt dieser befehl?

Die "lround" (long round) Funktion rundet eine Gleitkommazahl auf den nächsten ganzzahligen Wert und liefert eine Ganzzahl vom Typ "long" zurück.

Du kannst in Deinen Arduino-Programmen (nahezu) alle Funktionen der "AVR libc" Library verwenden. Falls Du also mal Funktionen brauchst, alle diese Librarys sind verwendbar:
http://www.nongnu.org/avr-libc/user-manual/modules.html
Klick Dich durch und Du findest die jeweiligen Funktionen, die Du verwenden kannst, es sind hunderte!
Wenn Du nähere Infos brauchst: Die meisten Funktionen lassen sich sehr gut googeln, da es gewöhnliche Standardfunktionen sind, die in jeder C-Standardlibrary enthalten sind.

Code:
void initTimer2()
{ // Timer-Interrupt für eine Rate von 980 Interrupts pro Sekunde initialisieren
  TCCR2B = (1<<WGM22) | (1<<CS22);
  OCR2A = 254;
  // enable Timer 2 interrupts
  TIMSK2 = (1<<OCIE2A);
}
Code:
ISR(TIMER2_COMPA_vect)

Davon verstehe ich garnichts. Ich weiß ja das ich unerfahren bin mit dem Arduino und mit C++ aber sowas habe ich noch garnicht gesehen. Soweit ich verstanden habe sind diese Interrupts dafür da um aufgaben im hintergrund zu erledigen.

Damit werden Timer-Interrupts und eine Timer-Interruptbehandlungsroutine programmiert. Die AVR-Controller haben verschiedene Timer, die so programmiert werden können, dass bei einem bestimmten Timerstand das laufende Programm unterbrochen wird, es wird der Unterbrechungscode ausgeführt, und danach setzt das normale Programm an der Stelle weiter fort, an der es unterbrochen wurde.

Das fällt unter "Programmiertechniken für Fortgeschrittene".

Ich verwende die Timer-Interrupts, um exakt nach Ablauf von 1/980 Sekunden eine Messung am ACS712 durchzuführen. Aus 980 Messwerten pro Sekunde, bzw. in diesem Sketch 9800 Messwerten in 10 Sekunden errechne ich dann den sogenannten "Effektivwert" des Stroms, der "im Durchschnitt" tatsächlich fließt.

Code:
while (1); // Und eine Endlosschleife bis zum nächsten Reset ausführen

Meinst du mit reset den ganzen arduino reseten, also das ich den heizen() befehl erst nach einem kompleten arduino reset verwenden kann ?

Ja, die "Abschaltung" schaltet die Heizung ab und beendet die Programmausführung. Zum Neustart muß dann der Reset-Button gedrückt werden. Oder ein anderer Button, der an "Reset" angeschlossen ist.


The message exceeds the maximum allowed length (9500 characters) - Fortsetzung im nächsten Beitrag.
Logged

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2440
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Hab ich das richtig verstanden das dieser sketch auch abweichungen von Sollwert korrigiert?
Also zieht er automatisch bei abweichungen automatisch prozente ab oder fügt welche hinzu.

Ja. Der Sketch hat einen Proportional-Regler (P-Regler) eingebaut.

Mit dem Poti stellst Du NICHT die Stellung des Heizungsreglers ein, also mit wieviel Prozent der Maximalleistung geheizt werden soll. Diese Stellung des Heizungsreglers rechnet sich das Programm selbst aus.

Du stellst mit dem Poti ein: Gewünschte Heizleistung in Watt
Der Sketch macht: Tatsächliche Heizleistung in Watt messen.
Bei Abweichungen entweder mehr oder weniger heizen, bis es bestmöglich passt.

Also wenn der vom poti eingestelter sollwert 1500W ist der Istwert aber 1600 ist so werden -2,7333333333333333333333333333333% abgezogen richtig?
Oder habe ich da was falsch verstanden mit der regelung?

Korrekt, so habe ich es eingestellt. In dem Fall würde also (gerundet) beim nächsten Heizintervall die heizen() Funktion mit 3% weniger Heizwert aufgerufen werden als im Intervall vorher.

Falls Du Dich fragst, woher in der Formel der Faktor 0.82 herkommt: Der Faktor ist willkürlich "etwas niedriger als 1" gewählt, damit in einem Schritt nicht versucht wird, die volle aufgetretene Differenz auszugleichen, sondern etwas weniger. Mit dem Faktor 0,82 also 82% der vorhandenen Regeldifferenz in einem Schritt. Dies führt zwar zu einem etwas langsameren, aber insgesamt einem stabilen Regelverhalten.

Beispiel-Regelung mit Start bei heizen(0), Istwert 0, Sollwert 0 und nun wird der Sollwert plötzlich auf 1000 W gedreht.
Der Regler geht mal angenommen von 30W = 1% Heizleistung aus.

Nach 10s stellt der Regler fest:
Sollwert 1000, Istwert 0, Differenz 1000, stelle den Regler um 0,82*33,3= 27,3% = 27% höher

Nach nochmal 10s stellt der Regler fest
Sollwert 1000, Istwert 810, Differenz 190, stelle den Regler um 0,82*6,3% = 5,2% = 5% höher auf nunmehr 32%

Nach nochmal 10s stellt der Regler fest
Sollwert 1000, Istwert 960, Differenz 40, stelle den Regler um 0,82*1,3% = 1,1% = 1% höher auf nunmehr 33%

Nach nochmal 10s stellt der Regler fest
Sollwert 1000, Istwert 990, Differenz 10, stelle den Regler um 0,82* 0,3% = 0,2% = 0% höher, bleibt bei 33%

==> bleibende Regelabweichung 10W = 0,1% ab 30s nach Sollwertänderung von 0 auf 1000 W.

Der Faktor 0,82 sorgt also für ein langsames Annähren an den Zielwert, wenn der Faktor höher gewählt wird, z.B. 0,9 oder 0,95, erfolgt die Angleichung schneller. Aber Vorsicht: Es besteht dann die Gefahr des Überschwingens!

Denn der Regler rechnet nur damit (konstant), dass bei 1% mehr Heizen wohl mit 30 Watt mehr geheizt wird. Das stimmt aber bei Spannungsschwankungen nicht. Bei Überspannung von 253 statt 230 Volt ist ja die Leistung der Heizung um den Faktor (253/230)2= 1,21 größer, d.h. 1% Heizleistung entspricht nicht mehr 30 Watt, sondern 36,3 Watt.

D.h. wenn der Regler versuchen würde, beispielsweise fehlende 300 Watt Heizleistung durch 10% mehr heizen in einem Schritt auszugleichen, dann könnte er bei Überspannung tatsächlich mit 363 Watt mehr heizen und den Regler "überdrehen". Der zu regelnde Wert kann dadurch ins "schwingen" kommen, und würde dann mal deutlich über, mal deutlich unter dem Sollwert liegen. Und um ein instabiles Regelverhalten bei Überspannung zu vermeiden, regelt der Regler eben in jedem 10-Sekunden-Intervall nur 82% der Regeldifferenz aus. Weshalb 0,82? Oben habe ich mir bei Überspannung ausgerechnet, dass 1% Heizleistung statt nomineller 30 Watt bei Überspannung auch 36,3 Watt sein können. 30/36,3 = 0,826 = abgerundet 0,82.

Dynamisch geregelte Systeme entwickeln ja immer ein gewisses "Eigenleben", wenn sich das System selbst regelt. Da ist es natürlich vorteilhaft, wenn man vorher dran denkt, dass die Regelung nicht nur bei 207 Volt und 230 Volt zu einer stabilen Regelung führen muss, sondern auch bei 253 Volt Netzspannung darf die Regelung nicht einfach "durchdrehen".
Logged

Offline Offline
Sr. Member
****
Karma: 2
Posts: 261
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hab heute den sketch ausprobiert, war aber echt traurig weil auch dieser sketch nicht funktioniert hat.  smiley-sad

Ich habe wieder den Serialen monitor fotografiert, weil der  PC bei der apparatur kein internet hat, is für mich so einfacher.

Mal wurde einfach mal neuer sollwert paarweise runtergebrettert, und mal alle 10 sek diese debug zeile die zu viel watt angezeigt hat.





* k-20131001_145746.jpg (91.3 KB, 480x640 - viewed 18 times.)

* k-20131001_145943.jpg (64.72 KB, 480x640 - viewed 19 times.)

* k-20131001_151037.jpg (108.27 KB, 480x640 - viewed 17 times.)

* k-20131001_145447.jpg (101.53 KB, 480x640 - viewed 15 times.)
Logged

Gruß

strohhirn

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2440
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hab heute den sketch ausprobiert, war aber echt traurig weil auch dieser sketch nicht funktioniert hat.  smiley-sad

Ich habe wieder den Serialen monitor fotografiert, weil der  PC bei der apparatur kein internet hat, is für mich so einfacher.

Mal wurde einfach mal neuer sollwert paarweise runtergebrettert, und mal alle 10 sek diese debug zeile die zu viel watt angezeigt hat.

Tja, es ist wie ich oben geschrieben habe:
Quote from: jurs
Da ich nichts von der Hardware hier habe (keine Heizung mit SSR-Relais, kein ACS712) kann ich von dem Code praktisch nichts im Zusammenspiel testen.

Das Finden und Beseitigen der Fehler wäre Dir überlassen - viel Spass dabei!

Hast Du in dem Sketch die #define Statements für die Pins des Sollwert-Poti. des ASC712 und des SSR angepaßt?

Wenn der "sollwert paarweise runtergebrettert" bedeutet dass: Du hast am Sollwert-Poti überhaupt keinen stabilen Messwert. Das Sollwert-Poti am Analog-Pin kann von 0 bis 1023 messen, diese ca. 1000 verschiedenen Werte am ADC werden auf Sollwerte von 0 bis 3000 Watt in 30 Watt Schritten heruntergerechnet, d.h. 10 Einheiten am ADC entsprechen einem durch 30 teilbaren Sollwert. Immer wenn ein anderer Sollwert auftritt, wird dieser sofort ausgegeben. Das "Runterbrettern" der Werte heißt: Du bekommst ständig einen neuen Sollwert über das Poti. Das kann daran liegen, dass Du gar kein angeschlossenes Poti abfragst, sondern einen offenen, unbeschalteten Analogeingang. Oder Du hast erhebliche elektromagnetische Beeinflussungen in Deiner Schaltung, die den Wert schwanken lassen.

Auch der viel zu hohe Wert für die gemessene Leistung deutet daraufhin, dass Du womöglich einen unbeschalteten Analogeingang abfragst und keinen ACS712, der den Strom durch Deine Heizung mißt.

Ich würde nochmal die Pin-Definitionen prüfen und ob auch
- das Sollwert-Poti
- der ASC712
- das SSR zum Schalten der Heizung
dort angeschlossen wurden, wo es im Sketch definiert wurde.

Und ansonsten die erste Code-Zeile beachten und das Programm selbst debuggen.

Ich habe hier Deine Hardware nicht zum Testen zur Verfügung.


Logged

Pages: 1 ... 3 4 [5]   Go Up
Jump to: