ADC-Wert auf Display ausgeben - Ergebnis immer 1023

mcafer

Neues Mitglied
14. Okt. 2009
7
0
0
Sprachen
Hallo,

ich versuche in die Grundlagen rein zu kommen.
Aber da scheitert es schon - ich habe mit BASCOM ein einfaches Programm
geschrieben um den ADC abzufragen und den Wert auf ein Display darzustellen.
Ich bekomme als Ergebniss immer nur 1023 - auch wenn ich den Eingang auf Masse lege.
Mein Programm sieht so aus :

Code:
$regfile = "m8adef.dat"
$crystal = 4000000
$hwstack = 40
$swstack = 16
$framesize = 32

Dim W As Word

$lib "glcdKS108.lbx"

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

Start Adc

Config Graphlcd = 128 * 64sed , Dataport = Portd , Controlport = Portb , Cd = 4 , Rd = 3 , Ce = 0 , 
Ce2 = 1 , Enable = 5 , Reset = 2
Setfont Font8x8
Cls

Do

W = Getadc(0)


Lcdat 1 , 1 , W ; "Wert: "

Loop

End

$include "font8x8.font"

Was stimmt hier nicht - warum bekomme ich kein richtiges Ergebnis angezeigt ?
Wenn ich ein Poti am ADC-Eingang anschließe müsste ich doch Werte von Null bis 1023 erhalten.
Meine Schaltung ist folgende :

- ADC-GND mit GND verbunden dazu 100nF an AREF
- AVCC an +5V und über 100nF an GND

Das sollte doch so richtig sein - oder ?
Habe Ihr noch eine Idee was falsch sein könnte?

Danke !
 
Und der gemessene Eingang ist definitiv C0?
Sollte eigentlich alles passen, ggf probier mal aus, die I/O-Register manuell zuzuweisen/abzufragen.

Messe im laufenden Betrieb mal (vorsichtig) die Spannung, die am ARef-Pin anliegt (sollte AVcc entsprechen), und die an C0.
Was kommt raus, wenn Du getadc(14) (sollte was um die 255 ergeben) oder getadc(15) (=0) versuchst?
 
Danke für die schnelle Antwort !
Also am AREF-Pin sollten 5V anliegen - leider habe ich da keine Spannung
anliegen.
An den ADC - Eingängen sind es nur ein paar hunder Millivolt.
Irgendwas passt da nicht.
Habe auch schon zwei neue IC,s genommen - das selbe Ergebniss.
Also wird es im Programm liegen
Das heißt, die Register sind falsch gesetzt oder BASCOM compiliert den Text nicht richtig
(kann ich ja lange suchen).
Wie kann ich die Register per Hand einstellen ?
Auch wenn ich auf getadc (14) bzw. (15) einstelle erhalte ich auch immer nur 1023 :-(
Was nun ?
Hast Du noch eine Idee ?
 
Asche auf mein Haupt - hatte gehofft kompetente Hilfe zu finden ...
Hatte ja schon alles probiert - das Programm selbst soll ja so stimmen.
Warte also nicht nur auf "vor gekaute" Lösungen.
Bin selbst an einer / selbstständigen Lösung interessiert.
Auch ein Dummer braucht Denkanstöße und ist selbst nicht Dümmer als andere !
 
Und bist du nicht fähig einen Plan zu zeichnen? Wie hast alles angeschlossen? Das kann sich doch keiner hier aus der Luft saugen!

DU willst Hilfe!
 
Hallo,

- hatte gehofft kompetente Hilfe zu finden ...
Hatte ja schon alles probiert - das Programm selbst soll ja so stimmen.
je mehr Infos du gibst desto schneller geht es. Ein Schaltplan ist schonmal ne gute Sache damit man sieht wie du alles verkabelt hast. Es gab schon die dollsten Sachen an denen es gehakt hat (zB nicht verbundene GND-Anschlüsse).

Da die Leute hier nicht bei dir zuhause vor der Schaltung sitzen und dir über die Schulter blicken muß man sich alles irgendwie im Kopf aus den gegebenen Infos zusammenreimen. Also je mehr du den Leuten mit Infos weiterhilfst, desto mehr können sie dir mit Antworten weiterhelfen. Am besten alles auf den Tisch ;)

Gruß
Dino
 
