Forum: Mikrocontroller und Digitale Elektronik ATTiny45 PWM


von Norbert S. (norberts)


Lesenswert?

Moin,

Ich versuche einen kleinen Regler für Bürstenmotoren zu bauen.
RC-Signal einlesen, PWM raus.
Das RC-Signal lese ich mit PCint ein und messe das Signal mit einem 
freilaufendem Timer.
Funktioniert.
Nun die PWM auf Timer1, mit einem Tiny85 auf einem Arduino-Board hat das 
auch prima funktioniert.
Das Ding ist mir aber zu klobig, also habe ich das auf einem Breakout 
mit einem Tiny45 gemacht und die PWM geht nicht.
Die Hardware ist Ok. Ich kann den Pin toggeln lassen, das RC-Signal 
einlesen geht, PWM aber nicht.
Dann habe ich den dokumentierten Bug im Tiny45 bzgl. OC1B gefunden, der 
Workaraound hat aber auchch nicht funktioniert.
Also alles umgebaut, PWM nun auf OC0A. Und auch da funktioniert es 
nicht!

Mag mal einer drüber schauen?
1
Tccr0b.cs01 = 1                                             'Prescaler 8 = 4khz @ 8Mhz
2
3
Tccr0a.com1a1 = 1                                           'OC0A set on Ovf, clear on match in fast PWM
4
Tccr0a.com1a0 = 0
5
6
Tccr0a.wgm01 = 1
7
Tccr0a.wgm00 = 1                                            'Fast PWM
8
9
Pout Alias Ocr0a
10
11
Ddrb.0 = 1                                                  'OC0A Output PWM
12
13
Ocr0a = 100
14
Do
15
Loop

von Max D. (max_d)


Lesenswert?

Norbert S. schrieb:
> Tccr0a.com1a1 = 1                                           'OC0A set on
> Tccr0a.com1a0 = 0

Du nimmst die Bit-masken von timer1 für register von timer0....

Lad am besten mal das Originale Programm (das für timer1) hier hoch...

von M. K. (sylaina)


Lesenswert?

Norbert S. schrieb:
> Das Ding ist mir aber zu klobig, also habe ich das auf einem Breakout
> mit einem Tiny45 gemacht und die PWM geht nicht.

Also wenn das Teil mit nem Arduino-Board mit dem Tiny45 funktioniert wie 
gewünscht, auf einem extra angefertigten Board dann aber nicht dann kann

Norbert S. schrieb:
> Die Hardware ist Ok.

definitiv nicht stimmen.

Ansonsten: Anmerkungen von Max stimme ich zu: Du verwendest Bezeicher 
für fremde Register. So etwas kann klappen, muss aber auch nicht.

von S. Landolt (Gast)


Lesenswert?

> So etwas kann klappen, muss aber auch nicht.

Hier klappt es nicht, COM1An liegen auf den Bitpositionen 4 und 5, 
COM0An auf 6 und 7.

von Norbert S. (norberts)


Lesenswert?

Moin,

Ok, der Tippfehler mit com1an war es natürlich. Jetzt läuft es mit 
Timer0, allerdings mit Phase correct PWM weil 0A mit Fast PWM diese 
blöde Angewohnheit hat, immer entweder nie 100% oder 0% ausgeben kann, 
je nach Polung. Egal, läuft.

Das ursprüngliche Problem: Es lief mit OC1B auf dem Arduinoboard mit 
einem Tiny85!
Das eigene Board hat einen Tiny45 und der hat(te) wohl genau da einen 
Bug:
-----------------
Timer Counter 1 PWM output generation on OC1B – XOC1B does not work 
correctly
Timer Counter1 PWM output OC1B-XOC1B does not work correctly. Only in 
the case when the control bits, COM1B1 and COM1B0 are in the same mode 
as COM1A1 and COM1A0, respectively, the OC1B-XOC1B output works 
correctly.
Problem Fix/Work around
The only workaround is to use same control setting on COM1A[1:0] and 
COM1B[1:0] control bits, see table 14-
4 in the data sheet. The problem has been fixed for Tiny45 rev D.
-----------------
Nur leider funktionierte der Workaround auch nicht.
Ich konnte den Pin manuell toggeln, also war der offensichtlich ok und 
nur nicht am Timer drangeklöppelt.
So geht es jetzt erstmal und der letzte verbleibende frische Tiny45 
kommt in die Tonne.

