Pwm über Poti mit Mega8 in Bascom

Gast #2347043
Lesenswert?

Hi,
bin neu im Programmieren von Basic und hab gerade ein immenses problem 
mit der Ansteuerung der Pwm über ein Poti. Hab schon etliche Sachen 
ausprobiert, aber nichts hat wirklich gefruchtet. Möchte die Pwm in 5 
Stufen haben, also 0%, 25%, 50%, 75% und 100%. Hat jemand eine Idee wie 
man so was hinbekommt bzw. ob dies mit Basic oder überhaupt realisierbar 
ist. Auf überhebliche oder ironische Antworten wird verzichtet. An alle 
anderen die mir nützliche Tipps bzw. Infos liefern können, schon mal im 
Vorraus ein herzliches Danke.

MfG
Eddy
#2347073
Lesenswert?

Hi,

keine große Sache und als Einsteigerprojekt geeignet....

Neben dem Stichwort PWM musst du dich mit der Sache ADC vertraut machen, 
denn was du eigentlich brauchst ist:

Ein Poti welches die Spannung auf den ADC gibt.
Eine Firmware, die den Registerwert des ADCs in das Register der PWM 
schiebt.
Eventuell durch 4 Teilen falls du 8Bit PWM bei 10Bit ADC nutzt...

Sitze leider gerade am falschen PC sonst würde ich dir ein Code Snippet 
mitschicken...

Gruß
Jochen
Gast #2348047
Lesenswert?

Morgen,
mein programm sieht bis lang so aus:

$regfile = "m8def.dat"
$crystal = 8000000
$baud = 19200
$hwstack = 32
$swstack = 16
$framesize = 40

Config Adc = Single , Prescaler = Auto
Start Adc

Dim Analogwert As Word

Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Compare B 
Pwm = Clear Down , Prescale = 1
Enable Timer1
Start Timer1

Pwm1b = 0

Analogwert = Getadc(0)
Pwm1b = Analogwert

End

Hab ich hier irgendeinen Fehler gemacht? Hab dies mit Hilfe der BASCOM 
AVR Help Reference geschrieben. Wäre sehr dankbar wenn mir jemand weiter 
helfen könnte.

MfG
Eddy
Gast #2348054
Lesenswert?

Hallo Eddy,

das sieht schon gut aus, nur fehlt eine Endlosschleife.
Es wird einmal eine ADC-Wandlung durchgeführt und der Wert als PWM-Wert 
übergeben und danach rennt der ProgrammCounter ins Leere.

Und weiterhin bist du weit über dein Ziel hinausgeschossen - aus der 
5-Stufen-PWm wurden jetzt fast 1000


Gruß Limloz
Gast #2348081
Lesenswert?

Habe den Wert auf 8bit gestellt, Das tastverhältnis Pwm1b =64.
Zudem:

Do
Analogwert = Getadc(0)
Pwm1b = Analogwert
Loop

Funktioniert leider nicht so recht-.-

Zum besseren verständnis mein aufbau:
Das Poti ist mit einem Patchkabel am Pin 23 (ADC0) des mega8 
angeschlossen.
Von Pin 16 (OC1B) führt ein patchkabel zu einem uln2803a (Darlington). 
Und zu guter letzt noch eins zur Pwm Leitung des Lüfters.
Gast #2348097
Lesenswert?

8Bit sind 256 Stufen, und wenn Du die PWM auf 8Bit setzt, dann müsstest 
Du den ADC auch auf 8Bit bringen, sonst hat das merkwürdige Effekte.

Wenn Du ein einen Bereich in nur 5 Stufen auswerten willst, bei 
angenommenen 10Bit für ADC & PWM:

ADC-Wert = ADC-Wert / 204
PWM-Wert = ADC-Wert * 204

Dann baut man allerdings noch eine Hysterese ein, damit das "flattern" 
an den Umschaltpunkten unterbleibt. Aber das wird noch ein bisserl 
komplexer, schau' erstmal das die einfachsten Sachen laufen.
Gast #2348139
Lesenswert?

