Hallo zusammen,
jetzt habe ich schon den ganzen Tag dran gebastellt und bin nicht
wirklich weiter gekommen.
Mein ATmega48 soll mit einer Hardware-PWM 2 Servos ansteuern, was er
bisher auch macht. Nur ist der Servoweg etwa 10° oder 15° und keine
annähernden 180°
Keine Ahnung was ich falsch machen.
Der ATmega48 läuft mit 8MHz,
Timer1: 50Hz mit Prescaler 8,
Clear OC1A/OC1B on Compare Match
Wellenform 8, PWM phz correct, TOP= ICRn
1 | // ICC-AVR
| 2 | // Target : m48
| 3 | // Crystal: 8.0000Mhz
| 4 |
| 5 | #include <iom48v.h>
| 6 | #include "Taster.h"
| 7 |
| 8 | void port_init(void)
| 9 | {
| 10 | PORTB = 0xF1;
| 11 | DDRB = 0x0E;
| 12 | PORTC = 0x43;
| 13 | DDRC = 0xBC;
| 14 | PORTD = 0x00;
| 15 | DDRD = 0xFF;
| 16 | }
| 17 |
| 18 |
| 19 | //TIMER1 initialize - prescale:8
| 20 | // WGM: 10) PWM phz correct, TOP= ICRn
| 21 | // desired value: 50Hz
| 22 | // actual value: 50,000Hz (0,0%)
| 23 | void timer1_init(void)
| 24 | {
| 25 | TCCR1B = 0x00; // stop Timer
| 26 | ICR1 = 10000;// Obere Zählergrenze
| 27 | OCR1A = 1000; // Position erster Servo-Port
| 28 | OCR1B = 2000; // Position zweiter Servo-Port
| 29 | TCCR1A = (1<<COM1A1) | (1<<COM1B1); // Clear OC1A/OC1B on Compare Match
| 30 | TCCR1B = (1<<CS11) | (1<<WGM13); // prescaler 8, Waveform 8
| 31 | }
| 32 |
| 33 | void main(void)
| 34 | {
| 35 | //stop errant interrupts until set up
| 36 | CLI(); //disable all interrupts
| 37 | port_init();
| 38 |
| 39 | timer1_init();
| 40 |
| 41 | MCUCR = 0x00;
| 42 | EICRA = 0x00; //extended ext ints
| 43 | EIMSK = 0x00;
| 44 |
| 45 | TIMSK0 = 0x00; //timer 0 interrupt sources
| 46 | TIMSK1 = 0x00; //timer 1 interrupt sources
| 47 | TIMSK2 = 0x00; //timer 2 interrupt sources
| 48 |
| 49 | PCMSK0 = 0x00; //pin change mask 0
| 50 | PCMSK1 = 0x00; //pin change mask 1
| 51 | PCMSK2 = 0x00; //pin change mask 2
| 52 | PCICR = 0x00; //pin change enable
| 53 | PRR = 0x00; //power controller
| 54 | SEI(); //re-enable interrupts
| 55 | //all peripherals are now initialized
| 56 |
| 57 | while (1)
| 58 | {
| 59 |
| 60 | funkt_tast(); //Tasterfunktion wie im Tutorial
| 61 | if (taster == 2)
| 62 | { OCR1A = 1000;
| 63 | OCR1B = 2000;}
| 64 | else
| 65 | { OCR1A = 2000;
| 66 | OCR1B = 1000;
| 67 | }
| 68 | }
| 69 | }
|
Was mich auch störrt, aber momentan nebensächlich ist, wenn der Taster
gedrückt ist, brummt der Servo leise. Fast, als ob er gegen die endlage
fährt und weiter will. Aber an dieser Stelle ist die Endlage noch nicht
erreicht.
Ich hoffe, Ihr findet meinen Fehler.
So, ein bisschen weiter bin ich gekommen, obwohl es auch mit der
Wellenform8 funktionieren müsste.
Genau, ich habe die Wellenform mal auf 14. geändert.
1 | TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
| 2 | TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS11);
| 3 |
| 4 | ICR1 = 20000; //
| 5 | OCR1A = 1500;
| 6 | OCR1B = 1500;
|
Jetzt kann ich zumindest 80° den Servo drehen. Wenn ich nun noch die
Grenzen etwas vergrößere komme ich zumindest auf etwa 100°. 1 | OCR1B = 2230;
| 2 | OCR1B = 710;
|
Aber das kann ja eigentlich auch nicht sein, denn so würde das Signal
0,7ms bis 2,2ms lang sein, was zumindest nicht normal ist.
> Aber das kann ja eigentlich auch nicht sein, denn so würde das Signal
> 0,7ms bis 2,2ms lang sein, was zumindest nicht normal ist.
Doch, das kommt hin. Bei 1,0 bis 2,0 ms ist der Stellweg meist nur 90°
bis 120°. Da Servos keinen Schutz gegen "auf Anschlag fahren" haben,
solltest Du nicht versuchen, die Endlagen zu erreichen.
Meist braucht man auch nicht den vollen (mechanisch möglichen)
Drehwinkel. Denn meist wird mit dem Servo ein Gestänge bewegt, dessen
Geometrie bei Drehwinkeln von 60° bis 90° optimal ist.
...
Das ist aber ganzschön wenig.
Gibt es auch eine Möglichkeit, den vollen Weg auszunutzen, wenigstens
anneähernd 180°.
Und kann mir auch jemand sagen, was ich im ersten Fall falsch mache? Das
müsste doch genauso funktionieren?
Squat *** schrieb:
> Und kann mir auch jemand sagen, was ich im ersten Fall falsch mache?
Du schreibst nach ICR1, bevor der entsprechende Timer-Modus eingestellt
ist. ICR1 ist erst beschreibbar, nachdem ein Timer-Modus eingestellt
wurde, der ICR1 verwendet.
Das ich erst den Timer einstellen muss, und dann mit ICR1 die obere
Grenze festlege, hat leider nichts gebracht. Aber gut zu wissen, macht
ja auch Sinn. Aber wenn ich auch hier die Grenzen weiter verschiebe,
dann komme ich sogar zu einem besserem Ergebnis. 1 | OCR1B = 1200;
| 2 | OCR1B = 300;
|
Damit kann ich im ersten Fall fast den gesamten Weg des Servos
ausnutzen. Wenn ich nicht aufpasse, fährt dieser sogar gegen die
Endlagen.
Aber warum ist die Zeitspanne von 1-2ms so verschoben? Und warum ist
dies mit der zweiten Konstelation nicht möglich in die Enlage zu fahren?
> Aber warum ist die Zeitspanne von 1-2ms so verschoben? Und warum ist
> dies mit der zweiten Konstelation nicht möglich in die Enlage zu fahren?
Das kann ich Dir nicht sagen. Dies hier (auch Mega48) funktioniert
präzise:
http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html
...
@ Squat *** (squat)
Deine Einstellungen stimmen. Kann es sein, dass dein Takt nicht passt?
Sind wirklich 8 MHz RC-Oszillator eingestellt und auch die CLKDIV Fuse
NICHT aktiv?
Ausserdem ist dein Programm fehlerhaft! Was soll das cli() am Anfang?
VOllkommen unsinning. Aber viel schlimer, was soll das sei()! Ich sehe
KEINERLEI ISR?
Lass es weg! Die PWM läuft ohne ISR!
Und die ganzen Nullen brauchst du nicht in die Register schreiben, die
stehen nach dem Reset schon drin.
MFG
Falk
Ich habe bisher mit dem ICCAVR gearbeitet. Dieser hat die Einstellungen
so durchgeführt.
Zumindest das CLI();
Das auch noch anderen Register mit Nullen beschrieben werden, ist mir
erst heute wirklich klar geworden als ich Stück für Stück die
Hexadezimalen Zahlen umgebastelt habe.
Aber ich habe mir sowie so schon vorgenommen, auf GCC-AVR umzusteigen.
Da es frei zur Verfügung steht, bekomme ich eher Antworten auf meine
Fragen.
Das SEI(); steht schon richtig da. Ich habe mein Programm ganz schön
gekürtzt und auf das Wesentliche beschränkt, damit es nicht zu
kompliziert für mich und die anderen wird. Und andere Fehlerursachen
ausgeschlossen werden.
Ich finde mich jetzt wohl damit ab, hätte jedoch noch eine Frage zum
Schluss.
Wenn ich den Timer1 für die Hardware-PWM nutze, kann ich dann keinen
Interrupt damit ausführen lassen?
Zumindest funktioniert das bei mir nicht.
Wenn ich 1 | TIMSK1 = 0x00; //timer 1 interrupt sources
|
auf 1 | TIMSK1 = 0x01; //timer 1 interrupt sources
|
stelle, dann funktioniert der Servo nicht mehr, jedoch wird wie
gewünscht der Overflow und die damit verbundenen Befehle ausgeführt.
So sieht der Interrupt- Befehl aus. 1 | #pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
| 2 | void timer1_ovf_isr(void)
| 3 | {
| 4 | //TIMER1 has overflowed
| 5 | static unsigned int t1;
| 6 | TCNT1H = 0xB1; //reload counter high value
| 7 | TCNT1L = 0xE1; //reload counter low value
| 8 | if(t1) {t1=9; f_200ms=1;}
| 9 | else --t1;
| 10 | }
|
Dann schon mal vielen Dank an die fleißige Unterstüntzung.
@ Squat *** (squat)
>Das SEI(); steht schon richtig da. Ich habe mein Programm ganz schön
>gekürtzt und auf das Wesentliche beschränkt, damit es nicht zu
>kompliziert für mich und die anderen wird.
"Sehr sinnvoll"! Damit ja niemand deinen echten Code sieht und möglichst
nicht den Fehler findet. Lies mal was über Netiquette!!
> Und andere Fehlerursachen ausgeschlossen werden.
Wenn das mal kein Irrtum ist.
>Ich finde mich jetzt wohl damit ab, hätte jedoch noch eine Frage zum
>Schluss.
Bitte? Du findest dich mit Müll ab? Viel Spaß.
>Wenn ich den Timer1 für die Hardware-PWM nutze, kann ich dann keinen
>Interrupt damit ausführen lassen?
Doch.
>Zumindest funktioniert das bei mir nicht.
>TIMSK1 = 0x01; //timer 1 interrupt sources
>stelle, dann funktioniert der Servo nicht mehr, jedoch wird wie
>gewünscht der Overflow und die damit verbundenen Befehle ausgeführt.
>So sieht der Interrupt- Befehl aus.
>#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
>void timer1_ovf_isr(void)
>{
> //TIMER1 has overflowed
> static unsigned int t1;
> TCNT1H = 0xB1; //reload counter high value
> TCNT1L = 0xE1; //reload counter low value
> if(t1) {t1=9; f_200ms=1;}
> else --t1;
>}
Und das wundert dich? Du verändert den Zähler! Und diese Reloadmethode
ist uralt und Scheißdreck! Dafür gibt es den CTC Modus!
Post ECHTEN, VOLLSTÄNDIGEN CODE als Anhang und man kann dir helfen.
MfG
Falk
P S Wenn du kein Oszi zum messen hast, kannst du aber mit einem normalen
Multimeter dein Servosignal messen. Es misst den Mittelwert. Bei 2ms
sind das 10% von VCC, sprich 0,5V, bei 1ms halt die Hälfte.
Vielen Dank Falk, für die Tips.
Natürlich will ich mich nicht mit Müll abfinden, aber da ich hier nicht
verlangen kann, dass mir jemand eine Lösung serviert und ich es nunmal
nicht besser weiß, würde ich mich zur Not auch damit abfinden.
Das mit dem Interrupt habe ich jetzt hinbekommen. War mir vorher nicht
ganz klar, was der ICCAVR dort durch mich eingestellt hat (war noch aus
einem anderen Projekt).
@Falk Ich weiß nicht, was Dich daran stört, dass ich das Programm für
meine Frage abgekürzt habe. Das ist meine ich ein
Fehlerausschlußverfahren, denn es läuft ja auch mit den wenigen
Codezeilen nicht.
Und natürlich wird man Unmengen an Fehler finden. Das liegt wohl daran,
dass ich kein Nachrichtentechniker oder Programmieren bin. Ich bin
natürlich für jede Tip dankbar, denke jedoch, dass hier erstmal das
geschilderte Problem gelöst werden sollte, bevor man sich auf den ganzen
Quelltext her macht.
So wie Ihr das Programm in Anhang findet, läuft es auf dem ATmega48, nur
halt die Grenzen sind ganz schön verschoben.
Und zum CTC. In einem anderen Threat habe ich dazu folgendes gelesen:
Stefan Ernst (sternst) schrieb im Beitrag
Beitrag "Re: 2 Modellbauservos an AVR mit CTC top=ICR1":
>Bevor ihr euch die Köpfe einschlagt:
>
>CTC-Mode:
>Man muss den Ausgang selber per Software beim Compare-Match und dem
>Overflow setzen/löschen
>=> Software-PWM
>PWM-Mode:
>Die Hardware übernimmt das Setzen/Löschen des Ausgangs
>=> Hardware-PWM
Ich habe jedoch vor, eine Hardware-PWM zu erzeugen.
@ Squat *** (squat)
>@Falk Ich weiß nicht, was Dich daran stört, dass ich das Programm für
>meine Frage abgekürzt habe. Das ist meine ich ein
>Fehlerausschlußverfahren, denn es läuft ja auch mit den wenigen
>Codezeilen nicht.
Das ist prinzipiell richtig, aber dennoch musst du dann dieses gekürze
Programm VOLLSTÄNDIG posten. Sonst reden wir aneinander vorbei!
>So wie Ihr das Programm in Anhang findet,
Fehlt. Schaust du dir dein Posting nicht mal 5s an?
>Und zum CTC. In einem anderen Threat habe ich dazu folgendes gelesen:
>>CTC-Mode:
>>Man muss den Ausgang selber per Software beim Compare-Match und dem
>>Overflow setzen/löschen
>>=> Software-PWM
Stimmt nicht. CTC hat mit PWM in erste Linie nix zu tun, auch wenn man
beides kombinieren kann.
>Ich habe jedoch vor, eine Hardware-PWM zu erzeugen.
Gut, dafür ist Der Modus 14 des Timer 1 genau richtig.
MFg
Falk
Doch, aber irgendwie will er den Code nicht hochladen.
Ich hoffe diesmal klappte es mit dem Anhang.
Was ist denn der Unterschied bzw. Vorteil des CTC?
Falk Brunner schrieb:
>>>CTC-Mode:
>>>Man muss den Ausgang selber per Software beim Compare-Match und dem
>>>Overflow setzen/löschen
>>>=> Software-PWM
>
> Stimmt nicht. CTC hat mit PWM in erste Linie nix zu tun, auch wenn man
> beides kombinieren kann.
Was soll daran nicht stimmen? Es ging um das Erzeugen einer PWM. Und
wenn man das mit Hilfe des CTC-Mode machen will, dann muss man den
Ausgang selber setzen/löschen, und das ist dann das, was man als
Software-PWM bezeichnet.
@Squat *** (squat)
>So wie Ihr das Programm in Anhang findet, läuft es auf dem ATmega48, nur
>halt die Grenzen sind ganz schön verschoben.
Tja, und da sehen wir schon mehrere Probleme. Du schreibst ICR1 VOR der
Initialisierung von Timer1, das hatten wir schon als mögliche
Fehlerquelle gefunden, du hast es NICHT umgesetzt! Bzw. auskommentiert.
Was bitte so die Initialisierung von Timer 1 im Interrupt? Vollkommen
daneben!
Wozu brauchst du ZWEI Zähler, um eine 100ms und 200ms Flag zu erzeugen?
Das macht EIN Zähler spielend.
Deine Variablen f_100ms und f_200ms müssen volatile sein, siehe
Interrupt.
Schalte erstmal KEINE Interrupts ein, die brauchst du erstmal nicht. Und
räum deinen Code auf! Die Initialisierung aus der ISR RAUS! kein sei();
Tja, soviel zum Thema, "mal schell Code kürzen".
MFG
Falk
@ Stefan Ernst (sternst)
>> Stimmt nicht. CTC hat mit PWM in erste Linie nix zu tun, auch wenn man
>> beides kombinieren kann.
>Was soll daran nicht stimmen?
Der Zusammenhang, in dem der OP dich zitiert hat.
>wenn man das mit Hilfe des CTC-Mode machen will, dann muss man den
>Ausgang selber setzen/löschen, und das ist dann das, was man als
>Software-PWM bezeichnet.
Ja.
Mfg
Falk
@ Squat *** (squat)
>Was ist denn der Unterschied bzw. Vorteil des CTC?
Beim CTC wird der Zähler automatisch per Hardware zurückgesetzt, man hat
damit einen Zähler mit sehr variabler Auflösung. Das Ganze läuft
komplett unabhängig von der CPU und Interrupts.
Wenn man per Interrupt und CPU den Timer "vorlädt", geht das nur, wenn
der im Vergleich zu CPU langsam läuft also min. mit Presclaer 8, eher
32. Denn zwischen Auslösen des Interrupts und Nachladen darf der Zähler
nicht weitzählen, sonst stimmt die Rechnung nicht. Und das Anspringen
des Interrupts + Timer "vorladen" (welch schreckliches Wort) dauert gut
ein Dutzend Takte. Wenn andere Interrupts noch aktiv sind kann das auch
mal gut 1000 Takte und länger dauern -> Error!
MfG
Falk
So, jetzt habe ich noch mehr herausgeschmissen.
sei(); habe ich drin gelassen, um das Interrupt vom Timer1 ausführen zu
lassen und die Funktion des Tasters durchzuführen. Oder geht das anders
besser?
Und dann habe ich das mit dem ISR wohl noch nicht richtig verstanden,
oder habe ich es jetzt schon korriegiert?
Und noch zum letzten Threat:
Macht es dann Sinn, den Timer so einzustellen, dass er mit einem
Vorteiler von 32 oder sogar mit 256 läuft? Oder bezieht sich der Satz
auf den CTC?
Ich dachte, eine Hardware-PWM wäre zuverlässiger, wenn ich während
dessen noch weitere Aufgaben vom Controller abverlange.
@ Squat *** (squat)
>sei(); habe ich drin gelassen, um das Interrupt vom Timer1 ausführen zu
>lassen und die Funktion des Tasters durchzuführen. Oder geht das anders
>besser?
Es geht vieles besser . .
Für einen Einfachen Test kann man auch mit _delay_ms() arbeiten, ohne
Interrupts.
>Und dann habe ich das mit dem ISR wohl noch nicht richtig verstanden,
>oder habe ich es jetzt schon korriegiert?
???
Deine ISR ist immer noch Unsinn. Dein f_100ms wird bei JEDEM Aufruf
gesetzt, was bewirkt, dass das if() Konstrukt sinnlos ist. Aber ich sehe
gerade, die ISR wird sowieso nie aufgerufen, weil es keinen Overflow
gibt. Nur einen Compare Match. Overflow ist immer 0xFFFF -> 0x0000.
>Und noch zum letzten Threat:
Wen willst du denn bedrohen? ;-)
>Macht es dann Sinn, den Timer so einzustellen, dass er mit einem
>Vorteiler von 32 oder sogar mit 256 läuft?
Nö.
> Oder bezieht sich der Satz auf den CTC?
Bitte? Lies die Postings mal in Ruhe.
>Ich dachte, eine Hardware-PWM wäre zuverlässiger, wenn ich während
>dessen noch weitere Aufgaben vom Controller abverlange.
Hat jemand was anderes behauptet?
MfG
Falk
Squat *** schrieb:
> Gibt es auch eine Möglichkeit, den vollen Weg auszunutzen, wenigstens
> anneähernd 180°.
Die meisten Servos sind für 90° Drehwinkel mit 1-2ms Puls spezifiziert.
Meistens hat die Mechnaik einen möglichen Drehwinkel von ca. 180°,
allerdings liegt der Solldrehwinkel irgendwo in diesem Bereich. Es kann
also sein, dass Du kaum unter 1ms darfst, aber weiter über 2ms, oder
auch umgekehrt.
Solltest Du 180° brauchen, musst Du nach Robotik-Servos schauen. Die
sind aber meist deutlich überteuert.
Die Funktion delay, habe ich leider nicht in diesem Compiler integriert.
Ich hatte es zwar gestern mal kurz versucht, aber da delay.h auf GCC-AVR
basiert und ich mit ICCAVR arbeite, glaube ich, ist das sowieso nicht
ganz so einfach zu übernehmen.
Lasse mich jedoch gerne von jemand besseren Belehren.
Ich meinte mit ISR eigentlich die Position von ICR1. Entschuldigung. Hab
mich wohl verschrieben. 1 | void timer1_init(void)
| 2 | {
| 3 | // Waveform 14 //
| 4 | TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
| 5 | TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS11);
| 6 |
| 7 | ICR1 = 20000;
| 8 | OCR1A = 1500;
| 9 | OCR1B = 1500;
| 10 | }
|
Und mit dem Überlauf 1 | #pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
| 2 | void timer1_ovf_isr(void)
| 3 | {
| 4 | //TIMER1 has overflowed
| 5 | static unsigned char t1;
| 6 |
| 7 | if(t1) {t1=4; f_100ms=1;}
| 8 | else --t1;
| 9 | }
|
Muss ich das Register TCNT beschreiben? Das, welches ich gerade heraus
gelöscht habe, da es die Einstellungen der PWM in meinem Fall verändert
hatte?
@ Squat *** (squat)
>void timer1_init(void)
Passt.
>void timer1_ovf_isr(void)
Ist zwar Unsinn, tut aber nicht weh.
>Muss ich das Register TCNT beschreiben?
NEIN! Das macht der Timer allein!
MFG
Falk
Das der zweite Teil unsinnig ist, verstehe ich ehrlich gesagt nicht.
Wenn er überläuft, wird doch gefragt, ob t1 = 0 ist und wenn er das ist,
wird er wieder auf 4 gesetzt. Falls nicht, wird weiter herunter gezählt,
oder nicht?
@ Squat *** (squat)
>Wenn er überläuft, wird doch gefragt, ob t1 = 0 ist
Nö, du fragst, ob t UNGLEICH Null ist.
> if(t1) {t1=4; f_100ms=1;}
Das ist die C-Kurzform für
if(t1 != 0) {t1=4; f_100ms=1;}
> und wenn er das ist,
>wird er wieder auf 4 gesetzt. Falls nicht, wird weiter herunter gezählt,
>oder nicht?
Oder nicht ;-)
Dann macht es anders herum Sinn. 1 | if(t1) {--t1;}
| 2 | else {t1=4; f_100ms=1;}
|
@ Squat *** (squat)
>Dann macht es anders herum Sinn.
Und damit das auch normale Menschen lesen können, eher so.
1 | if (t1) {
| 2 | --t1;
| 3 | }
| 4 | else {
| 5 | t1=4;
| 6 | f_100ms=1;
| 7 | }
|
MFG
Falk
Alles klar und bitte entschuldige, meine teilweise ausgefallene
Schreibweise.
Dann Vielen Dank.
Mit dem jetztigen Quelltext, kann ich den Servo um genau 90° drehen und
so wie es scheint, ist orginal auch nicht mehr drin.
Entweder ich schraube an den Zeit noch etwas herum, oder ich besorge mir
einen Windenservo und probiere an dem etwas herum. Vielleicht hilft es
auch, wenn ich mir die Hardware zu Gemüte ziehe und die Widerstände
etwas anpasse.
Der Vollständigkeit, packe ich den Quelltext erneut hier an.
Ach eine Frage habe ich doch noch.
Mit dem Timer0 steuere ich einen Gleichstrommotor mittels Mosfet an. Das
klappt auch wunderbar.
Nur wenn ich den Timer0 dafür vorbereite und das TCCR0A-Register
beschreibe, (zur Einstellung der Taktrate), fließt Strom zum Motor.
Nicht viel, aber ich höre ein leichtes Brummen. Dabei ist OCR0A = 0;.
Bisher habe ich TCCR0A glöscht, und erst beim Startbefehl, den TCCR0A
konfiguriert. Ist das Normal?
Gleicher Quelltext, nur mit dem folgendem erweitert. 1 | void timer0_init(void)
| 2 | {
| 3 | TCCR0A |= (1 << WGM01) | (1 << WGM00); // Fast PWM
| 4 | TCCR0B |= (1 << CS02); // Prescaler: 1/256
| 5 |
| 6 | // Timer noch nicht anschalten, da sonst die Pumpe läuft //
| 7 | TCCR0A |= (1 << COM0A1); // Fast PWM, non-inverting mode
| 8 | TCCR0A &= ~(1 << COM0A0);
| 9 | OCR0A = 0x00;
| 10 | OCR0B = 0x00;
| 11 | }
|
Und im Programmablauf: 1 | if(f_100ms)
| 2 | {
| 3 | f_100ms=0;
| 4 | funkt_tast();
| 5 | if (taster == 2) {
| 6 | OCR0A = 0xEE;
| 7 | OCR0B = 0xEE;
| 8 | }
| 9 | if (taster == 0) {
| 10 | OCR0A = 0x00;
| 11 | OCR0B = 0x00; }
| 12 | }
| 13 |
| 14 | }
|
@ Squat *** (squat)
>Nur wenn ich den Timer0 dafür vorbereite und das TCCR0A-Register
>beschreibe, (zur Einstellung der Taktrate), fließt Strom zum Motor.
>Nicht viel, aber ich höre ein leichtes Brummen. Dabei ist OCR0A = 0;.
Das liegt daran, das bei OCR0A = 0 der Pin NICHT dauerhaft Null ist,
sondern ein Puls mit einer Timertaktlänge ausgegeben wird, siehe
Datenblatt. Das kann man auf zwei Arten ändern.
Den Wert 0 gesondert behandeln und dabei die PWM abschalten, das IO-Pin
als normalen Ausgang mit LOW schalten
Invertierte PWM nutzen. Dann erreicht man aber nicht mehr 100% High,
denn dann wird immer ein LOW Takt bei OCR0A = 255 ausgegeben.
MFG
Falk
Alles klar, dann lag ich ja garnicht so verkehrt, mit dem TCCR0A auf
Null setzen. Ist das der Fall, den du meinst? Denn der Pin wird ja am
Anfang von mirn als Ausgang mit Low definiert.
Oder meinst du mit PWM abschalten noch was anderes?
@ Squat *** (squat)
>Alles klar, dann lag ich ja garnicht so verkehrt, mit dem TCCR0A auf
>Null setzen. Ist das der Fall, den du meinst?
Ja.
>Oder meinst du mit PWM abschalten noch was anderes?
Nein.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|