Naja, danke für den Hinweis mit dem com1an, so hatte ich das gehofft.
Daß das Bascom ist sieht man vielleicht. Da kann man wirklich jeden 
Bitbezeichner mit jedem Register unterjubeln, ist nur die Bitnummer. Ich 
denke bei C-Compilern wird das aber nicht anders sein, oder?

Gruß,
Norbert

von Stefan F. (Gast)


Lesenswert?

Norbert S. schrieb:
> Ich denke bei C-Compilern wird das aber nicht anders sein, oder?

korrekt, C-Compiler können solche Fehler ebenfalls nicht erkennen.

Bei STM32 enthalten die Konstanten immer den namens des Registers. Zum 
Beispiel:

Register: RCC->CR
Ein Bit davon heisst: RCC_CR_PLLON

Schreibzugriff: SET_BIT(RCC->CR, RCC_CR_PLLON);

Da kann man leicht erkennen, wenn Register- und Bit-Namen durcheinander 
gewürfelt wurden. Nur tut es leider nicht der Compiler erkennen.

von S. Landolt (Gast)


Lesenswert?

Nun ja, das ist bei den AVR8 zumindest ähnlich, hier z.B. COM0_ bzw. 
COM1_.

von c-hater (Gast)


Lesenswert?

Norbert S. schrieb:

> Das eigene Board hat einen Tiny45 und der hat(te) wohl genau da einen
> Bug:
[...]

Das muss dann aber ein seeeehr gut abgehangener Tiny gewesen sein...

Dieser Bug betraf die Revisionen B..C. Aktuell ist F. Und seit Rev. D 
gibt es lt. DB keine known errata mehr. Da liegen sicher viele Jahre 
dazwischen...

Fazit: Man muss auch mal den Mut aufbringen, etwas wegzuwerfen. Das 
fällt zumindest dann eigentlich sehr leicht, wenn der Ersatz weniger 
kostet als ein Besuch auf'm Bahnhofsklo nur zum Pinkeln...

von Norbert S. (norberts)


Lesenswert?

Moin,

Nunja, falsches Bit zum Register ist ja nun nicht so ein gängiger 
Fehler. Wobei das wirklich einfach für den Compliler wäre...

Ja, der Tiny ist alt. Mit "0934" als Datecode wohl gut 10 Jahre. Lag 
hier noch so rum...
Wie gesagt, der Zweite den ich noch habe/hatte ist soeben in die Tonne 
gewandert.

Gruß,
Norbert

von Stefan F. (Gast)


Lesenswert?

Norbert S. schrieb:
> Wobei das wirklich einfach für den Compliler wäre...

Wie denn, ohne eine neue Syntax zu erfinden? Erkläre mal.

von Norbert S. (norberts)


Lesenswert?

Moin,

Vorrausgesetzt, die Bitbezeichner sind eindeutig, also Bit abc01 gibt es 
nur in einem Register, steht das zumindest bei Bascom als Kommentar in 
der Definitionsdatei des µC drin.
Dummerweise nur als Kommentar, z.B. so:
---------------
; TCCR0A - Timer/Counter  Control Register A
WGM00  = 0  ; Waveform Generation Mode
WGM01  = 1  ; Waveform Generation Mode
COM0B0  = 4  ; Compare Output Mode, Fast PWm
COM0B1  = 5  ; Compare Output Mode, Fast PWm
COM0A0  = 6  ; Compare Output Mode, Phase Correct PWM Mode
COM0A1  = 7  ; Compare Output Mode, Phase Correct PWM Mode
---------------

Da muss der Compiler doch nur erkennen, daß das Bit nicht zum Register 
passt.
Allerdings denke ich, daß der Leidensdruck da nicht gegeben ist.
Da fielen mir wirklich ärgerlichere Dinge ein, die auch nicht so 
schwierig sein können und wo man sich an den Kopf packt. Sei es C, 
Bascom oder sonstwas.

Gruß,
Norbert

von Max D. (max_d)


Lesenswert?