Das sieht demnach so aus:

Config Adc = Single , Prescaler = Auto
Start Adc

Dim Analogwert As Word

Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Compare B 
Pwm = Clear Down , Prescale = 1
Enable Timer1
Start Timer1

Analogwert = 1023 / 204
Pwm1b = 1023 * 204

Do
Analogwert = Getadc(0)
Pwm1b = Analogwert
Loop

End

Ist das korrekt oder muss man da noch was verändern?
Gast #2348160
Lesenswert?

EazyEddy schrieb:
> Ist das korrekt oder muss man da noch was verändern?

Nein, das ist nicht richtig. Die Rechnung muss nach GetADC() in der 
Schleife ausgeführt und dann der errechnete Wert jeweils an die PWM 
übergeben werden.

> Analogwert = 1023 / 204
> Pwm1b = 1023 * 204

Das macht keinen Sinn, schau' Dir nochmal meine Berechnung an und denk' 
drüber nach.
Gast #2348169
Lesenswert?

Demnach müsste das ganze dann so aussehen:

Config Adc = Single , Prescaler = Auto
Start Adc

Dim Analogwert As Word , Pwm1 As Word

Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Compare B 
Pwm = Clear Down , Prescale = 1
Enable Timer1
Start Timer1

Pwm1b = 0

Do
Analogwert = Getadc(0)
Analogwert = Analogwert / 204
Pwm1 = Analogwert * 204
Pwm1b = Pwm1
Loop

End

Fail???
Gast #2348194
Lesenswert?

Bei 100%:
1023/204=5,01470882352941*204=1023
Bei 50%:
512/204=2,509803921568627*204=512

Und wo hat sich jetzt der fail versteckt? xD

Spass beiseite dieses Thema ist mir ziemlich ernst
und ich steig da nich so durch!
#2348202
Lesenswert?

EazyEddy schrieb:
> Bei 100%:
> 1023/204=5,01470882352941*204=1023
> Bei 50%:
> 512/204=2,509803921568627*204=512
>
> Und wo hat sich jetzt der fail versteckt? xD

Ich geb dir eine Analogie. Denn eben weil das so wichtig ist, musst du 
selbst drauf kommen.

Angenommen du hättest Zahlen von 1 bis 100

0, 1, 2, 3, 4, 5, ...,, 98, 99, 100

Die dividierst du jetzt erst mal durch 10. Und zwar ganzzahlig! Also 
keine Kommastallen.

Alle Zahlen von 0 bis 9 ergebn, wenn man sie durch 10 dividiert eine 
glatte 0.

Alle Zahlen von 10 bis 19 ergeben eine glatte 1
Alle Zahlen von 20 bis 29 ergeben eine glatte 2
....

soweit klar?

Wenn du nun dieses Zwischenergebnis wieder mit 10 multiplizierst, was 
ergibt sich dann.
Nun 0 mal 10  ist wieder 0
    1 mal 10  ist wieder 1
etc.

Das sollte auch klar sein. Bis hier her ist alles trivial.

Und jetzt fügen wir das alles mal zusammen

Ausgangszahl   / 10   Zwischenergebnis    * 10     Endergebnis
---------------------------------------------------------------
  0                        0                             0
  1                        0                             0
  2                        0                             0
...
  9                        0                             0
 10                        1                            10
 11                        1                            10
 12                        1                            10
...
 19                        1                            10
 20                        2                            20
 21                        2                            20
...
 29                        2                            20
 30                        3                            30
 31                        3                            30
...

merkst du was?

Durch das dividieren durch 10 (ohne Kommastellen) und anschliessende 
Multiplizieren mit 10, hast du etwas erreicht. Nämlich alle Zahlen von 0 
bis 9 ergeben geschlossen 0. Alle Ausgangszahlen von 10 bis 19 ergeben 
geschlossen 10, usw. usw.

Was du also gemacht hast: Du hast die Ausgangszahlen von 0 bis 99 in 10 
Bereiche eingeteilt, wobei die Bereiche auch wieder von 0 bis 90 laufen, 
aber die Ausgangszahlen sauber in diese Bereiche eingepasst werden.
Gast #2348207
Lesenswert?

