PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega48 + ADC + PWM



Michael 123
25.02.2009, 18:25
Hallo,

habe mir ein Programm geschrieben, mit dem ich 4 Akku laden kann.
Allerdings zickt das Progrämmchen noch. Ab und zu kommen vom ADC-Wandler Werte, die um 20-40 zu hoch / zu niedrig sind. Bis jetzt habe ich noch keine wiederholbarkeit festellen können.

Jetzt mein Frage:
Da ich ja auch gleichzeitig PWM nutze, kann es sein, dass das PWM dort reinspuckt und den ADC dadurch dureinander bringt?
Ich nutze Hardware PWM.
Dann habe ich noch einen Timer, um alle 10s den ADC zu messen, musste aber dort auch eine Variable einfügen, die hochgezählt wird. Kann es am Interrupt liegen? Das der dann den ADC stört?

Naja, ich hoffe ihr könnt helfen.

Hier noch der Code:


'########################################
'######### Akkulader 2009.2.25 ##########
'######### c Michael Brambach ###########
'########################################
'# Ein vervielfältigung ohne die #
'# Zustimmung des Autors ist verboten. #
'# Es darf nur für private Zwecke #
'# genutzt werden. #
'# Wer diese Programm nutzen möchte, #
'# sollte beim Autor eine Nachricht #
'# hinterlassen. Es steht grundsätzlich #
'# einer privaten Nutzung nichts im #
'# Wege. #
'########################################
$regfile = "m48def.dat" ' specify the used micro

$crystal = 4000000 ' used crystal frequency

$baud = 19200 ' use baud rate

$hwstack = 32 ' default use 32 for the hardware stack

$swstack = 10 ' default use 10 for the SW stack

$framesize = 40 ' default use 40 for the frame space

Config Portd = Output


'----- L C D ----

Config Lcdpin = Pin , Db4 = Portd.6 , Db5 = Portd.7 , Db6 = Portd.4 , Db7 = Portd.2 , E = Portb.0 , Rs = Portd.5
Config Lcdbus = 4
Config Lcd = 16 * 2

'---- E I N G Ä N G E ----

Config Portb.5 = Input
Config Portc.5 = Input
Config Portc.4 = Input
Config Portb.4 = Output


'Sonderzeichen
Deflcdchar 0 , 32 , 32 , 32 , 32 , 32 , 32 , 32 , 31
Deflcdchar 1 , 32 , 32 , 32 , 32 , 32 , 31 , 31 , 31
Deflcdchar 2 , 32 , 32 , 32 , 31 , 31 , 31 , 31 , 31
Deflcdchar 3 , 32 , 31 , 31 , 31 , 31 , 31 , 31 , 31
Deflcdchar 4 , 31 , 31 , 31 , 31 , 31 , 31 , 31 , 31
Deflcdchar 5 , 31 , 17 , 23 , 19 , 23 , 23 , 31 , 31
Deflcdchar 6 , 32 , 4 , 8 , 31 , 8 , 4 , 32 , 32


'---- T I M E R ----
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
Config Timer2 = Pwm , Pwm = On , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1

Enable Timer0


'---- A D C ----
Config Adc = Single , Prescaler = Auto
Start Adc


'---- I N T E R R U P T S ----
On Timer0 Isr_tim0
Enable Interrupts



'---- V A R I A B L E N ----
'Fir-Regler
Dim Fir1(40) As Integer
Dim Fir2(40) As Integer
Dim Fir3(40) As Integer
Dim Fir4(40) As Integer
'Dim Fir(4) As Integer


'Fir Rechen Variablen
Dim Ende1_1 As Integer
Dim Ende2_1 As Integer
Dim Ende3_1 As Integer
Dim Ende4_1 As Integer
Dim Ende1_2 As Integer
Dim Ende2_2 As Integer
Dim Ende3_2 As Integer
Dim Ende4_2 As Integer
Dim Ende(4) As Integer

'PWM Speicherwerte
Dim Akku(4) As Integer

