PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATMEGA32 ADC PWM



karthago
27.03.2007, 10:15
Hallo !

ich möchte mit einem ATMEGA32 ein PWM signbal erzeugen,

ich hab diese Übertragungsfunktion:

Y= 2,5 X - 0,75

Y: PWM Duty Cycle

0% PWM = 0,3 < Y < 100% PWM = 0,7

X: Sensorspannung

kann mir bitte jemand helfen ??

Merci

wkrug
27.03.2007, 10:23
Die PWM Funktion läuft normalerweise im Timer 1 des ATMEGA32 und erwartet dort Werte zwischen 0 und (2^16)-1 für 0 bis 100% Duty Cycle.
Wenn Du also deine Formel mit einem Multiplikator von (2^16/100) versiehst sollte das eigentlich passen, obwohl ich den zweiten Teil deiner Formel nicht ganz verstehe.

karthago
27.03.2007, 10:27
meinst du die -0,75 ??

wkrug
27.03.2007, 10:45
meinst du die -0,75 ??
Nein ich meinte die zweite Formel
0% PWM = 0,3 < Y < 100% PWM = 0,7 ????

Mit der Information über das Comparematchregister solltest Du aber trotzdem die nötigen Werte berechnen können.

karthago
27.03.2007, 10:59
achso , ich möchte einen Fan Management Bauteil ersetzen (MIC502) die werte habew ich vom Datasheet genommen.

