Moin moin, zuerst mal bin ich völliger Newbie in diesem Bereich und habe nicht wirklich viel Erfahrung im Bereich programmieren und würde mich über hilfreiche Beitrage die mich weiterbringen sehr freuen ! Ich möchte gerne über meinen Attiny13 2 Ausgangskarten(Pollin Bausatz) über einen Eingang(Taster) steuern, mit Folgender Funktion: Wenn die Schaltung Spannung bekommt, soll als erstes Ausgangskarte 1 einmal 5 Sekunden lang angesteuert werden. Wenn ich nun meinen Schalter betätige, soll Ausgangskarte 2 5 Sekunden angesteuert werden. Wenn ich nun meinen Schalter erneut betätige soll wiederum Ausgangskarte 1 5 Sekunden angesteuert werden. Dies soll immer im Wechsel so weiter gehen. Wichtig ist, das die Steuerung beim Start immer mit der selben Ausgangskarte anfängt. Ist dies einfach und mit einem Attiny13 zu realisieren ? Kann mir jemand bei dem Programm auf die Sprünge helfen ? MFG Steve
Steffen Ebeling schrieb: > Kann mir jemand > bei dem Programm auf die Sprünge helfen ? Starte hier: https://www.mikrocontroller.net/articles/AVR und mach dann mit dem AVR Tutorial weiter. Wenn du eine LED blinken lassen kannst, bist du in der Lage Ausgangspins zu steuern. Weiterhin brauchst du für dein Projekt eine Art Uhr, die beim AVR Timer genannt wird. Und du musst Eingangspins lesen können. Das ist erstmal die Grundlage. Feinheiten sind z.B. die Entprellung deines Schalters und das Speichern seines Zustandes, damit du die Bedingung deines Projekts erfüllst.
:
Bearbeitet durch User
Steffen E. schrieb: > zuerst mal bin ich völliger Newbie in diesem Bereich Dann ist der Ratschlag meines Vorschreibers sehr zu beherzigen. Nutze die genannten Lernhilfen! > Ist dies einfach und mit einem Attiny13 zu realisieren Logo. > Kann mir jemand > bei dem Programm auf die Sprünge helfen ? Jetzt ist die erste Frage: Welche Programmiersprache? Ich empfehle da Assembler, da Du den Controller und dessen Möglichkeiten dann mit dem Tiny13 Datenblatt in der Hand gleich von grundauf kennenlernst. > Wichtig ist, das die Steuerung beim Start immer mit der selben > Ausgangskarte anfängt. Das wird schon dadurch sichergestellt, daß Dein Programm immer von der gleichen Stelle aus anfängt und Du dann eben Deine vorgesehene Karte samt eines sogenannten Hardware-Timers aktivierst. > einmal 5 Sekunden lang Für sowas brauchst Du diesen Timer des Tiny13. Der wird in Abhängigkeit von der Taktfrequenz des Controllers zum Beispiel so eingestellt, daß er nach Aktivierung durch die Tasterabfrage los- und bei 5 Sekunden "überläuft" und dabei was sinnvolles auslöst- wie eben das Deaktivieren der aktuellen Karte. Die Tasterabfrage aktiviert neben dem Timer natürlich auch die nächste, richtige Karte. Du hast nur zwei, also kann man sich den aktuellen Zustand in einer binären Variable merken (beim Controllerstart auf 0 gesetzt). Die wird bei Timerablauf einfach noch mit invertiert, damit die Tasterabfrage beim nächsten Auslösen wieder die andere Karte aktivieren kann. So weit so einfach- der ganz grobe Ablauf. Eine solche Taster-Anwendung enthält aber oft noch eine besondere Herausforderung: Mechanische Taster prellen. Das heißt, sie können in kürzester Zeit mehrfach auslösen. Mit Deinem gemächlichen Vorhaben hast Du aber Glück: Das muß Dich nicht interessieren. Die Tasterabfrage tut bei aktiviertem 5s-Timer einfach nix...
Hi Moin moin, zuerst mal bin ich völliger Newbie in diesem Bereich und habe nicht wirklich viel Erfahrung im Bereich programmieren und würde mich über hilfreiche Beitrage die mich weiterbringen sehr freuen ! Nun, so allgemein wie du dein Anliegen vorbringst, liest sich das wie:" Ich brauch ein Programm, wer macht mir das". Das ist jetzt nicht bös gemeint, aber es wird ein weiter Weg, bis du ein Programm selbst schreiben kannst. Sicherlich hast du den bereits erwähnten Hinweis auf die Tutorials gesehen. Die sind gut verständlich und für Übungen bestens geeignet. So lernst du die Controller kennnen. Zur Sprache kann ich auch noch auf einen Beitrag im Forum von WWW.AVR-Praxis.de unter der Rubrik FAQ verweisen. Dort findest du u.A. im Beitrag "keine Angst vor Assembler" sicherlich alle benötigten Bausteine für deinen Programmwunsch ausführlich beschrieben. Gruß oldmax
Moby schrieb: > Jetzt ist die erste Frage: Welche Programmiersprache? > Ich empfehle da Assembler, da Du den Controller und dessen Möglichkeiten > dann mit dem Tiny13 Datenblatt in der Hand gleich von grundauf > kennenlernst. Kommt drauf an wie weit du einsteigen willst. Assembler ist schon eine Hausnummer mit der du dich gewaltig beschäftigen muss. Schau mal nach "Arduino"! Damit kannst du das nach zwei Tagen realisieren. Nimmst du jetzt noch einen "Arduino Nano", kannst du ihn nach bestandenen Tests in eine Schaltung auf Lochraster Platinen übernehmen. Wobei ich dir die Lochstreifenraster empfehle. Wenn du mit C programmieren willst, bietet sich auch der ATmega328 an (der auf dem Nano ist), weil du z.B. dieses Programm dann locker auf einen ATtiny10 ohne große Änderungen laufen lassen kannst. http://www.ebay.de/itm/Nano-V3-0-ATmega328-16M-5V-Micro-controller-CH340G-board-for-arduino-/371179047627?pt=LH_DefaultDomain_77&hash=item566bfecacb
foldi, der TE möchte das alles gerne mit dem ATTiny13 realisieren, was, wie wir uns schon einig waren, ohne jedes Problem möglich ist, sonst hätte ich auch gleich protestiert. Das geht in Assembler oder in C, bei einem so überschaubaren Projekt ist ASM das simpelste und man lernt den MC richtig gut kennen. Der Tiny10 ist schon wieder eine andere Liga, die TPI Programmierung kann nicht jeder Programmer und man muss mit den Pins ganz schön haushalten. Hier würde es gerade reichen... Da wir nichts darüber wissen, was der TE für Tools hat, nehmen ich mal an, das der Tiny13 gerade da ist und programmiert werden kann.
Ich hab da grad mal Bock drauf:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #define KARTE1 PB0
|
5 | #define KARTE2 PB1
|
6 | #define TASTER PB2
|
7 | |
8 | |
9 | |
10 | int main(void) |
11 | {
|
12 | // Timer
|
13 | TCCR0A |= (1<<WGM00) | (1<<WGM01); // CTC |
14 | OCR0A = 149; // 9,6MHz / ((149+1) * 64) = 1KHz |
15 | TIMSK0 |= (1<<OCIE0A); // Capture Interrupt |
16 | TCCR0B |= (1<<CS00) | (1<<CS01); // Prescaler 64 |
17 | |
18 | // IOs
|
19 | PORTB = 0; |
20 | DDRB |= (1<<KARTE1) | (1<<KARTE2); |
21 | PORTB |= (1<<TASTER); // Pull-up enable |
22 | |
23 | // global Interrupt enable
|
24 | sei(); |
25 | |
26 | |
27 | while(1){; |
28 | //Nothing to Do
|
29 | }
|
30 | }
|
31 | |
32 | /* 1kHz */
|
33 | ISR (TIM0_COMPA_vect) |
34 | {
|
35 | static uint16_t debounce = 0; |
36 | static uint16_t OnTime = 5000; |
37 | static uint8_t Kartenwahl = 0; |
38 | |
39 | if (debounce) debounce--; |
40 | |
41 | if (!(PINB & (1<<TASTER)) && !debounce){ |
42 | debounce = 100; |
43 | OnTime = 5000; |
44 | Kartenwahl++; |
45 | }
|
46 | |
47 | if (OnTime){ |
48 | switch (Kartenwahl%2){ |
49 | case 0: PORTB |= (1<<KARTE1); break; |
50 | case 1: PORTB |= (1<<KARTE2); break; |
51 | default: break; |
52 | }else{ |
53 | PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) ); |
54 | }
|
55 | }
|
Viel Spass damit
Ulrich F. schrieb: > OnTime ist, und bleibt, 5000. > Oder habe ich was übersehen? Warum? Wird einmal auf 5000 initialisiert und wird dann decrementiert. Erst bei erneutem drücken des Tasters wird die Variable wieder auf 5000 gesetzt. Stichwort static Edit: Ja sorry, das Decrement fehlt :(
1 | if (OnTime) OnTime--; |
:
Bearbeitet durch User
Da ist es aber nicht egal, wie der Schalter beim Start steht. Es soll ja in jedem Fall erst Karte 1 laufen, und beim Umschalten dann Karte 2. Man sollte also den Startzustand des Schalters in einem Flag speichern und den Schalter damit vergleichen. Wenn gleich, dann Karte 1, bei Unterschied dann Karte 2.
Matthias Sch. schrieb: > foldi, der TE möchte das alles gerne mit dem ATTiny13 realisieren, Hast recht.
Ingo Less schrieb: > Edit: > Ja sorry, das Decrement fehlt :( > >
1 | > if (OnTime) OnTime--; |
2 | >
|
Einen hab ich noch. Ich hoff, ich hab mich da jetzt nicht vertan. Wenn während der 5 Sekunden der Taster erneut betätigt wird, kann es sein, dass beide Karten angesteuert werden. Obwohl: der TO hat ja nicht verraten, was in diesem Fall die korrekte Reaktion wäre. Genauso wie er nicht verraten hat, ab wann die Zeit laufen soll. Ab niederdrücken oder ab loslassen. Kann man durch gedrückt halten des Tasters die 5 Sekunden verlängern oder nicht?
:
Bearbeitet durch User
Moin, vielen Dank erst mal für die vielen Kommentare ! :) Matthias Sch. schrieb: > Starte hier: > https://www.mikrocontroller.net/articles/AVR > und mach dann mit dem AVR Tutorial weiter. Wenn du eine LED blinken > lassen kannst, bist du in der Lage Ausgangspins zu steuern. Weiterhin > brauchst du für dein Projekt eine Art Uhr, die beim AVR Timer genannt > wird. Und du musst Eingangspins lesen können. Ja habe mich auch schon eine Weile mit den Ganzen Grundlagen beschäftig. Da das alles für mich Neuland ist, finde ich das es sehr viele Informationen auf einmal sind. Ingo Less schrieb: > Ich hab da grad mal Bock drauf:#include <avr/io.h> > #include <avr/interrupt.h> > > #define KARTE1 PB0 > #define KARTE2 PB1 > #define TASTER PB2 > > int main(void) > { > // Timer > TCCR0A |= (1<<WGM00) | (1<<WGM01); // CTC > OCR0A = 149; // 9,6MHz / ((149+1) * 64) = 1KHz > TIMSK0 |= (1<<OCIE0A); // Capture Interrupt > TCCR0B |= (1<<CS00) | (1<<CS01); // Prescaler 64 > > // IOs > PORTB = 0; > DDRB |= (1<<KARTE1) | (1<<KARTE2); > PORTB |= (1<<TASTER); // Pull-up enable > > // global Interrupt enable > sei(); > > > while(1){; > //Nothing to Do > } > } > > /* 1kHz */ > ISR (TIM0_COMPA_vect) > { > static uint16_t debounce = 0; > static uint16_t OnTime = 5000; > static uint8_t Kartenwahl = 0; > > if (debounce) debounce--; > > if (!(PINB & (1<<TASTER)) && !debounce){ > debounce = 100; > OnTime = 5000; > Kartenwahl++; > } > > if (OnTime){ > switch (Kartenwahl%2){ > case 0: PORTB |= (1<<KARTE1); break; > case 1: PORTB |= (1<<KARTE2); break; > default: break; > }else{ > PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) ); > } > } Vielen dank! Könntest du eventuell die einzelnen Programmzeilen mal ein wenig erklären, was mit welchen Befehlen genau gemacht wird und wie nun mein gewünschter Ablauf entsteht ? Ich kann aus dem Programm nämlich nicht genau die Zusammenhänge untereinander deuten. Ich würde das Programm gerne verstehen wollen. MFG
Karl Heinz schrieb: > Wenn während der 5 Sekunden der Taster erneut betätigt wird, kann es > sein, dass beide Karten angesteuert werden. > > Obwohl: der TO hat ja nicht verraten, was in diesem Fall die korrekte > Reaktion wäre. > Genauso wie er nicht verraten hat, ab wann die Zeit laufen soll. Ab > niederdrücken oder ab loslassen. Kann man durch gedrückt halten des > Tasters die 5 Sekunden verlängern oder nicht? Das Ansteuern beider Karten gleichzeitig, würde in meinem fall keinen Fehler und Fehlfunktion in meiner Schaltung hervorrufen. Beim Auslösen des Schalters wäre eine steigende Flanke besser. MFG
:
Bearbeitet durch User
Hi Steffen E. schrieb: > Beim Auslösen des Schalters wäre eine steigende Flanke besser. In der Regel ist ein Eingang mit einem internen Pullup Widerstand verschaltet. Das bedeutet für deine Schaltung, wenn du keinen externen PullDown verwenden willst, das dein Schalter/ Taster genau anders herum schaltet. Also, eine steigende Flanke bekommst du dann beim Loslassen. Gruß oldmax
Steffen E. schrieb: > Vielen dank! Könntest du eventuell die einzelnen Programmzeilen mal ein > wenig erklären, Das würde bedeuten, das Tutorial hier genau noch einmal hinzuschreiben. > mein gewünschter Ablauf entsteht ? Ich kann aus dem Programm nämlich > nicht genau die Zusammenhänge untereinander deuten. Ich würde das > Programm gerne verstehen wollen. Dann bleibt dir nichts anderes übrig als die Dinge zu lernen. Hier wird dir keiner eine 12 Seiten Abhandlung schreiben, die alles im Detail erläutert. Arbeite das Tutorial durch, mach Übungen zu den einzelnen Themenkreisen. Das ist der Weg, wie man Dinge lernt. Schriftsteller zu werden lernt man auch nicht dadurch, dass einem ein anderer Schriftsteller seinen Roman Wort für Wort auseinanderklaubt. Ganz wichtig ist: Das Tutorial nur zu lesen ist zu wenig. Das ist wie beim Radfahren. Du kannst hunderte Bücher über radfahren lesen. Solange du dich nicht selbst in den Sattel setzt, wirst du dich nicht auf dem Rad halten können. Soviel kann man aber sagen: zentrales Element ist ein Timer, der durch seine Einstellung einen regelmässigen Basistakt (und damit eine definierte Zeitreferenz) erzeugt. In genau diesem Takt wird die ISR aufgerufen. Der Rest ist dann nur noch: Wenn ich 5 Sekunden benötige, und eine 'Uhr' zur Verfügung habe, die mir jede zb Zehntelsekunde einen Beep gibt, dann muss ich 50 Beeps abzählen, bis 5 Sekunden beisammen sind. Die ISR ist so eingestellt, dass sie jede 1 Millisekunde feuert, also muss ich 5000 derartige 'Feuerungen' abzählen (entweder von 0 bis 5000, oder von 5000 runter bis 0) um eine Zeit von 5 Sekunden abzumessen. zusätzlich zum Tutorial: FAQ: Timer Aber Timer ist schon etwas für fortgeschrittene Anfänger, auch wenn kaum ein Programm ohne sie auskommt. Mit einem Timer umgehen muss man können, weil sie praktisch überall vorkommen. Nur ist das (noch) kein Thema, wenn man bei 0 einsteigt. Da müssen zuerst andere Dinge verstanden worden sein.
:
Bearbeitet durch User
Karl Heinz schrieb: > Wenn während der 5 Sekunden der Taster erneut betätigt wird, kann es > sein, dass beide Karten angesteuert werden. Ja das stimmt, das kann man ja aber abfangen wenn man will indem man einfach die Tasterabfrage blockiert so lange noch eine Karte aktiv is.
1 | if (!(PINB & (1<<TASTER)) && !debounce && !OnTime){ |
2 | ...
|
3 | }
|
Hi Karl Heinz schrieb: > Dann bleibt dir nichts anderes übrig als die Dinge zu lernen. Hier wird > dir keiner eine 12 Seiten Abhandlung schreiben, die alles im Detail > erläutert. Doch Karl Heinz. Im von mir angesprochenem Beitrag der AVR-Praxis Gemeinde hab ich das mal gemacht. Nur lesen muss das jeder, der sich dafür interessiert, schon selber. Und jetzt noch mal einzelne Auszüge davon mundgerecht zu präsentieren, dazu hab ich natürlich keine Lust. Gruß oldmax
oldmax schrieb: >> Dann bleibt dir nichts anderes übrig als die Dinge zu lernen. Hier wird >> dir keiner eine 12 Seiten Abhandlung schreiben, die alles im Detail >> erläutert. oldmax schrieb: > Doch Karl Heinz. Im von mir angesprochenem Beitrag der AVR-Praxis > Gemeinde hab ich das mal gemacht. Ich glaube Karl-Heinz meint, dass sich jetzt niemand hinsetzt und mein kleines Programm beschreibt! Ich hätte natürlich jede Zeile kommentieren können, aber da war ich zu faul zu...
Ingo Less schrieb: > Ich hätte natürlich jede Zeile kommentieren können, aber da war ich zu > faul zu... Das ist auch nicht sinnvoll. Denn Dinge wie * Wie wird ein Bit gesetzt * Wie wird es gelöscht" * Wie fragt man einen Eingang ab die müssen einfach im Schlaf sitzen, ehe man überhaupt daran denken kann, ein Real-World Programm zu schreiben. Damit ist aber noch lange nicht die Logik, die Idee die im Programm steckt, beschrieben. Die Idee hab ich versucht kurz zu skizzieren. Damit und mit ein wenig spielen mit Papier und Bleistift und verfolgen wie sich die einzelnen Werte ändern, sollte es eigentlich möglich sein, zu verfolgen wie sich daraus die gewünschte Funktionalität ergibt. Rein durch hinsehen wird ein Anfänger die einzelnen Bestandteile und welche Idee sie verkörpern nicht identifizieren, das ist mir schon klar. Aber der beste Weg ist immer noch, sich da durchzu'quälen', auch wenn das jetzt hart klingt. Hilft aber nichts, da musste jeder mal durch. Und mit der Zeit wird man ja auch besser, weil man Dinge, bestimmte Konstrukte, wiedererkennt. Ist wie beim Schachspielen. Die Regeln sind schnell erklärt, aber in einem realen Schachspiel steckt mehr als nur die Anwendung der Regeln. Als Anfänger kannst du einem Hr. Pfleger stundenlang zu hören, du wirst trotzdem nicht verstehen wovon er da redet, bzw. wie er darauf kommt. Erst nach einiger Spielpraxis erschliesst sich vieles davon.
:
Bearbeitet durch User
Karl Heinz schrieb: > Das ist auch nicht sinnvoll. Macht meiner Meinung hier auch keinen Sinn, da das Programm genau das verkörpert, was er wollte. Somit hat er seine Programmbeschreibung selber geschrieben. Nur das "Wo passiert was" muss er sich halt selber raus suchen. Ich denke aber, dass ist bei den paar Zeilen kein Ding der Unmöglichkeit.
Ich hab da grad mal Bock drauf: // Ich auch, Dank an Ingo Less
1 | // Aus der C Bibliothek Funktionsdateien laden
|
2 | #include <avr/io.h> |
3 | #include <avr/interrupt.h> |
4 | |
5 | // Definition welcher Portpin zu welchen Anschluss gehören soll.
|
6 | #define KARTE1 PB0
|
7 | #define KARTE2 PB1
|
8 | #define TASTER PB2
|
9 | |
10 | |
11 | // C Programm Hauptschleife
|
12 | int main(void) |
13 | {
|
14 | // Timer Inbetriebsetzen hier auf 1khz stellen Wenn abgelaufen löst der Timer einen Interrupt aus.
|
15 | TCCR0A |= (1<<WGM00) | (1<<WGM01); // CTC |
16 | OCR0A = 149; // 9,6MHz / ((149+1) * 64) = 1KHz //Vergleichsregister |
17 | TIMSK0 |= (1<<OCIE0A); // Capture Interrupt Vergleichsinterrupt einschalten |
18 | TCCR0B |= (1<<CS00) | (1<<CS01); // Prescaler 64 Vorteiler des Timers siehe Datenblatt vom Tiny |
19 | |
20 | // IOs Ein und Ausgänge vorbereiten
|
21 | PORTB = 0; //Portausgänge alle auf 0 setzen |
22 | DDRB |= (1<<KARTE1) | (1<<KARTE2); // 2 Portpinne als Ausgänge machen |
23 | PORTB |= (1<<TASTER); // Pull-up enable Der Eingangspin mit einem Pullup Widerstand beschalten. |
24 | |
25 | // global Interrupt enable Freigabe der Interrupt Funktion allgemein
|
26 | sei(); |
27 | |
28 | |
29 | while(1){; // Hauptschleife ist fertig Mach nichts mehr. Das Programm lebt jetzt nur noch vom Interrupt |
30 | //Nothing to Do
|
31 | }
|
32 | }
|
33 | |
34 | /* 1kHz */
|
35 | // Programmteil das bei einer Interrupt Auslösung abarbeitet wird.
|
36 | ISR (TIM0_COMPA_vect) |
37 | {
|
38 | static uint16_t debounce = 0; // Variable debounce deklarieren 16bit ohne Vorzeichen und wird auf 0 gesetzt |
39 | static uint16_t OnTime = 5000;// Variable OnTime 16bit ohne Vorzeichen wird auf 5000 gesetzt. |
40 | static uint8_t Kartenwahl = 0;// Variable Kartenwahl 8bit ohne Vorzeichen wird auf 0 gesetzt. |
41 | |
42 | if (debounce) debounce--; |
43 | |
44 | if (!(PINB & (1<<TASTER)) && !debounce){ // Tasterabfrage wenn Eingangspin auf 1 ist dann |
45 | debounce = 100;// Variable debounce auf 100 stellen |
46 | OnTime = 5000;// OnTime auf 5000 stellen |
47 | Kartenwahl++;// Zähler Kartenwahl um 1 addieren (Increment) |
48 | }
|
49 | |
50 | if (OnTime){// Wenn ONTime abgelaufen? (Bin selber Anfänger) |
51 | switch (Kartenwahl%2){// switchanweisung siehe Grundlagen |
52 | case 0: PORTB |= (1<<KARTE1); break;// Wenn Kartenwahl 0 ist dann Portausgang für Karte1 setzen |
53 | case 1: PORTB |= (1<<KARTE2); break;// Wenn Kartenwahl 1 ist dann Portausgang für Karte2 setzen |
54 | default: break;// Breakanweiseung auch hier bitte die switch Grundlagen lesen |
55 | }else{ // Falls weder 0 noch 1 ist dann Portausgänge der beiden Karten auf 0 setzen |
56 | PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) ); |
57 | }
|
58 | }
|
Viel Spass damit // auch von mir Ich schliesse mich meinen Vorschreibern an, bitte die Grundlagen durchackern. Hier gab es ja schon viele Links Gruß Greg
Greg schrieb: > if (OnTime){// Wenn ONTime abgelaufen? (Bin selber Anfänger)
1 | if (debounce) debounce--; // Taster mit 100ms Entprellen |
2 | |
3 | if (OnTime){// Während OnTime Karten schalten |
4 | ...
|
5 | }else{ // Falls OnTime abgelaufen, alle Karten deaktivieren |
6 | PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) ); |
7 | }
|
:
Bearbeitet durch User
Greg schrieb: > debounce = 100;// Variable debounce auf 100 stellen Ganau diese Art von Kommentar hilft garnicht. Hier hätte es heißen müssen "Entprellzeit 100ms".
Ingo Less schrieb: > Ganau diese Art von Kommentar hilft garnicht. Ja. Und wenn, dann sollte er wenigstens richtig sein: Greg schrieb:
1 | IMSK0 |= (1<<OCIE0A); // Capture Interrupt Vergleichsinterrupt einschalten |
mfg.
Moin Leute, das Programm läuft wie es oben geschrieben wurde nicht wirklich. Ausgangskarte 1 läuft immer dauerhaft und Ausgangskarte 2 geht an wenn man den Taster drückt und wenn man Ihn 5 Sekunden hält und wieder los lässt, geht Ausgangskarte 2 wieder aus aber auch nur dann.
:
Bearbeitet durch User
Steffen E. schrieb: > Moin Leute, > das Programm läuft wie es oben geschrieben wurde nicht wirklich. Welche Version? Hast du auch die nachträglichen Änderungen noch eingepflegt? Zum Rest: Eigentlich ist das Programm so einfach, dass man auch einem Anfänger zumuten kann zu analysieren, wie das ganze arbeitet. Dreh und Angelpunkt ist die Erkentnis, dass die ISR-Funktion jede 1 Millisekunde aufgerufen wird. Das funktioniert also wie ein Wecker, der alle x Zeiteinheiten läutet. Der Benutzer wacht auf, sieht sich um, entscheidet was er zu tun hat (anhand seiner Umgebung) und macht die entsprechenden Aktionen. Mit dieser Vorgabe, einem Blatt Papier und Bleistift sollte es eigentlich nicht mehr schwer sein, die Funktionalität nachvollziehen zu können, bzw. zu ergründen, warum etwas nicht funktioniert.
Ingo Less schrieb: > Greg schrieb: >> debounce = 100;// Variable debounce auf 100 stellen > Ganau diese Art von Kommentar hilft garnicht. > Hier hätte es heißen müssen "Entprellzeit 100ms". Und um das klar zu stellen: Das ist nur ein willkürlich herausgegriffenes Beispiel für sinnlose Kommentierung. Der Rest der Kommentierung (die nicht von Ingo stammen) ist vom genau gleichen Kaliber: sinnlos Sorry Greg. Aber du hast dir eine Menge Arbeit für nichts gemacht.
:
Bearbeitet durch User
Steffen E. schrieb: > das Programm läuft wie es oben geschrieben wurde nicht wirklich. > Ausgangskarte 1 läuft immer dauerhaft und Ausgangskarte 2 geht an wenn > man den Taster drückt und wenn man Ihn 5 Sekunden hält und wieder los > lässt, geht Ausgangskarte 2 wieder aus aber auch nur dann. Wie hast du deinen Taster angebunden? Wenn du alle Nachträge ins Programm eingepflegt hast, dann sollte es funktionieren. Sofern der Taster richtig angeschlossen ist. Aber wie K.-H. schon schrieb. Das Programm ist überschaubar einfach. Es soll dich ja auch dazu ermuntern es zu verstehen. Copy&Paste funktioniert meist eh nicht auf Anhieb.
Da ich hier einen Internen Pull-up Widerstand benutze, ist von PB2 auf den Taster und von dort auf 0V angeschlossen. ich habe das Decrement noch eingefügt, bin mir aber auch nicht sicher ob das an der richtigen Stelle war. Sonst habe ich nichts mehr eingepflegt.
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #define KARTE1 PB0
|
5 | #define KARTE2 PB1
|
6 | #define TASTER PB2
|
7 | |
8 | |
9 | |
10 | int main(void) |
11 | {
|
12 | // Timer
|
13 | TCCR0A |= (1<<WGM00) | (1<<WGM01); // CTC |
14 | OCR0A = 149; // 9,6MHz / ((149+1) * 64) = 1KHz |
15 | TIMSK0 |= (1<<OCIE0A); // Capture Interrupt |
16 | TCCR0B |= (1<<CS00) | (1<<CS01); // Prescaler 64 |
17 | |
18 | // IOs
|
19 | PORTB = 0; |
20 | DDRB |= (1<<KARTE1) | (1<<KARTE2); |
21 | PORTB |= (1<<TASTER); // Pull-up enable |
22 | |
23 | // global Interrupt enable
|
24 | sei(); |
25 | |
26 | |
27 | while(1){ |
28 | //Nothing to Do
|
29 | }
|
30 | }
|
31 | |
32 | /* 1kHz */
|
33 | ISR (TIM0_COMPA_vect) |
34 | {
|
35 | static uint16_t debounce = 0; |
36 | static uint16_t OnTime = 5000; |
37 | static uint8_t Kartenwahl = 0; |
38 | |
39 | if (debounce) debounce--; |
40 | |
41 | |
42 | if (!(PINB & (1<<TASTER)) && !debounce){ |
43 | debounce = 100; |
44 | OnTime = 5000; |
45 | Kartenwahl++; |
46 | }
|
47 | if (OnTime) OnTime--; |
48 | |
49 | if (OnTime){ |
50 | switch (Kartenwahl%2){ |
51 | case 0: PORTB |= (1<<KARTE1); break; |
52 | case 1: PORTB |= (1<<KARTE2); break; |
53 | default: break; |
54 | }}else{ |
55 | PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) ); |
56 | }
|
57 | }
|
:
Bearbeitet durch User
Hast du eigentlich an den Fuses des AtTiny rumgemacht? Denn wenn du da nichts getan hast, dann stimmt die Zeitberechnung im Programm nicht. Der Timer ist so eingerichtet, dass die Zeiten bei 9.6Mhz Taktfrequenz stimmen. Hast du an den Fuses nichts gemacht, dann läuft der Tiny aber nicht mit 9.6Mhz sondern mit 1.2Mhz. Also Folge davon sind alle Zeiten real dann 8 mal so lang. Aus deinen 5 Sekunden werden ca. 40 Sekunden. Und die können laaaang sein, wenn man vor einem Gerät sitzt und darauf wartet, dass etwas passiert. Ich hätte hier
1 | switch (Kartenwahl%2) { |
2 | case 0: PORTB |= (1<<KARTE1); |
3 | PORTB &= ~(1<<KARTE2); |
4 | break; |
5 | |
6 | case 1: PORTB |= (1<<KARTE2); |
7 | PORTB &= ~(1<<KARTE1); |
8 | break; |
9 | |
10 | default: break; |
11 | }
|
ja dafür gesorgt, dass die Ausgänge mit Sicherheit immer wechselseitig geschaltet sind.
:
Bearbeitet durch User
Karl Heinz schrieb: > ja dafür gesorgt, dass die Ausgänge mit Sicherheit immer wechselseitig > geschaltet sind. Ja, auch sinnvoll... Das kommt davon wenn man solch ein Progrämmchen mit heißer Nadel schreibt. :)
Karl Heinz schrieb: > Hast du an den Fuses nichts gemacht, dann > läuft der Tiny aber nicht mit 9.6Mhz sondern mit 1.2Mhz. Wenn es nur um die CKDIV8-Fuse geht, bevor das im Übereifer fehlschlägt:
1 | #include <avr/power.h> |
2 | |
3 | int main(void) |
4 | {
|
5 | clock_prescale_set(clock_div_1); |
6 | .
|
7 | .
|
8 | .
|
mfg.
Thomas Eckmann schrieb: > Wenn es nur um die CKDIV8-Fuse geht, bevor das im Übereifer fehlschlägt: > #include <avr/power.h> > > int main(void) > { > clock_prescale_set(clock_div_1); > . > . > . > > mfg. Ich habe das noch nie verwendet. Wie genau ist das?
F. Fo schrieb: > Ich habe das noch nie verwendet. Wie genau ist das? 100%. Damit stellt man den Clock Prescaler ein. Mit dieser Funktion lässt sich der Takt auf 1, 1/2, 1/4 und 1/8 einstellen. Unabhängig von der Fuse-Voreinstellung. Das ist alles auch nichts Neues und setzt lediglich ein paar Bits im CLKPR. Dieses Register muss aber in einer Timed Sequence beschrieben werden, ähnlich dem Watchdog. Das Timing nimmt einem die Funktion ab. Die berühmt-berüchtigte Fuse macht lediglich die Startvorgabe auf 1/8 oder 1. Also nicht "festverdrahtet" wie die Einstellung der Taktquelle. mfg.
:
Bearbeitet durch User
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.