Forum: Mikrocontroller und Digitale Elektronik Einstellen von ''ti'' bei PWM


von Seggel (Gast)


Lesenswert?

Guten Abend,
ich habe mich heute zum ersten mal mit den PWM funktionen der 
Timer/counter und mit der ADC Wandlung beschäftigt.
Dazu habe ich einen kleinen Servotester gebaut der an Pin40 (PA0 bzw. 
ADC0)
meines ATmega 32 eine Analoge Spannung am Schleifer eines 10k Potis 
abgreift. Das Poti ist mit 10k gegen masse geschalten. Sodass der 
schleifer nicht auf masse liegt. Der letzte Freie Pin liegt über 1k auf 
+5V um nicht ganz auf die Versorgungs- und Referenzspannung zu kommen. 
Als Referenz verwende ich AREF auf +5V(ADMUX bit 7 und 6 auf 0).

Den nun Digitalisierten Wert nehme ich als Vorgabe für ti (also OCR1A).
Das funktioniert auch alles Wunderbar. Ich habe meine 20ms Periodendauer 
nur die Impulsdauer läuft von knapp 500µs bis knapp 1000µs. So, nun habe 
ich mir durch sehr primitive weise geholfen und den Wert ADCW einfach 
mit 2 Multipliziert. So komme ich auf 0,980ms bis 1,940ms laut meinem 
Oszi.
Das Servo lässt sich steuern, sieht gut aus, nur die Unschöne Lösung in 
meinem Programm stört mich.
Prinzipiell eine frage, muss ich in der Software, oder der Hardware nach 
der Lösung des Problems suchen?
Hier noch mein Quelltext:
1
#include<avr/io.h>
2
3
int main (void)
4
{
5
  DDRD = 0b00100000;
6
  
7
  TCCR1A = 0b10100010;
8
  TCCR1B = 0b00011010;
9
  
10
  ICR1 = 20000;
11
  
12
  while (1)
13
  {
14
    ADMUX = 0b00000000;
15
    ADCSRA = 0b11100010;
16
    OCR1A = ADCW*2;
17
  }
18
}

Danke schonmal im Vorraus.
Grüße Jens

von Karl H. (kbuchegg)


Lesenswert?

Seggel schrieb:

> meines ATmega 32 eine Analoge Spannung am Schleifer eines 10k Potis
> abgreift. Das Poti ist mit 10k gegen masse geschalten. Sodass der
> schleifer nicht auf masse liegt.

Das ist der eigentlich unschöne Punkt


> Das Servo lässt sich steuern, sieht gut aus, nur die Unschöne Lösung in
> meinem Programm stört mich.

Was bitte ist an einer Lösung unschön, die einen Wertebereich in einen 
anderen umrechnet?

Hast du alle Tage:
1
  0 Äpfel kosten 10 Euro   (10 Euro wegen der Kiste)
2
 10 Äpfel kosten 17 Euro
3
-------------------------
4
 wieviel kosten x Äpfel

An einer linearen Gleichung
1
   Ergebnis = k * x + d
ist ganz und gar nichts unschön. Ganz im Gegenteil. Unschön wird es 
erst, wenn man sie nicht anwenden kann. Siehe zb diverse Widerstände, 
die völlig unnötig eingebaut werden, weil man Angst vor ein bischen 
Mathe hat.

: Bearbeitet durch User
von Seggel (Gast)


Lesenswert?

Hallo Herr Buchegger,
vielen dank für ihre Antwort.
Also viel hilft nicht immer viel.
Da ich die Formel wohl so lassen kann fürs erste,
muss ich an der Hardwaremäßig verbauten Schaltung etwas ändern das habe 
ich schonmal herausgelesen. Wer lesen kann ist klar im Vorteil, das hat 
nach wie vor gültigkeit.
Danke schonmal für den Lösungsansatz, damit werde ich mich weiter auf 
den weg machen.

Beste grüße und einen Schönen abend
Jens

von Karl H. (kbuchegg)


Lesenswert?

Seggel schrieb:

> Hallo Herr Buchegger,

Herr Buchegger?
Der 'Herr Buchegger' ist mein Vater. Ich bin einfach der Karl Heinz 
(oder nur Heinz).

