Forum: Mikrocontroller und Digitale Elektronik ATmega48 Hardware-PWM - Zu kurzer Servoweg


von Squat *. (squat)


Lesenswert?

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.

von Squat *. (squat)


Lesenswert?

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.

von Hannes L. (hannes)


Lesenswert?

> 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.

...

von Squat *. (squat)


Lesenswert?

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?

von Stefan E. (sternst)


Lesenswert?

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.

von Squat *. (squat)


Lesenswert?

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?

von Hannes L. (hannes)


Lesenswert?

> 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

...

von Falk B. (falk)


Lesenswert?

@  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

von Squat *. (squat)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@  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.

von Squat *. (squat)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@  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

von Squat *. (squat)


Angehängte Dateien:

Lesenswert?

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?

von Stefan E. (sternst)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@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

von Falk B. (falk)


Lesenswert?

@  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

von Falk B. (falk)


Lesenswert?

@  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

von Squat *. (squat)


Angehängte Dateien:

Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@  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

von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

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.

von Squat *. (squat)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

@  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

von Squat *. (squat)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

@  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 ;-)

von Squat *. (squat)


Lesenswert?

Dann macht es anders herum Sinn.
1
if(t1) {--t1;}
2
else   {t1=4; f_100ms=1;}

von Falk B. (falk)


Lesenswert?

@  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

von Squat *. (squat)


Angehängte Dateien:

Lesenswert?

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.

von Squat *. (squat)


Lesenswert?

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
  }

von Falk B. (falk)


Lesenswert?

@  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

von Squat *. (squat)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

@  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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.