Hallo,
ich versuche eine kleine Software zu schreiben, welche eine kleine
Ausschaltverzögerung nachbildet.
Folgende Funktionen sollte sie können:
- Taster über Pullup angeschlossen PA0
- Poti zum einstellen der ausschaltverzögerung ADC4
- PWM ausgang OCR0
wird der Taster gedrückt, soll OCR0 = 255 sein, nach dem loslassen des
Tasters soll der Wert bis zum ablaufen einer Zeitspanne (einstellbar
über Poti (max. 30s)) konstannt gehalten werden (am sugang der PWM
ändert sich nichts). Ist die Zeit abgelaufen, soll der PWM wert auf 0
heruntergedimmt werden.
Leider funktioniert das Herunterdimmen bei mir überhaupt nicht, der PWM
Port blinkt manchmal kurz auf und erlischt wieder. Weiters stimmt die
Zeit nicht, in welcher der Timer durchlaufen wird, ich habe ein wenig
herumpobiert und so stimmt der Wert irgendwie, weiß nur nicht was an
meiner Berechnung falsch ist.
Könnt ihr mir bitte ein wenig helfen?
Grüße
Lukas
Lukas B. schrieb:> Leider funktioniert das Herunterdimmen bei mir überhaupt nicht, der PWM> Port blinkt manchmal kurz auf und erlischt wieder.
Kein Wunder, wenn du gleich im ersten Schleifendurchlauf OCR0 auf 0 (und
nebenbei i auf 1) setzt. ;-)
Hallo,
habe vergessen OCR0 = 0 auszukommentieren, habe dies zum testen gemacht
und funktioniert auch, leider funktioniert das dimmen gar nicht, wenn
ichs mit dem simplen code mache:
1
if((count>=adc_wert)&&(start==0x01))
2
{
3
count=0;
4
PORTC=0x00;// PORTC auf 0 (Debugg)
5
start=0x00;// Hilfsvariable auch auf 0
6
7
8
//OCR0 = 255;
9
// Wenn der count = dem ADC Wert entspricht
10
// sollte der PWM Ausgang auf 0 heruntergedimmt werden, Zeit ist vorerst
11
// egal.
12
13
/* // Code für Dimmung funktioniert nicht, OCR0 leuchtet kurz auf und geht wieder aus, keine Ahnung warum
14
int i;
15
for (i = 255; i>0; i--)
16
{
17
18
OCR0 = i;
19
_delay_us(10000);
20
if(i = 1)
21
{
22
OCR0 = 0;
23
break;
24
}
25
}
26
*/
27
_delay_ms(5);
28
OCR0=250;
29
_delay_ms(5);
30
OCR0=200;
31
_delay_ms(5);
32
OCR0=100;
33
_delay_ms(5);
34
OCR0=0;
35
36
}
funktionierts auch nicht, ich verstehe überhaupt nicht was da los ist,
vl weis irgandhemand von euch an was es liegt.
Grüße
Lukas
Funktioniert denn deine ADC Abfrage?
Funktioniert das Dimmen für sich alleine?
Schreib dir doch fürs erste mal eine wirklich simple Anwendung, womit du
die Einzelteile testest.
Erst mal muss PWM ohne irgendetwas anderes funktionieren
1
intmain()
2
{
3
uint8_ti;
4
5
...timerinitialisieren
6
7
while(1){
8
i++;
9
OCR0=i;
10
_delay_ms(10);
11
}
12
}
das sollte eine schön auf- (oder ab-) dimmende LED ergeben.
Funktioniert das?
WEnn das funktioniert, dann nimm den ADC mit dazu
1
intmain()
2
{
3
...timerinitialisieren
4
...adcinitialisieren
5
6
while(1){
7
OCR0=adc_wert;
8
}
9
}
drehen am Poti muss die Helligkeit der LED verändern.
Und erst dann, wenn das alles funktioniert, machst du die Zeitsteuerung
mit dazu. Wobei du das durchaus problemlos innerhalb der Interrupt
Handler Routine machen kannst. Die paar Anweisungen kannst du dir ohne
Bedenken dort leisten.
Wobei du wieder nicht sofort zum Rundumschlag ausholst, sondern in
Stufen vorgehst. Bei Tastendruck soll die LED eingeschaltet werden und
nach einer gewissen fixen Zeitdauer (nach dem Loslassen) einfach
ausgeschaltet werden.
Du machst das, indem du in der ISR einen Zeitzähler um 1 verminderst,
wenn er nicht schon 0 war, und wenn nach dem Runterzählen um 1 die Zeit
zu 0 geworden ist, schaltest du die LED aus.
1
uint8_tWarteZeit;
2
3
SIGNAL(...)
4
{
5
...
6
7
if(WarteZeit>0){
8
WarteZeit--;
9
if(WarteZeit==0)
10
OCR0=0;
11
}
12
}
13
}
Ein Tastendruck setzt die Wartezeit auf eine bestimmte Zeitdauer und
schaltet die LED ein. Der Timer läuft und zählt die Wartezeit wieder
runter und wenn sie dann vorbei ist (0 erreicht), dann schaltet er die
LED aus.
Erst mal nur ausschalten.
Danach ersetzt du die bis dahin fixe Wartezeit, die du bei gedrückter
Taste zuweist durch einen Wert, den du vom ADC bekommst. Damit kannst du
dann die Leuchtdauer durch das Poti einstellen.
Und wenn das dann alles klappt, dann fadest du mit dem ISR Mechanismus
die LED langsam aus, anstelle dass du sie durch Setzen von OCR0 einfach
ausschaltest.
Nicht zuviel auf einmal machen! Einzelkomponenten testen!
Schrittweise aufs Ziel hinarbeiten - egal wie einfach das Endziel auch
am Anfang aussehen mag.
PORTA=0x01;// Pullup an Pin 1 einschalten (fur Schalteingang)1
38
39
sei();//alle Interrupts enablen
40
unsignedinti;
41
42
while(1)
43
{
44
i++;
45
OCR0=i;
46
_delay_ms(10);
47
}
48
49
}
dabei tritt folgendes Verhalten auf:
zu beginn ist die LED an OCR0 aus, nach ca 3 sec. schaltet sie auf ganze
Helligkeit und dann wird si richtig ruckartig heller und dünkler, geht
aber nie ganz aus.
an was kann es liegen, bin voll ratlos?!
Grüße
Lukas
Lukas B. schrieb:> Hallo Karl Heiz,> vielen dank für deine ausführliche Vorgehensweise!> ich habe nun den Code so geändert:> [c]> /**************************************************************/> /* Title: Testversion Firmware ausschaltverzögerung> */> /* Author: Bitschnau Lukas> */> /* Date: 11/2009 */> /* Purpose: Toggeln aller 8 LEDs */> /* Software: AVR-GCC / AVR Studio 4.12 */> /* Hardware: ATmega16/Megacard */> /* Note: fclk=12MHz */> /**************************************************************/> #include <AVR/io.h>> #include <AVR/interrupt.h>> #include <AVR/signal.h>> #include <until/delay.h>>>> int main( void )> {>> //Timer Initialisierung>> TCCR0 = 0b01100001; // Kein Timer Vorteiler> /*> kein Vorteiler> keine Invertierung> fast PWM> normale Port operation> */
Dein Kommentar stimmt nicht.
Tu dir doch selbst einen Gefallen und schreib das NICHT mit einer
Binärzahl
TCCR0 = ( 1 << WGM00 ) | // Phase correct PWM
( 1 << COM01 ) | // Clear on Up-match, Set on Down-match
( 1 << CS00 ); // Prescaler: 1
so liest sich das viel besser und es lässt sich auch viel leichter mit
dem Datenblatt kontrollieren, als wie wenn man ständig im Datenblatt hin
und her scrollen muss um zu kontrollieren, welche Bits du da eigentlich
gesetzt hast und was sie bedeuten.
> TIMSK = 0x01; // Timer Interrupt Aktiviern
Detto
TIMSK = ( 1 << OCIE0 );
Du gibst also den Output Compre Interrupt vom Timer 0 frei. Wenn du das
tust, dann musst du auch eine ISR schreiben. Hast du keine ISR, dann
wird beim ersten Interrupt der µC resettet.
> an was kann es liegen, bin voll ratlos?!
liegt wahrscheinlich an der ISR, die du nicht implementiert hast. Für
dieses Beispiel brauchst du sie nicht. Also gib den Interrupt einfach
nicht frei.
Die PWM müsste damit funktionieren. Allerdings
* Warum Phase Correct Mode, anstelle von Fast PWM MOde
* denn: Mit dem Compare Match Interrupt wirst du nicht viel anfangen
können, wenn es um die Zeitsteuerung geht. Da ist der Fast-PWM
mit seinen regelmässigen Overflow Interrupts viel besser geeignet.
Hallo Karl Heinz,
vielen Dank für deine Hilfestellung!
Ich habe ein wenig gearbeitet und mit Hilfe des Tutorials und des
Datenblattes einen funktionierenden Code geschrieben, ich habe in Mal in
den Anhang gestellt. Ich werde jetzt noch die Platine fertig designen,
den Print anschließend bestücken und dan das Fertige Projekt in der
Codesammlung veröffentlichen.
Grüße
Lukas
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.