es ist auch keine Formel verkehrt, aber dumerkst doch sicher auch 
selber, das etwas anderes herauskommt, als du willt.


>Analogwert = Getadc(0)
>Analogwert = Analogwert / 204
>Pwm1 = Analogwert * 204
>Pwm1b = Pwm1

wenn man die sinnlose Rechnerei kürzt steht da:

Pwm1b = Getadc(0)

damit liegen wieder die 10 bit an der PWM.
#2348210
Lesenswert?

Edit:

Und nein. Du musst nicht durch die gleiche Zahl dividieren mit der du 
auch multiplizierst. Indem du die beiden Zahlen geeignet wählst, kannst 
du auch den Zahlenbereich 0 bis 1023 (die Werte, die du vom ADC 
bekommst) zb in den Wertebereich 0 bis 255 (so wie sie eine 8 Bit PWM 
haben will) umrechnen, wobei sich eine von dir gewünschte Anzahl an 
'Stufen' ergibt.


> 1023/204=5,01470882352941*204=1023
> 512/204=2,509803921568627*204=512

Dein Fehler besteht darin, dass du ganz automatisch davon ausgehst, dass 
in einem Computer alles mit Nachkommastellen gerechnet wird. Dem ist 
aber nicht so.
Gast #2348225
Lesenswert?

Karl Heinz Buchegger schrieb:
> Dein Fehler besteht darin, dass du ganz automatisch davon ausgehst, dass
> in einem Computer alles mit Nachkommastellen gerechnet wird. Dem ist
> aber nicht so.

Es ist mir schon bewusst. War eben nur ein dummer fehler von mir.
Programmier jetzt schon über 1 Woche an der Pwm rum und mein Kopf lässt 
mich langsam im Stich.
#2348243
Lesenswert?

EazyEddy schrieb:
> Karl Heinz Buchegger schrieb:
>> Dein Fehler besteht darin, dass du ganz automatisch davon ausgehst, dass
>> in einem Computer alles mit Nachkommastellen gerechnet wird. Dem ist
>> aber nicht so.
>
> Es ist mir schon bewusst. War eben nur ein dummer fehler von mir.
> Programmier jetzt schon über 1 Woche an der Pwm rum und mein Kopf lässt
> mich langsam im Stich.

Hinweis.
In meiner Tabelle findet sich die Anzahl der Stufen bei dem 
Zwischenergebnis wieder.

Wenn du also 5 Stufen haben willst, dann sorg dafür dass dein 
Zwischenergebnis aus den Zahlen 0, 1, 2, 3, 4 bestehen kann und aus 
sonst nichts. Wenn also der ADC Werte von 0 bis 1023 liefert, wodurch 
musst du diesen Wert dividieren, damit da nur die Zahlen 0, 1, 2, 3, 4 
rauskommen können? (Dazu gehst du am besten von der Zahl 1024 aus und 
verusuchst die so zu dividieren, dass da 5 rauskommt. Denn du willst ja 
haben, dass sich deine 5 Bereiche gleichmässig auf die ADC Werte 
verteilen)

Hast du dein Zwischenergebnis, dann wird von dort auf die PWM 
umgerechnet. Die PWM-Stufe (ich geh jetzt mal von einer 8-Bit PWM aus) 
möchte Werte von 0 bis 255 (weil sie ja 8 Bit ist). Du hast die Zahlen 
0, 1, 2, 3, 4. Womit musst du die daher multiplizieren, damit sich 
daraus Zahlen ergebn die im Bereich 0 bis 255 liegen? (Wieder: womit 
musst du 5 multplizieren, damit da möglichst 256 rauskommt. Denn auch 
wieder: du willst eine gleichmässige Aufteilung).


Übrigens: Mit Excel lässt sich am PC das alles ganz wunderbar für jede 
einzelne Zahl, die vom ADC kommen kann, erst mal durchspielen. Da kannst 
du dir für jede Zahl ansehen, was bei deiner Berechnung rauskommen wird 
(und natürlich auch die Zwischenwerte, damit du auch verfolgen kannst, 
wie sich das Endergebnis ergibt)
Gast #2348257
Lesenswert?