kannst du mir bitte eklären was du mit 2^16/100 meinst und comparematchregister meinst, bin beginner :(

wkrug
27.03.2007, 11:16
Also noch mal ganz von vorne.

Man bringt den Timer 1 in einen der verschiedenen PWM Modi.
Welchen PWM Mode Du brauchst musst Du anhand des Datenblattes selber rausfinden.
Dann wird ein Comparematchregister z.B. Comp1A mit einem Wert zwischen 0 und 65535 gefüttert.
Der Wert steht dann im direkten Zusammenhang mit der ausgegebenen Pulsbreite. Also 0 ist dauerhaft Low 65536 ist dauerhaft High.
Man kann aber auch invertet PWM machen die Puls Pausen verhältnisse sind dann umgekehrt.
Die Werte dazwischen produzieren dann die entsprechende Pulsweite.
Das ganze Spiel läuft nach der Konfiguration Hardwaremäßig ab und ist im Datenblatt des Controllers wirklich gut und umfangreich beschrieben.
Die Impulse kommen dann üblicherweise am OC1A Pin des Controllers raus.

Zum Ändern der Pulsweite muss das COMP1A dann nur wieder mit neuen Werten belegt werden. Auch dabei kann es zu sog. Glitches = Phasenfehlern kommen (Steht auch im Datenblatt). Wenn dich das aber nicht stört musst Du dagegen auch nichts unternehmen.

Als Tipp aus der Praxis kann ich Dir noch mitgeben, das Du an deinen Controller keine Großen Lasten hängst (LED's usw.) . Sonst wird je nach Belastung des Controllers die PWM Spannung schwanken.
Ist es trotzdem nötig höhere Lasen zu schalten solltest Du auf jeden Fall Treiber z.B. Mos Fet's oder integrierte Treiberbausteine verwenden.

karthago
27.03.2007, 11:26
@wkrug,

merci, ich werde die Datenblatt nochmal lesen und versuchen

karthago
27.03.2007, 14:35
laut der Datenblatt des FAN-Bauteil MIC502:

Vt = 0,7 Vcc = Vpwm max ( 100 % dutyCycle)
Vt = 0,3 Vcc = Vpwm min ( 0% duty Cycle )

Vt = die digitale Spannung die vom Sensor kommt
Vcc= 5 V

wie kann ich bitte das in c schreiben
bin total durcheinander :-s

wkrug
27.03.2007, 17:30
Also die Spannung die vom Sensor kommt liegt zwischen 0,3 und 0,7V

diesen Wert solltest Du auf einen A/D Wandler legen, von denen der ATMEGA 32 8 Stück on Bord hat.
Der ATMEGA 32 hat eine interne Referenzspannungsquelle die 2,56V hat.
Also liefert eine Spannung von 2,56V einen A/D Wandlerwert von 1023.
Eine Spannung von 0,3V dürfte einen Wandlerwert 120 erzeugen.

Eine Spannung von 0,7V liefert einen Wandlerwert von 280.

Also du nimmst die werte vom A/D Wandler und ziehst 120 ab.
Nun teilst Du 65536 durch 280-120 und kommst damit auf den Skalierungsfaktor von ca. 410.

Also lautet deine Formel

PWM_Wert=(A/D_Wandlerwert-120)*410

Mit diesem Wert fütterst du das COMP1A Register und die Sache ist erledigt.

Du musst dann nur noch Wandler Werte <120 und PWM Werte über 65535 abfangen (if Abfragen) und dann sollte alles passen.
Was mich dabei noch ein wenig stört ist die etws grobe Abstufung der einzelnen Schritte - 160 insgesamt.
Aber wenn ich mich recht entsinne haben die A/D Wandler einen integrierten Vorverstärker mit dem man die 0,7V auf 1,4 oder gleich 2,1 V bringen könnte, was einer Verdopplung bzw. Verdreifachung der Auflösung bedeutet.

Mit dem ins Datenblatt schauen hab ich eigentlich das Datenblatt des ATMEGA 32 gemeint.

Ein komplettes C-Programm kann ich Dir jetzt nicht liefern.
Erstens Progge ich in Codevision AVR.
Zweitens ist mir das jetzt auch zu viel Arbeit.

karthago
28.03.2007, 20:59
@wkrug:
vielen Dank für Deine Antwort

Also der Sensor liefert eine Spannung die zwischen 0,5 und 4,5 V
ich will diese Spannung in Digital umwandeln, als refrenz Spannung habe ich Vcc genommen und die beträgt 5V
Dann
wenn Der Result vom ADC adc_result / VCC = 0,7 --> PWM Duty cycle = 100%
wenn ADC_result / VCC = 0,3 ---> PWM Duty cycle = 0%

dh 0.3 < ( adc_result / VCC) < 0,7

so muss das PWM Signal erzeugt

PWM frequenz soll 300 Hz sein

ich hoffe dass ich gut erklären konnte

Viele Grüße

jar
28.03.2007, 22:34
.............
ich hoffe dass ich gut erklären konnte
Viele Grüße

nö, hab kein Wort verstanden, aber ein funktionierendes PWM hab ich

LED Hintergrundbeleuchtung fürs Display + Kontrasteinstellung

Hz weiss ich nicht mal (100Hz?) müsste ich am Di auf dem Oszi schauen

OCRA1 macht LED über Treibertrasi
OCR1B macht D/A Wandlung über R/C auf Vo Display -> Kontrast

eingestellt wird es noch per RC5, später Taster oder Touchscreenfolie
eingestellt werden können natürlich beide einzeln, wobei mr bis jetzt Kontrast max am besten gefällt, nahe 0V, und der ADC0 misst die Ub, Ref LM4040 1%, Teiler von Ub 24k/12k = 1/3 gibt bei 5V und 1023max um 670 mul mit Scaler 0,07xxxx und mul mit 100 gibt schöne 500 integer für 5V , nun noch den Dezimalpunkt per Stringfunktion einfügen, irgendwie ist dieses C nicht wirklich mathe tauglich , habe mit float und double in ftoa kein richtigen Erflg gehabt, aber so gehts auch D)

karthago
29.03.2007, 05:11
.............
ich hoffe dass ich gut erklären konnte
Viele Grüße

nö, hab kein Wort verstanden, aber ein funktionierendes PWM hab ich



sorry,

hier nochmal eine Beschreibung als pdf

wkrug
29.03.2007, 07:54
Also der Sensor liefert eine Spannung die zwischen 0,5 und 4,5 V
Wie Du dann auf die Formel 0.3 < ( adc_result / VCC) < 0,7 kommst ist mir zwar schleierhaft, aber ich muß ja nicht alles verstehen.

Die PWM Frequenz ergibt sich aus der (Taktfrequenz / 65536)/ eingestellten Prescale Faktor. Das Alles für Timer 1.

Hau mich jetzt nicht wenns nicht stimmt - kann auch sein das man noch durch 2 teilen muß.

Die PWM Frequenz ist also bei hardwaremässiger Ansteuerung nicht frei einstellbar ! Näherungsweise solltest Du aber hinkommen.
Durch geschickte Auswahl des Quarzes sollte es auch möglich sein, die gewünschte PWM Frequenz genau zu treffen.

avion23
29.03.2007, 13:22
Hallo Kathargo,
ich glaube du hast da etwas falsch verstanden. Ich habe das Datenblatt kurz überflogen. So wie ich das sehe, regelt der Lüfter sich selbst und zwar per pwm.
Das Regelsignal selbst ist kein pwm-signal! sondern gleichstrom. Dieses kannst du zwar auch per pwm erzeugen, aber musst es noch filtern (und ich finde es sinnlos).

Der Lüfter hat bei 0.3V einen duty cycle von 0%, bei 0.7 sind es 100%, der Zwischenraum wird linear aufgeteilt. Wenn du diesen Lüfter abhängig von der Temperatur steuern willst, dann lies die letzten Zeilen. Dort wird die Verwendung eines NTC-Sensors angesprochen.

Wenn du einen Lüfter per mikrocontroller regeln willst: Google ist dein Freund. Am interessantesten scheint ein step-down Wandler zu sein, weil moderne Lüfter eine interne Elektronik zum Ansteuern der Spulen haben und es Probleme mit reiner PWM gibt. Dabei regelst du aber die Versorgungsspannung und kannst damit jeden beliebigen Lüfter regeln.

Wenn du wirklich nur diesen einen Lüfter per mikrocontroller regeln möchtest: Schlag nach, wie ein PWM Signal allgemein erzeugt wird. Du hast einen Spielraum von 0V bei 0% duty cycle bis 5V bei 100% duty cycle. Bei 10 Bit = 1024 sind das 5V/1024 = 4,9mV Schritte. Deinen Bereich von 0.3 bis 0.7V kannst du also auf (0.7V-0.3V)/0.0049V = 81 Schritt aufteilen.
In C kannst du Beispielcode für pwm benutzen. Den Bereich, in welchem geregelt wird wirst du wohl anpassen können :)
Auf die Schnell habe ich https://www.roboternetz.de/wissen/index.php/Hallo_Welt_f%C3%BCr_AVR_%28LED_blinken%29
gefunden, dort wird wenigstens die Verwendung von Timern erklärt.