Ich möchte nicht unhöflich sein, aber ich habe lediglich ein Display an den AtMega8 angeschlossen
und den ADC entsprechend meines ersten Beitrages angeschlossen (Standardbeschaltung).
Mehr gibt es (erstmal) nicht.
Erweiterungen sind möglich - aber bringen auch mehr Fehlerquellen mit sich.
Es geht erstmal um die Grundlagen ...
Ich möchte lediglich den ADC auslesen und den / die Werte über das Display auslesen können.
 
Hi,

...und den ADC entsprechend meines ersten Beitrages angeschlossen (Standardbeschaltung).
Mehr gibt es (erstmal) nicht.

Aus dem ersten Beitrag ...
Wenn ich ein Poti am ADC-Eingang anschließe müsste ich doch Werte von Null bis 1023 erhalten.
Meine Schaltung ist folgende :

- ADC-GND mit GND verbunden dazu 100nF an AREF
- AVCC an +5V und über 100nF an GND

Das sollte doch so richtig sein - oder ?
Also aus deinen Infos und meinen Annahmen ...
- AGND und GND verbunden
- AVcc und Vcc verbunden und natürlich an +5V
- ARef mit 100nF beruhigt
- ADC0 mit dem Schleifer des Potis verbunden
- Enden des Potis an GND und Vcc gelegt (Spannungsteiler)

Das Programm müßte man sich dann mal genauer ansehen ...

Gruß
Dino
 
Hier mal ne ADC-Messung von mir (aus nem größeren Programm rausgeschnitten). Allerdings mit Interrupt ...

Code:
Dim Adc_flag As Byte                                        ' Flag fuer ADC fertig
Adc_flag = 0
Dim Adc_delay_cnt As Byte                                   ' Zaehler fuer ADC-Rhythmus


' PA7 ------- VBat-ADC
'
' A=7= O=6= O=5= O=4= O=3= O=2= O=1= O=0=  => 01111111 => DDRB
' VBat Tim1 ws3  ws2  ws1  bl3  bl2  bl1   => 00000000 => PORTB (init)
'   |    |    |    |    |    |    |    |
'
Ddra = &B0111_1111
Porta = &B0000_0000




' =============================================================================
' ===== ADC7 Initialisieren ===================================================
' =============================================================================
' ADC-Kanal 7 (PA7) misst die Akkuspannung (10 Zellen NiMh, 2100mAh)
' Die Messung soll soweit moeglich hardwareunterstuetzt ablaufen und dadurch moeglichst
' wenig Prozessorzeit verbrauchen. Als Referenz wird die interne 2,56V Bandgapquelle
' verwendet weil AVcc zu stark schwanken kann. Da die Timer 0+1 bereits belegt sind und
' Timer2 keine Wandlung ausloesen kann sowie ein 8Bit-Timer eine zu hohe Wandelrate liefern
' wuerde, wird der Start manuell ueber Software gestartet und dann das Ergebnis ueber ISR
' abgefragt. Eine Wandelrate von 1-2Hz reicht absolut aus.
'
' Spannungsteiler:  Vbat---39k---ADC7---6k8---GND
'
' Berechnung der Akkuspannung aus dem gemessenen ADC-Registerinhalt:
'
' Vbat / (39k + 6k8) = Vadc / 6k8      ...=>... Vbat = ((39k + 6k8) / 6k8) * Vadc
' Vref / 1024steps   = Vadc / ADCsteps ...=>... Vadc = (Vref / 1024steps) * ADCsteps
'
' ( ((39k + 6k8) * Vref) / (6k8 * 1024steps) ) *ADCsteps = Vbat
'
' 0,016838235 * ADCsteps = Vbat        ...=>... Vbat = ADCsteps / 59,38864733
'
' ADC-Messzyklus:   Software -> ADSC=1 .. ADC-ISR(read) .. Anzeige der letzten Mesung
'
Config Adc = Single , Prescaler = 128 , Reference = Internal

' ===== ADC Multiplexer Selection Register =====
'Bit --7-- --6-- --5-- --4-- --3-- --2-- --1-- --0-- ADMUX
'    REFS1 REFS0 ADLAR  MUX4  MUX3  MUX2  MUX1  MUX0
'     R/W   R/W   R/W   R/W   R/W   R/W   R/W   R/W
'      |     |     |
'      |     |      \ADC Left Adjust Result (Write one to ADLAR to left adjust the result)
'       \   /
'        0 0 AREF, Internal Vref turned off
'        0 1 AVCC with external capacitor at AREF pin
'        1 0 Reserved
'        1 1 Internal 2.56V Voltage Reference with external capacitor at AREF pin
'
' MUX4:0  Single Ended Input
' 00111   ADC7
'
Admux = &B1100_0111

