Forum: Compiler & IDEs ADC zyklisch abfragen und gleichzeitig PWM generieren


von Tom (Gast)


Lesenswert?

Hallo zusammen,

ich möchte gerne in einer fest eingestellten Zeit eine AD Wandlung
vornehmen und infolge dieses Wertes das Tastverhältnis eines PWM Signal
mit einer def. Frequenz von 100Hz erzeugen. Das ganze soll also eine
Samplerate von 10S/s haben.

Ich benutze einen ATMega8 mit 4MHz Takt.

Ich habe mir also einen Timer genommen und die Samplerate eingestellt.
Das heißt alle 0,1s wird eine Interruptroutine ausgeführt und die AD
Wandlung vorgenommen. Soweit ist das ganze nicht so schwer. Nun will
ich ja aber das PWM mit einer festen Frequenz von 100Hz generieren. Die
genaue Frequenz kann ich aber mit der PWM Funktion der eingebauten Timer
nicht realisieren(habs nicht hinbekommen).Darum nehme ich also einen
zweiten Timer der beim Überlauf immer einen komplimentären Zustand an
dem Ausgabepin erzeugt.
Da ich aber für beide Timer die Interrupt Routine verwende kommmen
manchmal ganz komische Sachen am Ausgang heraus auch wenn ich das
Eingangssignal nicht verändere. Ich schätze die Interrupts
überschneiden sich.

Kann man dieses Phänomen unterdrücken oder funzt das mit der hier
beschriebenen Methode nicht ???

Vielen Dank schonmal
Grüße Tom

von Jörg Wunsch (Gast)


Lesenswert?

Warum solltest Du die 100 Hz nicht in Hardware erzeugen können?

Ich hab's selbst noch nicht gemacht, aber wenn ich mir die
Beschreibung durchlese, kannst Du den TOP-Wert mittels OCR1A auf 39999
festsetzen und den PWM-Wert mit OCR1B einstellen.  Damit hättest Du
eine Taktteilung durch 40000, was 100 Hz in der Ausgabe macht
(operation mode 15).

von Tom (Gast)


Lesenswert?

Hallo Jörg,

ich hab mich einmal etwas näher mit der Hardwaremöglichkeit
beschäftigt. Das stimmt das man ein PWM Siganl auf die Weise mit einer
festen Frequenz erzeugen kann. In der Beschreibung steht, dass wenn man
eine feste Frequenz erzeugen will, das TOP value in ICR1 schreiben
soll(Mode14)und der Vergleichswert in OCR1A.
So habe ich das wenigstens verstanden und folgendermaßen
implementiert.

#include <avr/io.h>
#include <inttypes.h>


DDRB|(1<<PB1);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
TCCR1A=(1<<WGM11)|(1<<COM1A0);
ICR1=39999;
OCR1A=20000;


int main(void)
{
  while(1)
  ;
}

Aber es tut sich am Port OC1/PB1 garnichts. Habe ich vielleicht noch
eine Kleinigkeit übersehen???

Grüße Tom

von Mike (Gast)


Lesenswert?

//36kHz Träger
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11);
TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10);
OCR1A = 111;
ICR1 = 222;

Nur zur Anregung, ist für einen ATMega8 mit 8MHz und arbeitet. Der Pin
muss nicht als Ausgang definiert werden, die Ausgabe erfolgt auf OC1A.

von leo9 (Gast)


Lesenswert?

@mike:
>> Der Pin muss nicht als Ausgang definiert werden, die Ausgabe
>> erfolgt auf OC1A.
Das ist aber ein Irrtum, wenn der Pin nicht als Ausgang definiert wird
kommt kein Signal heraus.

grüße leo

von Jörg Wunsch (Gast)


Lesenswert?

Genau da sehe ich auch Toms Fehler liegen:

DDRB|(1<<PB1);

Das ist ein ziemlich unnützes Statement (gibt das denn keine
Warnung?).  Gemeint war sicher:

DDRB |= (1 << PB1);

von Tom (Gast)


Lesenswert?

Hallo zusammen,

also ich denke auch dass der Pin schon als Ausgang definiert werden
muss. Wie auch immer schaden kann es denke ich nichts. Allerdings ist
mir der Fehler bei genauerem hinsehen auch aufgefallen, aber ich habe
keine Fehlermeldung bekommen.(DDRB oder gleich muss es natuerlich
heissen.)

@Mike:
Kannst du damit auch das Tastverhaeltnis aendern. Ich habe das auch
hinbekommen dass ich die richtige Frequenz an OC1A bekomme allerdings
konnte ich das TV nicht veraendern(es war immer 50%).


Gruesse Tom

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.