'Timerkorrektur + Doppeldurchläufe vermeiden
Dim Durchlauf As Byte 'akkuladen
Dim G As Bit 'akkuladen

Dim Durchlauf1 As Byte 'Taster
Dim G1 As Bit 'Taster

'vitueller Akku
Dim Wert(4) As Byte

'Ladeschluss Variable
Dim Ladeschlu(4) As Byte

'Schleifenwerte
Dim M As Byte
Dim Z As Byte
Dim N As Byte

'Taster
Dim T1 As Bit 'rauf
Dim T2 As Bit 'runter
Dim T3 As Bit 'rechts
Dim T4 As Bit 'links
Dim T5 As Bit 'OK

'Sonstiges
Dim Akt As Byte 'Courserposition
Dim C As Byte 'Akkuladebalken
Dim Pwm(4) As Integer 'PWM Wert


'---- A L I A S E ----
E1 Alias Pinb.5
E2 Alias Pinc.5
E3 Alias Pinc.4
Led1 Alias Portb.4


'Wert(1) = 1
'Wert(2) = 1
'Wert(3) = 1
'Wert(4) = 1

Akt = 1

Locate 1 , 6
Lcd "mA mA"
Locate 2 , 6
Lcd "mA mA"

Do

If Durchlauf = 76 Then '~ alle 10s eimal Durchlaufen (Akkulade Kontrolle)
If G = 0 Then

G = 1
'Led1 = 1
'Virtuell alles auf "1" setzen

'Wert(1) = 1
'Wert(2) = 1
'Wert(3) = 1
'Wert(4) = 1


'Ladeschaltung auf "0" setzen

Pwm1a = 0
Pwm1b = 0
Pwm2a = 0
Pwm2b = 0


'Fir Werte um 1 nach "vorne" verschieben

For M = 1 To 39

Fir1(m) = Fir1(m + 1)
Fir2(m) = Fir2(m + 1)
Fir3(m) = Fir3(m + 1)
Fir4(m) = Fir4(m + 1)

Next


'Regler auswertungsvariablen nullen

Ende1_1 = 0
Ende2_1 = 0
Ende3_1 = 0
Ende4_1 = 0

Ende1_2 = 0
Ende2_2 = 0
Ende3_2 = 0
Ende4_2 = 0


'ADC Werte auslesen und im "letzten" Fir Wert speichern.

If Ladeschlu(1) = 1 Then
Fir1(40) = Getadc(0)
End If

If Ladeschlu(2) = 1 Then
Fir2(40) = Getadc(1)
End If

If Ladeschlu(3) = 1 Then
Fir3(40) = Getadc(2)
End If

If Ladeschlu(4) = 1 Then
Fir4(40) = Getadc(3)
End If

Print Fir1(40)
'Regler auswerten.
'Die Ersten 20 und die zweiten 20 Werten addiert und anschließend die ersten 20 von den 2ten 20 abgezogen.

For M = 1 To 20
Ende1_1 = Ende1_1 + Fir1(m)
Ende2_1 = Ende2_1 + Fir2(m)
Ende3_1 = Ende3_1 + Fir3(m)
Ende4_1 = Ende4_1 + Fir4(m)

Z = M + 20

Ende1_2 = Ende1_2 + Fir1(z)
Ende2_2 = Ende2_2 + Fir2(z)
Ende3_2 = Ende3_2 + Fir3(z)
Ende4_2 = Ende4_2 + Fir4(z)
Next

Ende(1) = Ende1_2 - Ende1_1
Ende(2) = Ende2_2 - Ende2_1
Ende(3) = Ende3_2 - Ende3_1
Ende(4) = Ende4_2 - Ende4_1


'Akkus virtuell wieder laden lassen

For M = 1 To 4
If Ende(m) < 0 Then
Wert(m) = 0
Ladeschlu(m) = 0
Else
If Ladeschlu(m) = 1 Then
Wert(m) = 1
End If
End If

Next


'Akkus offiziel wieder laden lassen, fals notwendig