' ===== ADC Control and Status Register A =====
'Bit --7-- --6-- --5-- --4-- --3-- --2-- --1-- --0-- ADCSRA
'     ADEN  ADSC ADATE  ADIF  ADIE ADPS2 ADPS1 ADPS0
'     R/W   R/W   R/W   R/W   R/W   R/W   R/W   R/W
'      |     |     |     |     |
'      |     |     |     |      \ADC Interrupt Enable
'      |     |     |      \ADC Interrupt Flag
'      |     |      \ADC Auto Trigger Enable
'      |      \ADC Start Conversion
'       \ADC Enable
'
' ADPS2:0 - ADC Prescaler Select Bits => Division Factor
' 000 = 2 , 001 = 2 , 010 = 4 , 011 = 8 , 100 = 16 , 101 = 32 , 110 = 64 , 111 = 128
' Prescaler von 128 wuerde bei 16MHz etwa 96kHz Wandelrate ergeben. Reicht absolut.
'
Adcsra = &B1100_1111

' ===== Special FunctionIO Register =====
'Bit --7-- --6-- --5-- -4- --3-- -2- --1-- --0-- SFIOR
'    ADTS2 ADTS1 ADTS0  -   ACME PUD  PSR2  PSR1
'     R/W   R/W   R/W   R   R/W  R/W  R/W   R/W
'      |     |     |    |
'      |  __/      |     \_ W=0 !
'      | / _______/
'      || /
'      |||  ADTS2:0: ADC Auto Trigger Source
'      000 Free Running mode
'      001 Analog Comparator
'      010 External Interrupt Request 0
'      011 Timer/Counter0 Compare Match
'      100 Timer/Counter0 Overflow
'      101 Timer/Counter1 Compare Match B
'      110 Timer/Counter1 Overflow
'      111 Timer/Counter1 Capture Event
'
'SFIOR = &B0000_xxxx

'Vbat_adc = Getadc(7) ==> selber auslesen ist resourcenschonender
'
On Adcc Adc_isr                                             ' Interrupt-Vektor einstellen
' Enable ADC-Interrupt wird direkt im Register erledigt.



.......



  Gosub Akku_mess                                           ' Akkuspannungsmessung und Anzeige


........



' ================================================
' ===== ISR fuer ADC Conversion Complete =========
' ================================================
' ADC-Wandlung fuer Akkuspannungsmessung beendet
' 10Bit-Wert abholen
Adc_isr:
  ' Bei 10Bit UNBEDINGT erst das Low-Byte lesen damit
  ' dadurch das High-Byte in TEMP gelegt wird. Sonst ... RaceCondition!!
  Adc_l = Adcl                                              ' ZUERST Low-Byte holen
  Adc_h = Adch                                              ' Dann High-Byte aus TEMP lesen
  Adc_flag = 1                                              ' Flag setzen als Info das Wert neu ist
Return




' ================================================
' ===== Akkuspannungsmessung und Anzeige =========
' ================================================
' Anzeige des aktuellen Modus auf den 3 LEDs der
' Modusanzeige und auf dem Debug-LCD im Steuergerät
Akku_mess:

If Adc_delay_cnt > 20 Then                                  ' Anzeige und neue Messung starten
  Adc_delay_cnt = 0                                         ' Verzoegerungszaehler neu starten
  ' DVM = 12,916 , ADC = 13,370 => +3,51502% Meßfehler => neuer Faktor 61,47617199
'    Vbat = Adc_read / 59.38864733                           ' gemessenen ADC-Wert holen und umrechnen
  Vbat = Adc_read / 61.476171                               ' kalibrierte Umrechnung
  Vbatstr = Fusing(vbat , "#.##")                           ' Single-Wert formatieren
  Locate 1 , 1
  Lcd Vbatstr                                               ' Spannung anzeigen
  Set Adcsra.6                                              'adsc setzen - Start neue Conversion
End If
Incr Adc_delay_cnt                                          ' Verzoegerungzaehler fuer ADC-Messung

Return