Und unter Programmierern sind wir automatisch per Du.

> muss ich an der Hardwaremäßig verbauten Schaltung etwas ändern das habe
> ich schonmal herausgelesen.

Ja, schmeiss den Widerstand raus. Du brauchst nur das Poti.


Der ADC liefert dir dann die Potistellung als Zahlenwert von 0 bis 1023, 
Endstellung zu Endstellung.


Bei einem Potiwert von 0 soll die Berechnung einen OCR Wert von 1000 
ergeben.
Bei einem Potiwert von 1023 soll die Berechnung einen OCR Wert von 2000 
ergeben.

(weil du ja Zeiten von 1.0ms bis 2.0ms haben willst und die PWM so 
aufgesetzt ist, dass die ms einfach mal 1000 den OCR Wert ergeben.


d.h.
gesucht sind
1
   OCR = k * ADC + d
das k und das d, welches genau diese Umrechnung erledigen.

Da setzen wir einfach mal die bekannten Zahlenwerte ein
1
   1000 = k * 0  + d   ( I )
2
   2000 = k * 1023 + d  ( II )

und erhalten somit 2 Gleichungen in 2 Unbekannten ( k und d ). Das lässt 
sich aber lösen.

Aus der Gleichung I lässt sich unmittelbar ablesen, dass das d gleich 
1000 sein muss.
Das in die Gleichung II eingesetzt
1
   2000 = k * 1023 + 1000
und ein wenig umgeformt
1
   2000 - 1000 = k * 1023
2
   1000 = k * 1023
3
   1000 / 1023 = k
ergibt dann auch den Wert für k.


die gesuchte Gleichung, die die Umrechnung erledigt lautet also
1
   OCR_Wert = ADC_Wert * 1000 / 1023 + 1000

mit den bekannten Zahlenwerten kann man das noch ausprobieren und man 
sieht: jep stimmt. die vorgegebenen ADC Werte 0 und 1023 werden genau 
auf die gewünschten Werte 1000 und 2000 umgerechnet.

Ein kleines Problem gibt es noch. Der ADC WErt kann maximal 1023 werden. 
1023 mal 1000 ist aber zu groß für eine int Berechnung. Macht aber nix, 
der µC hat ja Zeit, lassen wir ihn einfach 32 Bit rechnen.
1
  OCR1A = ADCW * 1000L / 1023 + 1000;

und schon braucht kein Mensch mehr den Widerstand und der Wertebereich 
des ADC wird vollständig ausgenutzt.


Und sowas
1
  TCCR1A = 0b10100010;
2
  TCCR1B = 0b00011010;
will ich gleich gar nicht gesehen haben. Die Bits haben NAMEN! Atmel hat 
keine Kosten und Mühen gescheut, dir diese Namen auch im Programm zur 
Verfügung zu stellen. Siehe zb hier
FAQ: Timer

(und für den ADC gilt dasselbe)

: Bearbeitet durch User
von holger (Gast)


Lesenswert?

>Prinzipiell eine frage, muss ich in der Software, oder der Hardware nach
>der Lösung des Problems suchen?

Software.
1
  while (1)
2
  {
3
    ADMUX = 0b00000000;
4
    ADCSRA = 0b11100010;
5
    OCR1A = ADCW*2;
6
  }

Du wartest nicht auf das Ende der AD Wandlung und prügelst
dauernd Daten in OCR1A rein ohne auch mal das Ende einer
PWM Periode abzuwarten. ADMUX musst du nur neu beschreiben
wenn du den Kanal umschalten willst.

Fazit: So wird das nichts.

von Karl H. (kbuchegg)


Lesenswert?

holger schrieb:
>>Prinzipiell eine frage, muss ich in der Software, oder der Hardware nach
>>der Lösung des Problems suchen?
>
> Software.
>
>
1
>   while (1)
2
>   {
3
>     ADMUX = 0b00000000;
4
>     ADCSRA = 0b11100010;
5
>     OCR1A = ADCW*2;
6
>   }
7
>
>
> Du wartest nicht auf das Ende der AD Wandlung und prügelst
> dauernd Daten in OCR1A rein ohne auch mal das Ende einer
> PWM Periode abzuwarten. ADMUX musst du nur neu beschreiben
> wenn du den Kanal umschalten willst.
>


Da fällt mir ein, ich wollte ja noch einen Link zum ADC-Tutorial posten, 
habs aber dann doch verschwitzt.

AVR-GCC-Tutorial/Analoge Ein- und Ausgabe


> Fazit: So wird das nichts.

Ich hab mir jetzt nicht die Mühe gemacht, und seine Konfigurationsbits 
auseinander gedröselt um nachzusehen, welchen PWM Modus er nutzt und ob 
dort OCR1A automatisch erst beim TOP Wert upgedatet wird.

: Bearbeitet durch User
von Seggel (Gast)


Lesenswert?

Hallo Karl Heinz (oder nur Heinz),
zuerst einmal vielen dank für die Einführung in zwischenmenschliches bei 
Programmieren. Hatte ich in diesem Umfang noch nie.

Die Formel ist für mich nachvollziehbar und erklärt auch alles weitere 
zum Thema Poti und Widerstände. Der Zahlenbereich von 0 bis 1023 ist 
auch klar (1024 Werte sind 10bit).

Zwei fragen erlaube ich mir an dieser Stelle:
Nach dem du erwähnt hast das 1023 mal 1000 zu groß ist für eine int 
Berechung hast du in der Formel 1000L geschrieben. Ist das an dieser 
Stelle für den datentyp long?

Du schreibst das ich die Konfiguration der Register nicht über den 
binären code vornehmen soll, sondern über die Namen der jeweiligen bits. 
Dient das der übersichtlichkeit in Programmen?

Grüße und eine gute nacht

Jens

von Seggel (Gast)


Lesenswert?

Kurzer nachruf es geht, jetzt kann ich alles weitere noch vertiefen zu 
dem Thema

von Karl H. (kbuchegg)


Lesenswert?

Seggel schrieb:

> Zwei fragen erlaube ich mir an dieser Stelle:
> Nach dem du erwähnt hast das 1023 mal 1000 zu groß ist für eine int
> Berechung hast du in der Formel 1000L geschrieben. Ist das an dieser
> Stelle für den datentyp long?

C-Buch
oder
FAQ: Welche Datentypen haben Konstanten
Welche_Datentypen_haben_Konstanten

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Seggel schrieb:

> Du schreibst das ich die Konfiguration der Register nicht über den
> binären code vornehmen soll, sondern über die Namen der jeweiligen bits.
> Dient das der übersichtlichkeit in Programmen?

Ja.
Und es dient auch dazu, sich selbst und anderen eine Menge Sucharbeit zu 
ersparen.
Denn im Datenblatt sind die Erklärungen an die Bitnamen gekoppelt.
Will ich also wissen, was zb
1
ADCSRA = 0b11100010;
alles macht, dann muss ich erstens erst mal ergründen welche Bits denn 
eigentlich auf 1 gesetzt sind und zweitens kann ich dann erst mit den so 
ermittelten Namen in die Doku gehen und die Beschreibung dazu lesen.
Bei vielen Bitnamen kann ich mir das Nachlesen dann auch ersparen, weil 
man die Namen mit der Zeit auswendig kennt. So macht das Bit mit dem 
Namen ADLAR bei allen µC aus der AVR Reihe dasselbe. Es sitzt aber nicht 
bei allen AVR-Prozessoren an derselben Stelle im ADCSRA Register.

: Bearbeitet durch User
von Seggel (Gast)


Lesenswert?

Also gut,
das mit dem L hinter der 1000 habe ich verstanden. Das steht tatsächlich 
für den datentyp long. Allerdings steht das leider nicht in meinem Buch 
C von A bis Z. Oder zumindest nicht im kapitel mit dem datentyp long. 
Ich habe mir das aus den FAQ die verlinkt wurden erlesen.

Und das mit den Bitnamen sehe ich auch ein. Ergibt sinn. Obwohl ich 
gestehen muss das ich dachte meine schreibweise wäre übersichtlicher. 
Das werde ich mir aber auch noch aneignen.
Vielen dank für die Hilfestellung das hat mir sehr viel weitergeholfen.

Grüße Jens

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.