If Wert(1) = 0 Then Pwm1a = 0 Else Pwm1a = Pwm(1)
If Wert(4) = 0 Then Pwm1b = 0 Else Pwm1b = Pwm(4)
If Wert(3) = 0 Then Pwm2a = 0 Else Pwm2a = Pwm(3)
If Wert(2) = 0 Then Pwm2b = 0 Else Pwm2b = Pwm(2)

End If
End If




If Durchlauf1 = 3 Then

If G1 = 0 Then '~ alle 0,3s eimal Durchlaufen (Taster Auswertung)

G1 = 1


T1 = 0 '"rauf"
T2 = 0 '"runter"
T3 = 0 '"rechts"
T4 = 0 '"links"
T5 = 0 '"OK"

If E1 = 1 Then 'Taster 1

If E2 = 1 Then
T1 = 1
Goto Tasterende
End If

If E3 = 1 Then 'Taster 4
T4 = 1
Goto Tasterende
End If
'Taster 5
T5 = 1
Goto Tasterende
End If

If E2 = 1 Then 'Taster 2
T2 = 1
Goto Tasterende
End If

If E3 = 1 Then 'Taster 3
T3 = 1
Goto Tasterende
End If

Tasterende:

If T1 = 1 Then '"Strom" erhöhen
If Akku(akt) < 6000 Then
Akku(akt) = Akku(akt) + 100
End If
End If

If T2 = 1 Then '"Strom" verrringern
If Akku(akt) > 1 Then
Akku(akt) = Akku(akt) - 100
End If
End If

If T3 = 1 Then 'Position verschieben
If Akt < 4 Then
Akt = Akt + 1
End If
End If

If T4 = 1 Then 'Position in andere Richtung
If Akt > 1 Then
Akt = Akt - 1
End If
End If

If T5 = 1 Then '"OK" Taster

Ladeschlu(akt) = 1 'Ladeschluss aufheben

Pwm(akt) = Akku(akt) / 25

If Akt = 1 Then 'Fir Regler leeren
For N = 1 To 40
Fir1(n) = 0
Next
End If

If Akt = 2 Then ' --"--"--
For N = 1 To 40
Fir2(n) = 0
Next
End If

If Akt = 3 Then ' --"--"--
For N = 1 To 40
Fir3(n) = 0
Next
End If

If Akt = 4 Then ' --"--"--
For N = 1 To 40
Fir4(n) = 0
Next
End If

Led1 = 1 'Visuell bestätigen durch LED ~0,3s an
Else
Led1 = 0
End If

'LCD Anzeige:


For M = 1 To 2

Locate M , 2
Lcd " "
Locate M , 10
Lcd " "
Locate M , 8
Lcd " "
Locate M , 16
Lcd " "

Next


C = C + 1

If C = 5 Then
C = 0
End If

For N = 1 To 2

M = N * 2
Z = M - 1

If Akt = Z Then
Locate N , 8
Lcd Chr(6)
End If

If Akt = M Then
Locate N , 16
Lcd Chr(6)
End If

Locate N , 2
Lcd Akku(z)

Locate N , 10
Lcd Akku(m)

Locate N , 1

Lcd Chr(c)
Locate N , 1
If Ladeschlu(z) = 0 Then Lcd Chr(5)

Locate N , 9

Lcd Chr(c)
Locate N , 9
If Ladeschlu(m) = 0 Then Lcd Chr(5)

Next

Cursor Off
End If

End If

Loop


Isr_tim0:

Durchlauf = Durchlauf + 1

If Durchlauf = 77 Then

Durchlauf = 0
G = 0

End If

Durchlauf1 = Durchlauf1 + 1

If Durchlauf1 = 4 Then

Durchlauf1 = 0
G1 = 0

End If



Return

mfg
Michael

Besserwessi
25.02.2009, 19:39
Wenn das Layout nicht so besonders gut ist, könnte es schon Störungen geben. Die Ausgänge sollten nicht zu viel Strom schalten, die Masseführung sollte stimmen, und an VCC und AVcc sollten Abblockkondensatoren sein. Bei einem Brauchbaren Layout geht auch PWM während einer AD-wandlung. Der zu erwartende extra Fehler liegen mehr bei 1 LSB oder weniger.