Da ich aber eher direkt an den Registern gestrickt habe wird es wohl nicht so ganz für dich passen.

EDIT: Mal etwas gesucht ... rn-wissen.de - ADC (Avr)
Code:
' Die gemessene Spannung wird in der Variablen W gespeichert.
' Channel ist der Pin, an dem die Spannung gemessen werden soll.

$baud = 9600
$crystal = 1000000
$regfile "m32def.dat"
Config Adc = Single , Prescaler = Auto
Start Adc
Dim W As Word , Channel As Byte
Channel = 0
Do
  W = Getadc(channel)
  Print "ADC-Pin " ; Channel ; ": Wert " ; W
  Incr Channel
  If Channel > 7 Then Channel = 0
  Waitms 800
Loop
End
Bis auf das Waitms 800 sieht es eigentlich ähnlich deinem Programm aus.

GETADC...
Retrieves the analog value from the specified channel.

Beispiel aus der Hilfe ...
Code:
'configure single mode and auto prescaler setting
'The single mode must be used with the GETADC() function
'The prescaler divides the internal clock by 2,4,8,16,32,64 or 128
'Because the ADC needs a clock from 50-200 KHz
'The AUTO feature, will select the highest clockrate possible
Config Adc = Single , Prescaler = Auto

'Now give power to the chip
Start Adc

'With STOP ADC, you can remove the power from the chip
'Stop Adc

Dim W As Word , Channel As Byte

Channel = 0
'now read A/D value from channel 0
Do
   W = Getadc(channel)
   Print "Channel " ; Channel ; " value " ; W
   Incr Channel
   If Channel > 7 Then Channel = 0
Loop
End
hmmm ... komisch. Also das Beispiel ähnelt deinem Programm. Bist du wirklich sicher das deine Verkabelung richtig ist?
Hast du eine Seite deines Potis wirklich auf GND? Also einen Spannungsteiler? Auch kein Wackelkontakt?

Gruß
Dino
 
Danke Dino03 dass Du mir so viel Unterstützung gibst !

Ich habe mich an Beispiel-Codes / Samples orientiert - daher auch die Ähnlichkeit
mit öffentlichen Quellcode.
Ich habe alles auf ein Steck-Board aufgebaut und die Verdrahtung nochmals
geprüft - dass passt alles.
Die Ausgabe auf dem Display geht ja, nur die dass Auslesen der ADC-Werte eben nicht.
Ich habe die Demo-Variante von BASCOM (2.0.7.5.) - kann es daran liegen ?
An den AtMega sollte es nicht liegen - die sind noch neu und unbenutzt.
Etwas stutzig macht mich schon, dass an ARef keine 5V anliegen - anscheinend werden
doch nicht alle Register richtig gesetzt.
Wie kann ich mit BASCOM das richtige Setzen der Register überprüfen ?
Ich weiß ehrlich gesagt nicht mehr weiter.
Für Heute mach ich erstmal Schluss - weitere Hilfe ist gern gesehen.

Nochmals Danke !
 
Hmm... also ich hatte auf'm Steckbrett auch schonmal nicht leitende "Verbindungen"...

Ok, bleib mal bei interner AVcc-Referenz und messe die interne Bandgap (getadc(14) - liefert 1,3V, also ca. 1/4 von 5V=AVcc, also ca. 1/4 von 1023)
Nach dem Config ADC läßt Du jetzt die Register ADMUX und ADCSRA in der ersten Zeile des Displays ausgeben.
Nach Start ADC nochmal in der 2ten.
danach erstmal ein end. Programm (oder 'ne Endlosschleife) - die Werte stellst Du hier rein (kannst ja auch selbst mit dem Datenblatt auswerten.
Als nächstes könnte man dann dieselben Register nach einem Getadc ausgeben lassen.

Aber wie gesagt: Wann der ADC mit einer internen Referenz aktiviert ist, liegt die Referenzspannung am Aref-Pin an, da sie dort mit einem externen Kerko zu blocken ist. Zu beachten ist, daß der gesamte ADC-Block, und auch die Pegel von C3..0 aus der analogen Versorgung (AVcc, AGnd) ... ähm ... versorgt werden.

Also vom Programm her sieht das eigentlich iO aus - ich tippe auch auf irgendein Verdrahtungsfehler (ob Schaltplanfehler oder fehlendem Kontakt ist 'ne andere Sache).
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)