Ich habe bereits in anderen Forenbeiträge gesucht, jedoch nichts passendes gefunden. Um einen kleinen DC-Motor 3V 200mA über einen Taster zu steuern würde ich gerne einen ATtiny 45 gebrauchen. Mit dem Taster sollen drei verschiedene Geschwindigkeiten eingestellt werden können. Quasi: tasten--> Stufe 1; nochmal tasten---> Stufe 2; nochmal tasten-->Stufe 3 Ich bin auf dem Gebiet noch recht neu. Einen Atmega 32 hab ich schon geflasht und in C hab ich Grundkenntnisse. Ein STK500 hab ich auch. Die Drehzahlregelung kann man über PWM und Mosfet machen oder? Wichtig wäre mir auch, dass der Attiny sehr wenig Stom verbraucht im Leerlauf. Da die Schaltung über längere Zeit nicht benutzt wird und nur gelegentlich gebraucht wird. Gibt es eine Art Sleepmodus beim ATiny? Kann man das so programmieren, dass sich der Atiny nach einer gewissen Zeit nachdem es keinen Tasterschluss gab sich in den Sleepmodus schickt. Die Steuerung soll im Gesamten über einen Taster funktionieren also auch das Aufwecken des ATiny. Ich wäre sehr froh wenn mir jemand helfen könnte. Viele Grüsse Horst
Horst H. schrieb: > Ich habe bereits in anderen Forenbeiträge gesucht, jedoch nichts > passendes gefunden. Klar... > Die Drehzahlregelung kann man über PWM und Mosfet machen oder? Ja. Falls der Motor nur in eine Richtung laufen soll, reicht ein Mosfet. Ansonsten würde ich einen Motortreiber (L293D oder neuere Generationen) nehmen. > Wichtig wäre mir auch, dass der Attiny sehr wenig Stom verbraucht im > Leerlauf. Da die Schaltung über längere Zeit nicht benutzt wird und nur > gelegentlich gebraucht wird. Gibt es eine Art Sleepmodus beim ATiny? Ja, bitte schau ins Datenblatt. Steht da alles drin. Es gibt verschiedene Stromsparmodi, jeder hat andere Eigenschaften und andere Aufweckquellen. > Kann man das so programmieren, dass sich der Atiny nach einer gewissen > Zeit nachdem es keinen Tasterschluss gab sich in den Sleepmodus schickt. > Die Steuerung soll im Gesamten über einen Taster funktionieren also auch > das Aufwecken des ATiny. Ja klar. > Ich wäre sehr froh wenn mir jemand helfen könnte. Was für eine Art Hilfe stellst du dir hier vor? gruß cyblord
Das Ein-Ausschalten mit Tiny45 kannst Du hier sehen. Beitrag "EIN-AUS mit Taster per Interrupt, ATtiny25 o.ä." Es wird auch schon ein PWM-Signal an PB0 erzeugt. Die Ladungspumpe wird nicht benötigt, sondern ein passender N-Kanal MOSFET, der den Motor gegen GND einschaltet. Aber das Programm muß so modifiziert werden, dass das PWM-Signal bei jedem Tastendruck erhöht wird (OCR0A) und am Ende auf 0 gesetzt wird. Ist PWM auf 0, kann der Tiny wieder 'eingeschläfert' werden. Am einfachsten kann das in main() in der Schleife while1() erledigt werden, denn jeder erneute Tastendruck setzt die Variable 'abschalten' auf '1'.
Schrittweise vorgehen! Die Sache mit dem Sleep legst du erst mal auf Eis. Die brauchst du nicht sofort. Wenn du mit Motoren noch nicht so fit bist, dann nimm als erstes Ausgabeelement erst mal eine LED. Die ist einfach anzusteuern und auch vom Programm her kein Problem. PWM brauchst du da erst mal auch noch nicht. Denn: Du brauchst ein einfaches Ausgabeelement um dir erst mal eine 'Anzeigemöglichkeit' für dein erstes Teilziel zu schaffen: Tasten einlesen, entprellen und auswerten. Das ist dein erstes Teilziel, das du angehst: Die Tastendrücke erkennen. Und zwar nicht einfach irgendwie erkennen, sondern * als Tastendruck * und auch noch entprellt. Entprellung und mit dieser Tastenentprellung schaltest du erst mal nur die LED ein/aus. Hast du dieses Teilziel erreicht, dann kommt der nächste Schritt. Anstatt die popelige LED einfach nur ein/aus zu schalten, möchtest du sie dimmen (was im Prinzip den unterschiedlichen Drehzahlen deines Motors entspricht). Zum Dimmen nimmst du eine PWM her. Die probierst du erst mal ohne Tasten aus. D.h. du nimmst die PWM in Betrieb und mit der LED kontrollierst du, ob das so funktioniert, wie es sein soll. Durch Verändern der PWM (Konstante im Programm durch eine anderen Zahlenwert austauschen) siehst du nach, ob du tatsächlich unterschiedliche Helligkeiten der LED erreichen kannst. FAQ: Timer Ist das dann soweit erledigt, kannst du die Helligkeit durch Verändern der LED verstellen, dann werden die bisherigen beiden Teilziele zusammengeführt. Du möchtest mittels Tastendruck die LED durch eine Abfolge von Helligkeiten durchschalten. (Jetzt näherst du dich bereits deinem endgültigen Programm-Ziel). D.h. jetzt ist die Logik gefragt, wie Tastendrücke ausgewertet werden und so in Veränderungen der PWM umgesetzt werden, so dass die LED bei Tastendruck die jeweils nächste Helligekeit annnimmt. Jetzt ist es dann auch an der Zeit, die LED durch einen Motor zu ersetzen. Dazu brauchst du einen Motortreiber, denn der µC kann ja den Motorstrom/Spannung nicht liefern. D.h. es wird langsam Zeit diese Hardware aufzubauen und in Betrieb zu nehmen. In deinem Programm werden sich die konkreten Zahlenwerte für die PWM ein wenig verändern aber das ist das kleinere Problem. Dank guter Vorbereitung mit der LED hast du ja ein Programm, welches im Prinzip schon das gewünschte leistet. Wenn da jetzt also noch Probleme auftauchen, dann können die nur noch im Bereich Motortreiber bzw. dessen Ansteuerung liegen. Und dann, ganz zum Schluss kümmerst du dich um den Sleep-Modus und wie man den µC aus diesem rauskriegt bzw. um die Logik, wann sich der µC wieder schlafen legt. Eventuell musst du dazu deinen Taster nochmal an einen anderen µC-Pin legen, mit dem es dir gelingt den Sleep zu beenden. Tja, und so wie ich das sehe, bist du dann auch 'schon' fertig. Das wichtige: Arbeite in Schritten! Setz dir Teilziele! Teilziele, die du erreichen kannst ohne allzuviel Neues im System zu haben. Nach Möglichkeit willst du im nächsten Teilziel immer nur eine neue Komponente haben um die du dich kümmern musst. Also nicht alles auf einmal und keine AHnung haben, wo man anfängt, sondern bei den einfachen Dingen anfangen und dann sukzessive in kleinen Schritten in Richtung Ziel gehen, wobei durchaus auch mal ein kleiner Umweg (wie hier die LED) erlaubt bzw. sinnvoll ist, wenn sich dadurch das zu testende System zwischendurch extrem vereinfacht. Eine LED kann man einfach (mit Vorwiderstand) anhängen - ein Motor bringt schon wieder seine eigenen Probleme (wie zb Ströme) mit. Also sucht man für den Motor erst mal einen Ersatz, so dass man die programmiertechnische Seite trotzdem in Angriff nehmen kann OHNE dass einem die Hardware da sofort in die Suppe spuckt.
m.n. schrieb: > Das Ein-Ausschalten mit Tiny45 kannst Du hier sehen. > Beitrag "EIN-AUS mit Taster per Interrupt, ATtiny25 o.ä." Kein guter Artikel. Tasten mittels RC zu entprellen ist unnötig kompliziert. Aber auch das wurde im Artikel schon angesprochen.
An dieser Stelle mal ein dickes Lob an Karl Heinz! Finde es immer wieder schön zu sehen wie viel Mühe du dir gibst und wie gut verständlich und hilfreich deine oft ausführlichen Antworten sind. :)
Karl Heinz Buchegger schrieb: > Tasten mittels RC zu entprellen ist unnötig kompliziert. > Aber auch das wurde im Artikel schon angesprochen. Na gut, dann hast Du es auch nicht verstanden :-) @Horst Einen Abschnitt weiter beim obigen Link findest Du das Programm 'toggle_25.c'. Da ist die Ein-Ausschaltfunktion übersichtlicher. Diese könntest Du als Basis nehmen und die PWM-Stufen hinzufügen.
> dass sich der Atiny nach einer gewissen Zeit nachdem es keinen > Tasterschluss gab sich in den Sleepmodus schickt. Du weisst also schon, daß er schlafen muss, allerdings nicht wenn kein Tatendruck kam, sondern wenn der Motor nicht läuft. Aus dem sleep-Beispiel http://www.mikrocontroller.net/articles/Sleep_Mode zusammengestrichen, Fuses und Erklärungen siehe dort
1 | #define F_CPU 1000000
|
2 | #include <avr/io.h> |
3 | #include <avr/sleep.h> |
4 | #include <avr/interrupt.h> |
5 | #include <util/delay.h> |
6 | ISR(INT0_vect) { } |
7 | void long_delay(uint16_t ms) { while(ms-->0) _delay_ms(1); } |
8 | uint8_t mode; // 0=Motor aus, sleep, 1..3=Motor PWM |
9 | uint8_t taste,gedrueckt; |
10 | int main(void) |
11 | {
|
12 | DDRD=0x01; // PD0 = Motor, PD2 = INT0 = Eingang |
13 | PORTD=0x04; // Pull Up aktivieren, Motor aus |
14 | ACSR=0x80; MCUCR&=~0x3; |
15 | sei(); |
16 | while(1) |
17 | {
|
18 | GICR|=(1<<INT0); |
19 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); |
20 | sleep_mode(); |
21 | // hier wachen wir wieder auf wenn Taste gedrückt
|
22 | gedrueckt=0; // auf jeden Fall Tastendruck |
23 | GICR&=~(1<<INT0); |
24 | do // 30ms Schleife, Motor-PWM und Tastenentprellung |
25 | {
|
26 | taste=!(PORTB&1); // aktuellen Tastenzustand |
27 | if(taste&&!gedrueckt) mode=(mode+1)&3; |
28 | gedrueckt=taste; // entprellen |
29 | PORTB|=1; // MOTOR PWM an |
30 | long_delay(30-10*(3-mode)); |
31 | PORTB&=0xFE; // Motor PWM aus |
32 | long_delay(10*mode); |
33 | }
|
34 | while(mode||gedrueckt); |
35 | // fall asleep again
|
36 | }
|
37 | }
|
Es ist also nicht so schwer, ein Transistor an PD0 schaltet den Motor 5V -+--(M)--+ Motor | | +--|<|--+ BA157 | PD0--220R--|< BC337 |E GND
Meinen obigen Vorschlag habe ich spaßhalber umgesetzt und an den betreffenden Artikel angehängt. Beitrag "Re: EIN-AUS mit Taster per Interrupt, ATtiny25 o.ä."
Vielen Vielen Dank, das hat mir sehr geholfen. Ich setze mich diese Wochenende mal dran und geb mein bestes. Bis Später
Mercie Leute, es läuft, ein Traum. Vielen Dank. Besonderen Dank an m.n. Bei jedem Tastendruck wird der nächste Wert aus der tabelle genommen: uint8_t pwm_tabelle[] = {100, 160, 255}0; Jetzt würde ich gern einen einen Modus erzeugen indem ein PWM-Signal fadenkann. also quasi: uint8_t pwm_tabelle[] = {100,160,255, faden}0; Sprich die LED soll heller werden, dann wieder dunkler und das in einer Schleife. int a = 255; //höchster Wert while(1){ while(a>100){ OCR1A = a; _delay_ms(10); a--; } while(a<255){ OCR1A = a; _delay_ms(10); a++; } Wie kann ich das jetzt in eine Methode packen, die ich in die Tabelle schreiben kann? Vielen Dank Mein Code ist der von m.n.
1 | /*
|
2 | Dieses Programm erzeugt mit einem ATtiny25/45/85 ein PWM-Signal an PB0.
|
3 | Ein einziger Taster schaltet den Prozessor ein und nimmt den 1. Wert aus der
|
4 | PWM-Tabelle für das Tastverhältnis. Weitere Tastendrücke nehmen den nächsten Wert aus
|
5 | der Tabelle, bis das Ende erreicht ist. Abschließend wird der Prozessor wieder in den
|
6 | Power-Don-Modus gelegt.
|
7 | |
8 | zur Funktion:
|
9 | Nach dem Anlegen der Versorgungsspannung geht der µC nach ein
|
10 | paar Befehlen zur Initialisierung in den Power-Down-Modus mit einer Stromaufnahme
|
11 | von <1µA und wartet auf einen Interrupt, der ihn aufweckt.
|
12 | |
13 | Wird beim Drücken des Tasters die Schaltschwelle von PB4 zum Erkennen eines '0'-Pegels überschritten,
|
14 | wird der PinChange-Interrupt ausgelöst. Der Kondensator wird in der PCINT-Routine
|
15 | beschleunigt entladen, bis er GND Potential erreicht hat. Dadurch wird die Eingangshysterese auf
|
16 | nahezu Vcc erhöht. 'taste_gedrueckt' wird zur Auswertung in main() auf 1 gesetzt.
|
17 | |
18 | Das Loslassen des Tasters wird nicht ausgewertet. Lediglich der Kondensator am Eingang
|
19 | wird aktiv auf '1' Pegel gebracht.
|
20 | |
21 | http://www.mino-elektronik.de
|
22 | |
23 | Alle Angaben ohne Gewaehr !
|
24 | 2013-10-01
|
25 | */
|
26 | |
27 | #include <avr/io.h> |
28 | #include <avr/interrupt.h> |
29 | #include <avr/sleep.h> |
30 | |
31 | #define BIT(x) (1<<x)
|
32 | #define EIN_AUS_TASTER 4 // PortB 4
|
33 | #define EIN_AUS_SIGNAL 3 // PortB 3 (ggf. mit LED)
|
34 | #define PWM_OUT 0 // PortB 0
|
35 | |
36 | uint8_t pwm_tabelle[] = {100, 160, 255}0; // beliebige PWM-Werte |
37 | #define MAX_PWM_INDEX (sizeof(pwm_tabelle)/sizeof(pwm_tabelle[0]))
|
38 | |
39 | volatile uint8_t taste_gedrueckt; |
40 | uint8_t pwm_index, abschalten; |
41 | |
42 | // Interrupt vom Ein-Aus-Taster. Beim Schliessen des Tasters wird 'taste_gedrueckt' gesetzt.
|
43 | ISR (PCINT0_vect) |
44 | {
|
45 | volatile uint8_t n = 0xff; // darf nicht wegoptimiert werden |
46 | PCMSK &= ~BIT(EIN_AUS_TASTER); // sperren |
47 | if(PINB & BIT(EIN_AUS_TASTER)) { // steigende flanke |
48 | PORTB |= BIT(EIN_AUS_TASTER); |
49 | DDRB |= BIT(EIN_AUS_TASTER); // und Ausgang aktiv auf 1 |
50 | } else { |
51 | taste_gedrueckt = 1; // bei jedem Tastendruck setzen |
52 | PORTB &= ~BIT(EIN_AUS_TASTER); |
53 | DDRB |= BIT(EIN_AUS_TASTER); // und Ausgang aktiv auf 0 |
54 | }
|
55 | while(n--); // kurz warten bis kondensator aufge- oder entladen |
56 | PORTB |= BIT(EIN_AUS_TASTER); // pullup immer aktiv |
57 | DDRB &= ~BIT(EIN_AUS_TASTER); // und auf Eingangschalten |
58 | GIFR = 0x20; // ggf. Störungen ausfiltern, flag löschen |
59 | PCMSK |= BIT(EIN_AUS_TASTER); // zulassen |
60 | }
|
61 | |
62 | void schreibe_pwm_wert(uint8_t wert) |
63 | {
|
64 | OCR0A = wert; // aktuellen Wert setzen |
65 | if(wert) { // PWM aktivieren, wenn wert != 0 |
66 | TCCR0B = 0x02; // 8 Vorteiler |
67 | TCCR0A = BIT(COM0A1) + BIT(WGM01) + BIT(WGM00); // Fast PWM einschalten |
68 | PORTB &= ~BIT(EIN_AUS_SIGNAL); // Ausgang (LED) auf '0' = aktiv ! |
69 | } else { // sonst PWM abschalten |
70 | TCCR0B = 0x00; // Timer0 abschalten |
71 | TCCR0A &= ~(BIT(COM0A1) + BIT(WGM01) + BIT(WGM00)); // Fast PWM abschalten |
72 | PORTB &= ~BIT(PWM_OUT); // Ausgang auf '0' |
73 | PORTB |= BIT(EIN_AUS_SIGNAL); // Ausgang (LED) auf '1' = passiv ! |
74 | }
|
75 | }
|
76 | |
77 | |
78 | int16_t main(void) // typ. RC-Osz. 8MHz mit Teiler/8 |
79 | {
|
80 | DDRB |= BIT(EIN_AUS_SIGNAL); // Schaltausgang (PB3) aktivieren |
81 | DDRB |= BIT(PWM_OUT); // immer als Ausgang |
82 | PORTB |= BIT(EIN_AUS_SIGNAL); // Schaltausgang (LED) passiv |
83 | PORTB |= BIT(EIN_AUS_TASTER); // interner Pullup für Taster |
84 | PCMSK |= BIT(EIN_AUS_TASTER); // PCINT für PB4 freigeben |
85 | GIFR = BIT(PCIF); // flag löschen |
86 | GIMSK |= BIT(PCIE); // PCINT PORTB zulassen |
87 | abschalten = 1; // nach Reset in den Schlafmodus gehen |
88 | sei(); |
89 | while(1) { |
90 | if(abschalten) { |
91 | schreibe_pwm_wert(0); // PWM-Signal abschalten |
92 | abschalten = 0; |
93 | pwm_index = 0; // beim Einschalten wieder mit 1.Stufe beginnen |
94 | while(!(PINB & BIT(EIN_AUS_TASTER))); // warten, solange Taste gedrueckt |
95 | MCUCR = BIT(SE) + BIT(SM1); // Power-Down wählen |
96 | sleep_cpu(); // und immer wieder schlafen legen |
97 | }
|
98 | if(taste_gedrueckt) { |
99 | taste_gedrueckt = 0; |
100 | if(pwm_index >= MAX_PWM_INDEX) { |
101 | abschalten = 1; |
102 | } else { |
103 | schreibe_pwm_wert(pwm_tabelle[pwm_index]); // neuen Wert schreiben |
104 | pwm_index++; |
105 | }
|
106 | }
|
107 | } // endlos Schleife |
108 | }
|
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.