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 | int main() |
2 | {
|
3 | uint8_t i; |
4 | |
5 | ... timer initialisieren |
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 | int main() |
2 | {
|
3 | ... timer initialisieren |
4 | ... adc initialisieren |
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_t WarteZeit; |
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.
Hallo Karl Heiz, vielen dank für deine ausführliche Vorgehensweise! ich habe nun den Code so geändert:
1 | /**************************************************************/
|
2 | /* Title: Testversion Firmware ausschaltverzögerung */
|
3 | /* Author: Bitschnau Lukas */
|
4 | /* Date: 11/2009 */
|
5 | /* Purpose: Toggeln aller 8 LEDs */
|
6 | /* Software: AVR-GCC / AVR Studio 4.12 */
|
7 | /* Hardware: ATmega16/Megacard */
|
8 | /* Note: fclk=12MHz */
|
9 | /**************************************************************/
|
10 | #include <AVR/io.h> |
11 | #include <AVR/interrupt.h> |
12 | #include <AVR/signal.h> |
13 | #include <until/delay.h> |
14 | |
15 | |
16 | int main( void ) |
17 | {
|
18 | |
19 | //Timer Initialisierung
|
20 | |
21 | TCCR0 = 0b01100001; // Kein Timer Vorteiler |
22 | /*
|
23 | kein Vorteiler
|
24 | keine Invertierung
|
25 | fast PWM
|
26 | normale Port operation
|
27 | */
|
28 | TIMSK = 0x01; // Timer Interrupt Aktiviern |
29 | |
30 | // Port Initialisierung
|
31 | |
32 | // DDRC = 0x01; // LED0 als Ausgang
|
33 | DDRC = 0xFF; // PORTC als Ausgang (zum Debuggen) |
34 | DDRD = 0xFF; |
35 | DDRA = 0x00; // port A als eingang |
36 | DDRB = 0xFF; // OCR0 Port als ausgang (PWM ausgang) |
37 | PORTA = 0x01; // Pullup an Pin 1 einschalten (fur Schalteingang)1 |
38 | |
39 | sei(); //alle Interrupts enablen |
40 | unsigned int i; |
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.