Zumindest bei C dürfte das ziemlich unmöglich sein. Für den Compiler ist 
so ein Register nur eine Speicheradresse wie jedes andere Byte 
(inklusive RAM) auch.
Bei AVR gibt es zwar die spezielle IO-Adressierung, aber bis der 
Compiler anfängt über solche Sachen auch nur nachzudenken hat der 
Präprozessor jeglichen Namensbezug der Werte schon lange entsorgt.
Da muss einfach Brain 2.0 aktiv werden und die richtigen Knöpfe drücken.

von Norbert S. (norberts)


Lesenswert?

Max D. schrieb:
> Zumindest bei C dürfte das ziemlich unmöglich sein. Für den Compiler ist
> so ein Register nur eine Speicheradresse wie jedes andere Byte
> (inklusive RAM) auch.

Also vorweg: Ich sehe da auch keinen Handlungsbedarf.

Aber woher hat der Compiler die Speicheradresse von TCCR1A oder so?
Und die Nummer von Bit Com1a0? Richtig, aus der Definitionsdatei.

Der Compiler findet TCCR1A, kramt in der Def. und findet Adresse XY. Da, 
die Bitschieberei in diesem TCCR1A, Com1a0 steht ... such... ah, ne 3 
muss ich nehmen.
Wenn in der Def. nun steht:
TCCR1A = Adresse XY
bla..
bla
.
Com1a0 = 5
..

...dann kann das ja nicht so schwierig sein.
Das könnte man als reine Syntaxprüfung vorab machen.
Ok, Ppipfax, braucht man nicht.
Da nerven andere Dinge viel mehr.
Daß Bascom immer noch nur eine Operation pro Zeile kann (A = A + B + C 
geht nicht) oder daß C es nicht selber blickt, daß eine Variable 
vielleicht in einer ISR verändert werden könnte. Nein, ich möchte die 
Argumente eigentlich nicht hören/lesen, warum Letzteres so sein muss. 
Ich werde es aber gleich vermutlich doch erfahren... ;-)

Gruß,
Norbert

von M. K. (sylaina)


Lesenswert?

Norbert S. schrieb:
> Moin,
>
> Ok, der Tippfehler mit com1an war es natürlich. Jetzt läuft es mit
> Timer0

Ich hatte ja deinen Ausgangspost so gelesen, dass es mit Timer1 auf dem 
Breakout-Board nicht lief und du darauf hin auf Timer0 umgebaut hattest 
und auch damit lief es nicht. Aber auf dem Arduino Board lief es wie 
erwartet.

von Stefan F. (Gast)


Lesenswert?

Norbert S. schrieb:
> Da muss der Compiler doch nur erkennen, daß das Bit nicht zum Register
> passt...dann kann das ja nicht so schwierig sein.

Der Compiler sieht nur Adressen und Bit-Nummern. Jedes Register hat 8 
Bits. Solange du nicht versuchst, das neunte Bit zu ändern, ist aus 
Sicht des Compilers alles Ok.

Bedenke, dass der Compiler nicht intelligent ist. Er hat keinen blassen 
Schimmer, was Namen bedeuten. Er kennt nur eine Hand voll 
Schlüsselwörter wie "if", "else", "for", ...

Um dieses Verhalten zu ändern, müsste man eine neue Programmiersprache 
erfinden. Es wird ja auch alle paar Monate eine neue Programmiersprache 
als die Lösung der IT Probleme angepriesen. Ich kenne allerdings im 
Mikrocontroller Umfeld keine C-Ähnliche Sprache, die sich lange gehalten 
hat.

Es nicht nicht immer gut, Dinge zu ändern, weil man es kann. Man sollte 
schon einen guten Grund haben und daran denken, dass jede Änderung neue 
Probleme erzeugt. Manchmal ist es besser, den alten Gaul alt sein zu 
lassen und sich an seine Eigenarten zu gewöhnen.

von Klaus (Gast)


Lesenswert?

Stefan F. schrieb:
> Der Compiler sieht nur Adressen und Bit-Nummern. Jedes Register hat 8
> Bits. Solange du nicht versuchst, das neunte Bit zu ändern, ist aus
> Sicht des Compilers alles Ok.

Man könnte eine Structur aus Bitfeldern auf das SFR legen, bei dem die 
existierenden Bits passende Namen haben. Dann liefert der Compiler einen 
Fehler, wenn nicht existierende Bits oder Bits im falschen Register 
angesprochen werden sollen.

MfG Klaus

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.