Der Interrupt sollte den ADC nicht stören. Es sei denn dort wird auch der AD Wandler ausgelesen oder die Ausgänge an PORT C geändert.

Wenn die Störungen nur eher selten auftreten und man reichlich Zeit hat, könnte man mehrmals messen und dann mitteln bzw. die größten und kleinsten Werte verwerfen.

Michael 123
26.02.2009, 09:23
Hallo,

hmmm, das mit den Kondensatoren könnte sein, es sind ein paar wenige auf der Platine. (Hatte keine mehr da :-) )
Die Aussgänge schalten nur einmal eine LED, ansonsten über einen OP. Also da fließt kein Strom. Sie sind ja auch nicht immer an, auch nicht wenn der ADC misst.

Die Störungen teten so alle 5-20 Messungen auf, dann stimmt es wieder ein paar und dann wieder so ein Aussreiser.
Naja, Zeit hätte ich schon, aber der Mega48 ist voll :-). Es ist zwar ein Mega88 schon bestellt, aber der muss auch erst kommen.

Aber eigentlich müsste es doch ohne die Krugz gehen, den AD Wandler auszulesne, ohne noch "nachrenen" zu müssen.

Werde auf jeden Fall mal ein paar Kondensatoren noch einlöten.

Danke schon mal

mfg
Michael

Klingon77
27.02.2009, 00:59
hi,

bin ja kein Elektroniker...


Könnte man den Eingang des ADC´s ggf. mit einem kleinen Kondensator im nF oder gar im pF-Bereich gegen Masse nicht ein wenig "träger" machen?

Evtl. nimmt der Kerko die Störungen raus.

Der Ladevorgang der Akku´s geschieht ja langsam; sprich die Spannungsänderungen verlaufen recht langsam.

Es würde auch genügen wenn man nur alle paar Sekunden eine Messung durchführt.


liebe Grüße,

Klingon77

Edblum
27.02.2009, 08:16
Moin,

Ich habe damals eine Akkulader gebaut mit eine 80C535 Controller. Vorbild war eine Reflexlader von Elektor. Es ist wichtig dass mann den Ladestrom abschaltet während eine Messung. Damit die Akkus sich einigermasse erholen können. Und noch wichtiger, mann keine Störungen bekommt. Nur eine halbe Sekunde genügt. Bitte bau dass in deine Programm ein.

Gruss,

Edblum

Besserwessi
27.02.2009, 12:10
Ein Kondensator am Eingang des ADCs kann helfen höherfrequente Störungen zu vermeiden. Kondensatoren unter etwa 10 nF sollte man aber nur nehmen, wenn man eine relativ niederohmige Quelle hat. Die kleinen Kondensatoren reichen noch nicht aus ohne merklichen (1 LSB) Spannungsabfall den Kondensator der Sample und Hold Stufe des AD wandlers zu laden. Durch den zusätzlichen Kondesator verlängert sich dann die Zeit die es braucht bis sich der richtige Wert wieder Einstellt.

Bei größeren Kondensatoren (> 10 nF) am Eingang bricht die Spannung kaum noch ein, und die Signalquelle darf auch über 10 kOhm impedanz haben, wenn man nicht zu oft den Kanal wechselt.

Edblum
27.02.2009, 13:47
Moin,

Von Atmel wird weiterhin empfohlen eine Spule am Aref auf zu nehmen. Aber ob dass so kritisch ist beim Akkuladen? Bitte Datenblatt lesen.

Edblum

Michael 123
28.02.2009, 10:09
Hallo,

es geht nun!

Habe ein paar 47nF Caps eingebaut. Anschliesend noch die Zeit zwischen PWM aus und ADC auf 500 ms eingestellt. (hane ich auch ohne das hier zu lesen gemacht, da der adc ca. 100 zu vil anzeigte.

Nun läuft alles.

Danke

Michael