EazyEddy schrieb:
> Do
> Analogwert = Getadc(0)
> Analogwert = Analogwert / 204
> Pwm1 = Analogwert * 204
> Pwm1b = Pwm1
> Loop

Das ist schon ok so, Du musst nur hier aufpassen:

> Config Adc = Single , Prescaler = Auto

Ich setze voraus, daß das Poti an VCC & GND angeschlossen ist, es 
liefert damit zwischen 0..5V an den ADC Eingang. Wenn der ARef-Pin nicht 
beschaltet ist, dann sollte die Config-Zeile so aussehen:

Config Adc = Single , Prescaler = Auto , Reference = AVCC

Wenn dagegen der ARef-Pin am µC mit VCC verbunden ist (was man vermeiden 
sollte), dann reicht Deine ursprüngliche Config-Zeile.

Und lass das weg:

> Enable Timer1

Das schadet zwar hier nicht, ist aber sinnlos. Damit wird der 
Timer-Overflowinterrupt erlaubt, hast Du aber nicht.
#2348258
Lesenswert?

EazyEddy schrieb:
> Limloz schrieb:
>> wenn man die sinnlose Rechnerei kürzt steht da:
>> Pwm1b = Getadc(0)
>
> Das lässt aber komischer weise nicht kompilieren.

Tja. das ist BASCOM.
Das hat so seine Schwächen wenn es um die Formulierung von Berechnungen 
geht. In einer anderen Programmiersprache wäre das kein Problem.


> Nur das geht:
>
> Analogwert = Getadc(0)
> Pwm1b = Analogwert

Das ist aber im eigentlichen Sinne nicht das was du willst. Du wolltest 
ja 5 PWM Bereiche haben. So geht die Potistellung 1:1 auf die PWM durch 
und du hast keine Bereiche. Die PWM wird natürlich mit der Potistellung 
mitgehen, aber eben in genau der Abstufung, die du vom ADC hast. Also 
1024 Bereiche und nicht 5.
Wenn du 5 Bereiche haben willst, dann musst du die Zahlen so bearbeiten, 
dass sich das ergibt. Das Handwerkszeug dazu hast du ja jetzt. Im Grunde 
besteht der Trick darin, dass man bei der Division die Nachkommastellen 
wegfallen lässt. Das ist der entscheidende Punkt, der diese Umrechnung 
möglich macht.
Gast #2348259
Lesenswert?

EazyEddy schrieb:
> Limloz schrieb:
>> wenn man die sinnlose Rechnerei kürzt steht da:
>> Pwm1b = Getadc(0)
>
> Das lässt aber komischer weise nicht kompilieren.
> Nur das geht:
>
> Analogwert = Getadc(0)
> Pwm1b = Analogwert


Das soll ja nicht die Lösung für dein Problem sein, sondern durch kürzen 
lediglich aufzeigen, dass deine Rechnerei keine Skalierung durchführt.
#2348265
Lesenswert?

Limloz schrieb:
> EazyEddy schrieb:
>> Limloz schrieb:
>>> wenn man die sinnlose Rechnerei kürzt steht da:
>>> Pwm1b = Getadc(0)
>>
>> Das lässt aber komischer weise nicht kompilieren.
>> Nur das geht:
>>
>> Analogwert = Getadc(0)
>> Pwm1b = Analogwert
>
>
> Das soll ja nicht die Lösung für dein Problem sein, sondern durch kürzen
> lediglich aufzeigen, dass deine Rechnerei keine Skalierung durchführt.

Nur das in seinem Beispiel

>Analogwert = Getadc(0)
>Analogwert = Analogwert / 204
>Pwm1 = Analogwert * 204
>Pwm1b = Pwm1

die 'sinnlose' Rechnerei durchaus einen Effekt hat und somit ganz und 
gar nicht sinnlos war.
Gast #2348318
Lesenswert?

