Forum: Mikrocontroller und Digitale Elektronik Soft-PWM Problem


von Dominik R. (vision)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

nachdem ich gestern meine ATTinys wieder ans Laufen bekommen habe, gibt 
es heute ein Code-Problem.
Ich habe (versucht) ein kleines Test-Programm für einen ATTiny85 zu 
schreiben, um per Soft-PWM einen Servo an PB4 anzusteuern. Leider 
scheint meine Berechnung irgendwo einen einen Haken zu haben, denn die 
PWM ist zu langsam (50ms statt der gewünschten 20ms) und die Pulsbreiten 
dementsprechend zu lang, so dass der Poti am Anschlag klebt, statt sich 
hin und her zu bewegen.

Eine Änderung am OCR1A bringt genau gar nichs. Egal, ob ich 0x64, 0x32 
oder 0x16 ins Register schreibe, die Frequenz bleibt...

Wo liegt der Fehler?

von Uwe (de0508)


Lesenswert?

Hallo Dominik,

Du hast das Datenblatt nicht gelesen.

ein attiny85 vergleicht im CTC Mode sein TOP Zählerwert gegenüber OCR1C 
!
Aber das OCR1C kann keine Overflow-Interrupts auslösen !

Somit läuft der Zähler TCNT1 weiter an OCR1A vorbei, der dann einen 
Interrupts Event signalisiert und erst nach weiteren (256-OCR1A) 
Schritten fängt TCNT1 = 0.

//Bit 7 – CTC1 : Clear Timer/Counter on Compare Match
When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 
in the CPU clock cycle after a compare match with OCR1C register value. 
If the control bit is cleared, Timer/Counter1 continues counting and is 
unaffected by a compare match.//

: Bearbeitet durch User
von Uwe (de0508)


Lesenswert?

Hallo  Dominik,

hier ist noch ein Fehler:
1
if(i<arraysize){
2
      i++;
3
    }
4
    else{
5
      i = 0;
6
    }

Es gibt einen Durchlauf mit i=arraysize.
Das ist ein Fehler, denn der Index |i| greift auf ein Element im Array 
|servo_pulse[| zu das nicht existiert !

Wo hast Du den so programmieren gelernt ?

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Außerdem:

uint8_t arraysize = sizeof(servo_pulse) / sizeof(uint8_t);

Was rechts vom Gleichheitszeichen steht, ist eine Konstante, die der 
Compiler schon ausrechnen kann. Der Wert landet in einer globalen 
Variable. Daher wird der Compiler vorraussichtlich den Vergleich später 
mit der Variablen machen statt mit der Konstanten.

Daher besser:
1
#define ARRAYSIZE (sizeof(servo_pulse) / sizeof(uint8_t))
2
3
....
4
if (i < ARRAYSIZE - 1){      // -1: Hier den anderen Fehler glattgebügelt
5
...

: Bearbeitet durch Moderator
von Dominik R. (vision)


Lesenswert?

Danke euch beiden. Mit OCR1C und der angepassten Array-Größe läuft es 
jetzt!

von Uwe (de0508)


Lesenswert?

Zeige bitte noch dein komplettes Programm, so können andere auch deinem 
Erfolg folgen.

Ok ?

: Bearbeitet durch User
von Uwe (de0508)


Lesenswert?

Hallo Dominik,

noch ein Fehler, natürlich liefert dieser "Teiler" keine 1ms Ticks:
1
OCR1A = 0x64;

Wie man das richtig berechnet steht im Datenblatt !

Man wer liest den das überhaupt ?

von Dominik R. (vision)


Angehängte Dateien:

Lesenswert?

Anbei das geänderte Programm, dass es jetzt tut, aber was meinst du, 
dass der "Teiler" keine 1ms-Ticks liefert? Mal davon abgesehen, dass es 
OCR1C statt OCR1A heißen muss?
1MHz Systemtakt / 100 = 10kHz = 0.1ms oder verrechne ich mich da jetzt?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Dominik R. schrieb:
> 1MHz Systemtakt / 100 = 10kHz = 0.1ms oder verrechne ich mich da jetzt?

>  OCR1C = 0x64;      //1MHz/100 = 10kHz Interruptfrequenz = alle 0.1ms

 Falsch gerechnet - wo bleibt die Null ?

  OCR1C = 0x64 - 1;      //1MHz/100 = 10kHz

: 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
Noch kein Account? Hier anmelden.