Das zweite Problem (welches ich auch noch nicht gelöst habe):
Wenn du den Wert des PWM Signals misst, erhältst du nur Mist. Wenn die Messung im off-Teil erfolgt, misst du 0V, im on-Teil 5V (in der Realität natürlich nie ganz 0V/5V). Deswegen muss das Signal über einen Tiefpass integriert werden (glaube ich! Da scheitere ich im Moment ;) ).

Ach ja, warum verwendest du eine Frequenz von 300Hz für die PWM? Das ist unnötig langsam.

karthago
29.03.2007, 15:50
Servus Avion
Merci für Deine Antwort,

Eigentlich ich möchte in diesem System :
http://calypsotn.free.fr/System.JPG

http://calypsotn.free.fr/schaltung.JPG

den Bauteil MIC502 (Fan Management ) durch Atmega32 ersetzen, also der µC übernimmt die Aufgabe.

Laut der Datenblatt vom MIC502 (http://www.micrel.com/_PDF/mic502.pdf), wie ich es verstanden habe wenn Vh/Vcc = 0,7 haben wir 100% duty cycle und wenn Vh/Vcc= 0,3 haben wir 0% duty cycle.

ich möchte die Spannung vom Hall-Sensor (Vh) mit ADC eilesen ( 10 Bit mit Ref Spannung Vcc= 5V)

dann diesen Wert ( adc_result) durch 1024 teilen.

0,7 ~ 716 ( 0,7*1024)

wenn adc_result/1024 =~ 716 habe ich ein 100 % duty cycle

so möchte ich mein PWM signal einstellen

wkrug
29.03.2007, 20:12
Ich glaub das mit dem ADC hast Du falsch verstanden.

Wenn Du 5V Referenzspannung verwendest hast du 0,7/(5V/1024) und da kommt dann ~ 143 dabei raus.
Wenn Du die interne Referenz des ATMEGA 32 verwendest kommt 0,7/(2,56V/1024) = 280 raus.

Die komplette Auflösung des Knotens hab ich die eigentlich schon ein paar Antworten früher gegeben ?!

Eine bessere Auflösung könntest Du noch kriegen, wenn Du das Gebersignal 0,3...0,7V mit einem Op Amp um den Faktor von 3,5 Verstärkst.
Legst Du am Verstärker einen Offset von 0,3V an, kann die Verstärkung auch etwas mehr als 6 betragen und du nutzt die Volle Bandbreite des A/D Wandlers aus.

Wenn ich ehrlich bin würd ich aber so eine Aufgabe nicht mit einem Microcontroller lösen.
Warum nimmst Du nicht einfach einen Mehrfach Operationsverstärker? Einer Arbeitet als Sägezahngenerator, ein zweiter als Komperator, an dem an einem Pin die Sägezahnspannung im Bereich von 0,3...0,7V und am Anderen die Spannung vom Sensor auch 0,3...0,7V anliegt ?
Die Schaltung reagiert schneller als das ein Microcontroller je könnte und erfordert auch nicht wesentlich mehr Hardwareaufwand.

avion23
29.03.2007, 23:14
Erstens:
Wenn am Eingang 0.7V anliegen, dann ist dein ADC-Wert = 0.7V/0.0048V = 146. Wenn am Eingang 0.3V anliegen, dann ist ADC = 0.3/0.0048V = 63.

Zweitens:
Ich weiß nicht wie man das konkret löst. Wenn dein PWM Signal z.B. einen 16Bit Wert erwartet wäre es WAHRSCHEINLICH etwas in dieser Richtung:
PWM = 65536 für 100%, 0 für 0%.
Also soll bei 0.7V = 146 am ADC der Wert 65536 in das Register geschrieben werden, bei 0.3V = 63 dementsprechend 0.
Die Differenz zwischen 146 und 63 ist 83.
Also ist die Funktion PWM = 65536 * (ADC-63)/83
Die 63 musst du von ADC abziehen um die 0.3V als Nullpunkt definieren, dann wird (ADC-63)/83 für ADC==146 eins, bei ADC==63 aber null.

Übrigens hättest du doppelt soviele Schritt, wenn du die interne Referenz statt den 5V (die wahrscheinlich auch noch schwanken) verwendest.
Ich glaube aber, dass du eigentlich etwas ganz anderes möchtest. Aber ich komme nicht drauf... deswegen antworte ich auf das, was du gefragt hast.

karthago
30.03.2007, 10:37
Hallo ,
0,7 und 0,3 sind keine Spannung, sie sind das ergebnis vom Vh/Vcc.

ADC = Vh * (1024/Vref)

für Vref= 5V
und wenn ich zb eine Vh von 2,5V hab dann ist ja ADC = 512

Vh/Vcc = 512/1024 = 0,5

= > 0,7 = x / 1024 => 0,7 * 1024 = 716

wkrug
30.03.2007, 16:52
Das oben geschriebene hat damit aber weiterhin Gültigkeit, nur das sich der Skalierungsfaktor ändert.
Du kriegst also somit Wandlerwerte zwischen 307,2 und 716,8 raus.

Deine Formel für den PWM Wert lautet also:

((X*5V/(5V/1024) - 308) * 161

wobei X dann der Faktor von 0,3 bis 0,7 ist.
Die Werte stimmen zwar nicht ganz genau, stellen aber sicher, das 0 bis 100% PWM erreicht werden können.

Werte über 65535 und unter 0 müssen natürlich per Software abgefangen werden.

karthago
02.04.2007, 09:35
kannst Du mir bitte erklären wie Du auf 161 gekommen bist ??

wkrug
02.04.2007, 14:57
65536/(717-307) = 159 + Angstfaktor = 161.

Der A/D Wandler liefert Werte zwischen 307 und 717 (rechnerisch).

Aber ich glaub mit ein bischen Überlegen wärst Du auch selber drauf gekommen.

karthago
04.04.2007, 14:22
Hallo ,

Ich hab diesen Code geschrieben , am anfang gings mit dem PWM Signal aber jetzt kommt nur 0V von PD5 woran kann es liegen dh es gibt kein PWM signal mehr??

MErci


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






#define F_CPU 4433618UL //Oscillator-frequenz in Hz
#define BAUD 19200UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)


/* LED */

#define LED 4 //PIN 5 vom PORTA als LED nennen
#define LED_ON PORTA |= (1 << LED ) //PIN5 HIGH

void init_led (void)
{
DDRA |= (1 << LED); //PIN5 von DDRA als ausgang
}





/* ADC */
#define ADC_PIN 0 //PIN 0 vom PORTA als ADC nennen

void adc_init(void)
{
DDRA &= ~(1 << ADC_PIN); //PIN 0 vom PORTA als Eingang
ADMUX = ADC_PIN; //AD-Wandlerkanal 0 (ADC0) auswählen
ADMUX |= (1<<REFS0); //AVCC als Referenzspannung
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS0); //AD-Wandler einschalten und Prescaler = 32 einstellen
}

#define start_a2d ADCSRA |= (1<<ADSC) //Wandlung starten


/* PWM */

// PORT AND PIN CONFIGURATION


#define PWM_PIN 5


void pwm_init(void)
{
DDRD |= (1 << PWM_PIN);
// normale 10-bit Fast PWM aktivieren (nicht invertiert),
TCCR1A = (1<<COM1A0)|(1<<WGM11)|(1<<WGM10);

// Einstellen der PWM-Frequenz auf 4 kHz (Prescaler = 1024)
TCCR1B = (1<< CS12) | (1<<CS10) |(1<<WGM12);

// Interrupts für Timer1 deaktivieren

TIMSK &= ~0x3c;
}



int main(void) {
uint16_t adc_result;

uint16_t z;
uint32_t y;
init_led();
adc_init();
pwm_init();


while(1)
{
LED_ON;
start_a2d;
while ( !(ADCSRA & (1<<ADIF))); //Warten bis die AD-Wandlung abgeschloßen ist

adc_result = ADCL | (ADCH<<8) ; //AD-Wert auslesen

y = adc_result/1024 ;


z= ((y*1023)/716)*1024;

OCR1A = z;


}


}

wkrug
04.04.2007, 17:23
Miss doch erst mal die Spannung die dein Temperaturfühler abgibt.
Liegt die im zulässigen bereich sollte auch der A/D Wandler vernünftige Werte haben.
Lade das Comparematchregister mit einem festen Wert z.B. 32000.
Dann sollte eine PWM von ca. 50% rauskommen.
Kommt nichts raus, stimmt entweder deine Initialisierung nicht, oder der Port D5 ist defekt. Dann solltest Du aber mal deine Beschaltung an dem Pin überprüfen.
Wenn sich bei 32000 ein PWM Signal einstellt stimmt mit dem ADC Initialisierung, Hardware was nicht, oder in deiner Formel ist ein Fehler.