Also wenn ich jetzt hier beim ADC von 0-1023 arbeite müsste das doch so 
gehen:
           /204  *204
 0-203     = 0  =  0
 204-407   = 1  = 204
 408-611   = 2  = 408
 612-815   = 3  = 612
 816-1019  = 4  = 816
(1020-1023 = 5  = 1020)?
#2348332
Lesenswert?

>          /204  *204
> 0-203     = 0  =  0
> 204-407   = 1  = 204
> 408-611   = 2  = 408
> 612-815   = 3  = 612
> 816-1019  = 4  = 816
>(1020-1023 = 5  = 1020)?

Na das sieht doch schon prinzipiell gut aus!

Jetzt musst du nur noch überlegen, ob das deine Forderung
> 0%, 25%, 50%, 75% und 100%
erfüllt oder nicht, bzw. wie du die Zahlenwerte anpassen musst, damit es 
das tut.

Du willst wahrscheinlich
1
  ADC        0  ...................  ...............                     1023
2
  -----------------------------------------------------------------------------
3
  PWM in %   0  0  0  ... 25 25 25 ...  50 50 50 ... 75 75 75 ... 100 100 100
4
  PWM als Wert  0     ...   256    ...     512   ...   768    ...    1023

und dafür musst du jetzt eine Umrechnung finden, so dass die 100% PWM 
nicht erst bei einem ADC Wert von 1023 erreicht werden sondern schon 
früher.
Denn die 100% sollen ja wahrscheinlich nicht erst dann kommen, wenn du 
das Poti an den rechten Anschlag gedreht hast, sondern die Stufen sollen 
sich gleichmässig auf den Potiweg verteilen. Aber vielleicht sollen sie 
das auch nicht - du bist der Programmierer, du entscheidest. Wie immer 
du das haben willst, das ist per Definition richtig.
#2348347
Lesenswert?

EazyEddy schrieb:
> Karl Heinz Buchegger schrieb:
>> Jetzt musst du nur noch überlegen, ob das deine Forderung
>>> 0%, 25%, 50%, 75% und 100%
>> erfüllt oder nicht, bzw. wie du die Zahlenwerte anpassen musst, damit es
>> das tut.
>
> sieht mir eher nach 0,20,40,60,80,100 aus, da es jetzt von 0 bis 5 geht
> statt von 0 bis 4^^
>
> Aber ich komme lagsam dahinter. Danke.

Ich bin sicher du kriegst es jetzt alleine hin.

Und du hast sicher auch schon eines bemerkt: Es hilft, wenn man sich 
neben die Tastatur einen Zettel und Bleistift legt, mit dem man solche 
Zahlenspielereien durchprobieren kann :-)

Das glauben nämlich viele auch nicht. Aber in der Programmierung ist 
Vorbereitung das halbe Leben. Wenn ich etwas nicht mit Papier und 
Bleistift lösen kann, kann ich es auch nicht programmieren. Papier und 
Bleistift haben aber den Vorteil, dass ich leicht die Dinge variieren 
kann und mir an konkreten Zahlen die Dinge verdeutlichen kann. Und zwar 
in meiner Sprache, zb in Form von Diagrammen oder in Form von Tabellen, 
und nicht in einer abstrakten Programmiersprache.
Gast #2348379
Lesenswert?

Karl Heinz Buchegger schrieb:
> Jetzt musst du nur noch überlegen, ob das deine Forderung
>> 0%, 25%, 50%, 75% und 100%
> erfüllt oder nicht, bzw. wie du die Zahlenwerte anpassen musst, damit es
> das tut.

Stimmt, hab's zwar aufgemalt, bin trotzdem reingefallen. Was hier 
erschwerend dazukommt, ist daß beim Schema 0/25/50/75/100 die 100% PWM 
bereits bei 4V ADC kommen müssen, es also eine Transformation mit 
gleichzeitiger Begrenzung des Wertes nach oben werden muss, also:

pwm_val = adc / 204 * 256
wenn pwm_val > 1023 dann pwm_val = 1023

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren