Solarlicht Steuerung

Gast #638278
Lesenswert?

Hallo an alle Bastler und Hobbyprogrammierer!

Ich habe hier mal ein kleines Projekt als Anregung bzw. zur Diskussion 
eingestellt. Es ist eine µC-basierte Steuerung für eine Solarlampe.
An meinen Garten-Solarlampen hat mich schon immer gestört, dass der 
simple, diskret aufgebaute Step-Up Konverter ungeregelt ist, d.h. die 
Helligkeit mit sinkender Akkuspannung abnimmt. Inspiriert durch einen 
Artikel im ELV-Journal 3/2007 (SLS2) habe ich dann diese Steuerung 
entwickelt.

Warum?
Weil's Spaß macht und weil ich beim ELV-Teil nicht's am µC-Programm 
ändern kann! Einziger Nachteil: Die billigen LED-Treiber von Zetex sind 
schwer zu bekommen. Also dachte ich mir, dass ich die LED-Stromregelung 
einfach mit in den µC packe... bitte nicht schlagen, ich weiß, es gibt 
genug andere IC's dafür... aber ich habe dadurch einiges über DC-DC 
Konverter und deren Regelung gelernt! Ausserdem braucht sich meine 
Schaltung mit einem Wirkungsgrad von ca. 80% nicht gerade verstecken :-)
Zu verbessern wären der Schalttransistor (ein low Uce,sat) und 
vielleicht die Schottky-Diode. Ich habe mich mich eben mit dem begnügen 
müssen, was die Bastelkiste so her gab!

Das Projekt ist noch lange nicht fertig. So fehlt das eigentliche 
Feature: Die intelligente Verteilung der Akkuenergie, also Abschaltung 
der Lampe mitten in der Nacht, wenn's keiner braucht, dafür aber noch 
Energie übrig haben für den nächsten Morgen, etc. Ausserdem fehlen mir 
die Schwellwerte der Solarzellen-Spannung, zur An-/Abschaltung der 
Lampe. Muss ich erst noch messen. Dürfte aber eh' bei jeder Lampe etwas 
anders sein! Und zu guter Letzt muss das ganze auf 'ne eigene Platine 
drauf...

Trotzdem denke ich, dass man sich hierbei einige Anregungen holen kann, 
insbesondere wenn man MSP430 programmieren will. Denn nahezu alle 
Funktionen des verwendeten MSP430F1232 habe ich sozusagen ausgereizt.
Einige Features:

- Verwendung eines 32,768kHz Quarzes als Referenz-Clock
- periodischer Abgleich des internen DCO-Oscillators mit den 32,768kHz
  (Timer_A mit Capture)
- Timer_A mit Compare-Registern zur Erzeugung einer PWM mit variablem
  Duty-Cycle
- Synchronisierung der ADC-Messung mit der PWM
- digitale PI-Regelung (LED-Strom)
- versch. Messungen mit dem internen ADC10
- versch. Low-Power-Modi
- Statemachine mit (zum Teil) interrupt-gesteuerten Zustandsänderungen

Im Anhang sind der Schaltplan und die C-Sourcen, die ich mit IAR EW 
V3.42A (Kickstart) erstellt habe, sowie Flowcharts zum (hoffentlich) 
besseren Verständnis.

Noch Fragen? Immer her damit!
Außerdem würde ich mich natürlich über Anregungen, Hinweise und 
konstruktive Kritik freuen.

Ansonsten viel Spaß damit.
Gruß,
Stefan


P.S.: Ich glaube, es versteht sich von selbst, dass jeder diese 
Schaltung und das Programm verwenden darf. Es darf sich aber keiner 
beschweren, wenn irgend etwas nicht so funktioniert, wie er/sie sich das 
vorgestellt hat... sprich: ich übernehme dafür kein Haftung!
Angehängte Dateien:
Gast #639006
Lesenswert?

Prinzipiell hast Du recht, in diesem speziellen Fall geht ErrSum 
allerdings nicht in die Begrenzung (zumindest nicht im Normalfall). Die 
Sollgröße ist ja 109 (= 8mA LED-Strom), d.h der Fehler Err kann auch nur 
max. 109 sein. Die Begrenzung für ErrSum ist 32767/4=8191. D.h. ich 
könnte den max. Fehler (Err=109) 75-mal in ErrSum aufsummieren, ohne in 
die Begrenzung zu kommen.
Mein Abtast-/Regelintervall ist 2*85µs=170µs. Bei 75 Intervallen ergäbe 
das eine Regelungsdauer von 75*170µs=12,75ms. Der LED-Strom ist aber 
schon nach ca. 3ms eingeregelt -> genug Puffer :-)

Oder anders:
Wenn der LED-Strom auf den Sollwert eingeregelt ist, gilt:
PWM = (32*Err + 4*ErrSum)/128, mit Err=0.
Die Stellgröße ist dann PWM=42, d.h. ErrSum = PWM*128 / 4 = 1344 << 8191

Aber warum willst Du mit einem Timer oder Warteschleife einen Überlauf 
verhindern? Dann wäre doch das Abtastintervall nicht mehr konstant?
Gast #640197
Lesenswert?

Kleiner Bug-Fix:

> void Set_DCO (void)
> {
>    ...
>    while (!(CCIFG & CCTL2));
>    {
>      if(DCO_Timeout == 460)
>        WDTCTL = 0;
>    }
>    ...
>    while (!(CCIFG & CCTL2));
>    {
>      if(DCO_Timeout == 460)
>        WDTCTL = 0;
>    }
>    ...
> }

Hinter while ((!(CCIFG & CCTL2)) natürlich das Semikolon weglassen!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren