Forum: Mikrocontroller und Digitale Elektronik FastPWM funktioniert am Attiny85 nicht


von Jaslogic (Gast)


Lesenswert?

Hallo,
ich versuche mit einem Attiny85 und FastPWM ein Servo anzusteuern. Der 
Timer wird mit machen Werten wie gewollt resettet, aber OC0B liefert 
völlig absurde Werte, die komplett zufällig gewählt wirken. Das ist mein 
Code:
1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
void initTimer() {
7
    GTCCR = (1 << TSM) | (1 << PSR0); // Timer anhalten und Prescaler reset
8
    
9
    OCR0A = 10011100; // 8MHz / (1024 * 50Hz) = 156; 20ms
10
    OCR0B = 00001000; // 8Mhz / (1024 * 1000Hz) = 8; 1ms
11
    
12
    TCCR0A =
13
        (0 << COM0A1)   |
14
        (0 << COM0A0)   |
15
        (1 << COM0B1)   |
16
        (0 << COM0B0)   |
17
        (1 << WGM01)    |
18
        (1 << WGM00);
19
    TCCR0B = (1 << WGM02) | (1 << CS02) | (0 << CS01) | (1 << CS00); // prescaler = 1024
20
    GTCCR = (0 << TSM); // Timer starten
21
    
22
}
23
24
int main(void)
25
{
26
    DDRB |= (1 << PB1);
27
    PORTB &= ~(1 << PB1);
28
29
    initTimer();
30
31
    for(;;) {
32
    }
33
    return 0;
34
}

Mit dem Code ist beträgt die Periodendauer 27,5ms und der Puls 0,1ms. 
Mit andern Werten funktioniert es auch nicht wie gewollt.
Ich hoffe irgendjemand findet meinen Fehler,

LG.

von Stefan F. (Gast)


Lesenswert?

> GTCCR = (0 << TSM);

Ist Dir klar, dass du damit ALLE Bits auf 0 setzt?

von Stefan F. (Gast)


Lesenswert?

Du hast die Bits WGM00, WGM01 und WGM02 auf 1 gesetzt. Das ist der "Fast 
PWM" Modus mit TOP=OCRA.

Ich schätze, du wolltest WGM02 auf 0 setzen. Falls nicht, was hast Du 
Dir dabei gedacht?

von Jaslogic (Gast)


Lesenswert?

Ehrlich gesagt nicht, leider ändert das nichts am Problem.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jaslogic schrieb:
> GTCCR = (0 << TSM); // Timer starten

So löscht man keine Bits, sondern schiebt lediglich eine 0 nach links.

Man löscht das TSM-Bit so:

GTCCR &= ~(1 << TSM); // Timer starten

Ob das dann auch Deinen Timer startet, weiß ich nicht. Habe gerade kein 
DB zur Hand.

Dir fehlen Grundkenntnisse in C, siehe auch Bitmanipulation

von Stefan F. (Gast)


Lesenswert?

Dann mach mal was ganz anderes - ohne Timer. Lass eine LED blinken und 
benutze dazu _delay_ms(). Blinkt die LED mit dem richtigen Timing? 
Blinkt sie regelmäßig?

Sinn der Sache: Hardware-Fehler ausschließen.

von Jaslogic (Gast)


Lesenswert?

Das mit TOP = OCRA ist schon so geplant, ich dachte, dass dann nach 20ms 
der Timer immer wieder bei Null anfängt und ich dann mit OCR0B den Puls 
ändern kann.

von Stefan F. (Gast)


Lesenswert?

> OCR0A = 10011100;

Das ist eine Dezimal-Zahl.

> OCR0B = 00001000;

Das ist eine Oktal-Zahl.

Binärzahlen beginnen mit "0b".

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Jaslogic schrieb:
> OCR0A = 10011100; // 8MHz / (1024 * 50Hz) = 156; 20ms
>     OCR0B = 00001000; // 8Mhz / (1024 * 1000Hz) = 8; 1ms

Der Compiler denkt, das du da eine Dezimalzahl angibst. Du solltest, 
wenn du schon binär notieren willst, ein '0b' voranstellen.
Du kannst aber auch ganz einfach 156 und 8 reinschreiben, dann sparst du 
dir das fehlerträchtige Umkodieren in binär.
Stefan beats me to it :-P

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Du kannst auch ruhig das schreiben:

OCR0A = F_CPU / (1024 * 50);

Der Compiler berechnet solche konstanten Ausdrücke. Im Maschinencode 
wird nur die 156 stehen.

von Jaslogic (Gast)


Lesenswert?

Stefan U. schrieb:
>> OCR0A = 10011100;
>
> Das ist eine Dezimal-Zahl.
>
>> OCR0B = 00001000;
>
> Das ist eine Oktal-Zahl.
>
> Binärzahlen beginnen mit "0b".

Vielenn Dank das war das Problem.

von Jaslogic (Gast)


Lesenswert?

Matthias S. schrieb:
> Jaslogic schrieb:
>> OCR0A = 10011100; // 8MHz / (1024 * 50Hz) = 156; 20ms
>>     OCR0B = 00001000; // 8Mhz / (1024 * 1000Hz) = 8; 1ms
>
> Der Compiler denkt, das du da eine Dezimalzahl angibst. Du solltest,
> wenn du schon binär notieren willst, ein '0b' voranstellen.
> Du kannst aber auch ganz einfach 156 und 8 reinschreiben, dann sparst du
> dir das fehlerträchtige Umkodieren in binär.
> Stefan beats me to it :-P

Danke, das war mein Fehler.

von H.Joachim S. (crazyhorse)


Lesenswert?

Trotzdem ist der Ansatz (PWM mit 8bit) Mist.
Nehmen wir den besten Fall, der Timer läuft für die 20ms tatsächlich bis 
255.
D.h. ein Timertakt sind 20ms/255=78µs.
Der Stellbereich eines Servos ist üblicherweise 1,5ms...2,5ms. Du hast 
also die PWM-Werte 19...32, also nur 13 verschiedene mögliche 
Servostellungen. Das ist doch Murks und geht besser. Auch mit nem 
8bit-Timer.

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.