Forum: Mikrocontroller und Digitale Elektronik A/D Wandler defekt gibt nur 1023 aus


von Matthias H. (maethes26)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich wollte ebend auf meinem selbst gebauten Controllerboard, siehe Bild

Meinen schon vor Monaten auf den STK500 Board erstellten und 
funktionsfähigen Code zum Laufen bringen.
Der Code lief damals auf einem Atmega8.

Jetzt habe ich nur einen einzigen Atmega32 und da zeigt der Code für den 
Analogen Potiwert ständig nur 1023 an.

Habt ihr eine Idee woran das liegen könnte.
anbei auch der Code

Das merkwürdige ist, das wenn ich die Potispannung von beispielsweise 
1,5V auf den PIN0 an PORT A lege  ADMUX = 0x01;   dann messe ich am 
Eingangsport des ADC 0V, obwohl ich 1,5V anlege. die habe ich auch 
vorher gemessen und die sind da.

im Eingangsmodus funktioniert der PORT A problemlos.
Ist der code nicht in Ordnung (bitteeinmal drüber schauen) oder der 
Prozessor.


Viele GRüße und noch einen schönen Abend wünscht Matthias.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdlib.h>
4
#define LCD_Port PORTB
5
#include "E:\Eigene Dateien\Dropbox\Atmel AVR\AVR Programme\1aVorlagen\lcd_tools.c"
6
7
8
9
#define F_CPU 4000000UL // Systemtakt in Hz - Definition als unsigned long beachten 
10
                         // Ohne ergeben sich unten Fehler in der Berechnung
11
12
13
14
int main(void)
15
{
16
17
DDRD=0xff;  
18
DDRB=0xff; //PORT für LCD_Port aktivieren
19
20
double  result = 0;
21
char buffer[20];
22
ADMUX = 0x01;        // Kanal waehlen (ADC1)  
23
 _delay_ms(100); 
24
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);      // Frequenzvorteiler: setzen auf 32 (4 MHz / 32 = 125 kHz) und ADC aktivieren 
25
// ADCSRA &=~(1<<ADPS1);   //zur Sicherheit   
26
27
  
28
    
29
  ADMUX |= (1<<REFS0) ;     // externe Spannung nutzen 
30
  // ADMUX &=~(1<<REFS1);      // zur Sicherheit externe Refrerenzspannung nutzen 
31
32
  ADCSRA |= (1<<ADSC);                // eine ADC-Wandlung und danach wird das Bit wieder auf Null gesetzt
33
  while ( ADCSRA & (1<<ADSC) );       // auf Abschluss der Konvertierung warten , warten bis die Wandlung durchgeführt iwst und bit wieder auf Null
34
  result = ADCW;            // Wert abholen
35
  
36
37
lcd_ini();
38
/*
39
lcd_gotopos(1,1);
40
lcd_writetext("Spannung PIN 1=");
41
lcd_gotopos(1,19); lcd_writetext("V");
42
43
*/
44
45
while(1)
46
  {
47
48
  ADMUX = 0x01;        // Kanal waehlen (ADC1)     ?? 
49
50
    ADCSRA |= (1<<ADSC);                // eine ADC-Wandlung und danach wird das Bit wieder auf Null gesetzt
51
    while ( ADCSRA & (1<<ADSC) );       // auf Abschluss der Konvertierung warten , warten bis die Wandlung durchgeführt ist und bit wieder auf Null
52
    result = ADCW;            // Wert abholen
53
54
  
55
  
56
  // dtostrf (5*result/1024.0, 4,1, buffer);    lcd_writetext(buffer);
57
  lcd_gotopos(4,15); lcd_writezahl(result);
58
59
PORTD ^= ( 1 << PB6 );     // Toggle PB0 z.B. angeschlossene LED, die LED blinkt, das funktioniert, also wird der code mehrmals abgearbeitet
60
 _delay_ms(700); 
61
62
63
  }
64
65
66
return 0;
67
68
}

von Hubert G. (hubertg)


Lesenswert?

ADMUX = 0x01  ist ADC1 auf PORTA1

von Matthias H. (maethes26)


Lesenswert?

Hubert G. schrieb:
> ADMUX = 0x01  ist ADC1 auf PORTA1

Hallo Hubert,

danke für den Tipp.

Ja, ich habe sogar alle PORT A Pins durchprobiert, kein Erfolg.  PIN1 
auf PORT A müßte das sein, =anschlussPIN40 vom dem Atmega32.

Habe mich wohl mißverständlich ausgedrückt, aber kein PIN von PORT A 
funktioniert, leider.

Vielleicht noch eine Idee?
Ansonsten scheint der Code wohl in Ordnung zu sein, sonst hättest Du 
bestimmt noch was gesagt.
Viele Grüße,

Matthias.

von Ralf G. (ralg) (Gast)


Lesenswert?

Hubert G. schrieb:
> ADMUX = 0x01  ist ADC1 auf PORTA1
PORTA??

von Hubert G. (hubertg)


Lesenswert?

ADMUX = 0x01 Das ist aber Pin39 des Mega32

von Floh (Gast)


Lesenswert?

Dein AREF ist wie beschaltet?
Mit ADMUX = 1; wählst du AREF als Referenzspannung aus.
:-)

von Hubert G. (hubertg)


Lesenswert?

Ralf G. (ralg) schrieb:
> PORTA??

Beim Mega32 ist der ADC auf PORTA, zumindest steht es in meinem 
Datenblatt so.

von Matthias H. (maethes26)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

danke für Eure Hilfe.

anbei ein Foto von meinem Schaltplan.
selbst wenn ich mich um einen PIN vertuhen würde 39 anstatt 40. ich habe 
ja alle PORT A pins auf masse gezogen und es hat sich nichts an der LCD 
Ausgabe getan.

zur Sicherheit habe ich auch noch eine LED auf PRTD mit in dieser 
Messschleife vom POIRTA blinken lassen, um sicher zu gehen, das diese 
schleife überhaupt wiederholt abgearbeitet wird.

ich fahre jetzt schnell zu conrad und hole mir einen weiteren Chip 
Atmega32 für 7,5€ :-(  ist dort sehr teuer

muss jetzt schnell los.

kann aber von unterwegs jederzeit eure Mails lesen.

bis nachher

von Jannis C. (kabelwurm)


Lesenswert?

Hallo,
ADC in der Standart-Beschaltung?
http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC
Gruß Jannis

von Ralf G. (ralg) (Gast)


Lesenswert?

Hubert G. schrieb:
> Ralf G. (ralg) schrieb:
>> PORTA??
>
> Beim Mega32 ist der ADC auf PORTA, zumindest steht es in meinem
> Datenblatt so.
Ja, hatte etwas nachlässig den Eröffnungsthread gelesen. Ich ging beim 
'Tausch' von etwas pinkompatiblem aus :-(

Also:
ADMUX-Register sieht für mich auf den ersten Blick völlig anders aus.

von Floh (Gast)


Lesenswert?

Matthias H. schrieb:
> anbei ein Foto von meinem Schaltplan.

Dacht ichs mir.
Du musst deine Referenz im ADMUX-Register z.B. auf AVcc legen.
Also das Bit REFS0 setzen.
Sonst fehlt dir eine Referenzspannung, gegen die du misst.

von Jannis C. (kabelwurm)


Lesenswert?

Dar war ich zu langsam.
Nur mal eine Frage, warum hast du als Spulenwerd 10 und nicht 47 
MicroHenry verwendet?
Gruß Jannis

von Floh (Gast)


Lesenswert?

PS:
In dem Schaltplan fehlt dein Quarz und an AVcc vermisse ich den 
Kondensator nach Masse. :-)

von Martin N. (emsen)


Lesenswert?

Jannis C. schrieb:
> warum hast du als Spulenwerd 10 und nicht 47
> MicroHenry verwendet?

Habe ich etwas übersehen? Warum 47µH? Könnte ja so auch passen.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC

von gene (Gast)


Lesenswert?

rtfm

von Floh (Gast)


Lesenswert?

Matthias H. schrieb:
> ADMUX = 0x01;        // Kanal waehlen (ADC1)     ??

Falsch. Hier überschreibst du deine Referenzeinstellung.

von Jannis C. (kabelwurm)


Lesenswert?

Hallo,
Ich habe mal eine 47 Spule verwendet, nachdem merkwürdiger Weise es mit 
10 nicht funktioniert hat. Mag in deinem Fall besser funktionieren.
Gruß Jannis

von Karl H. (kbuchegg)


Lesenswert?

Was sagt dir
1
  ADMUX |= (1<<REFS0) ;     // externe Spannung nutzen 
2
3
  ...
4
5
  while(1)
6
  {
7
   
8
    ADMUX = 0x01;        // Kanal waehlen (ADC1)     ?? 
9
10
    ...

Ich frag mich ja immer wieder, wozu es im Tutorial fertige getestete 
Funktionen gibt, wenn sie dann keiner studiert, wie man die Dinge macht. 
Oder gar, Gott bewahre, einfach die Funktionen aus dem Tut nimmt.

von Hubert G. (hubertg)


Lesenswert?

Floh schrieb:
> Matthias H. schrieb:
>> ADMUX = 0x01;        // Kanal waehlen (ADC1)     ??
>
> Falsch. Hier überschreibst du deine Referenzeinstellung.

In der while(1)
Genau das wird es sein, dann ist externe Referenz eingestellt und nach 
dem diese 0V ist, ist jeder andere ADC-Wert 1023.

von Matthias der autof (Gast)


Lesenswert?

danke für den tipp. der kleine Fehler leuchtet mir ein. selber sieht man 
sowas oft nicht.
Einen schoenen abend noch.

von Matthias H. (maethes26)


Lesenswert?

Guten Morgen zusammen,

ich betreibe meinen Atmega32 im free running mode und habe eine Frage 
zur Kanalauswahl.

Ich habe es so verstanden, wenn man keienn Kanal wählen würde

 ADMUX = 0x06;   //Platinenpoti   also nciht diese Zeile,

dann würde der AD Wandler nach und nach alle Kanäle abfragen.

Was ist, wenn ich diese Kanäle aktiviere, weil ich sie in meinem 
Programm brauche
ADMUX |= 0x04;    //Motorpoti
ADMUX |= 0x03;  //shunt
ADMUX |= 0x06;   //Platinenpoti

meines Wissens nach werden dann nur diese Kanäle im free running mode 
durchlaufen, oder irre ich mich da?

jetzt habe ich aber eine Oversampling abfrageschleife so wie hier

result=0;

  for(i=0; i<20;i++)
  {
  //ADCSRA |= (1<<ADATE);
  while (!(ADCSRA & (1<<ADIF)));
  result += ADCW;

  }
result /=20;
dtostrf((double)result, 4,0, texte); lcd_gotopos(3,16); 
lcd_writetexte(texte);


Meine eigentliche Frage lautet, ob in dieser Schleife jetzt nach und 
nach alle 3!!! vorkonfigurierten ADC Kanäle abgefragt und ausgewertet 
werden???
Ich möchte doch in dieser konkreten Schleife jetzt nur einen der drei 
vorgewählten
ADMUX |= 0x04;    //Motorpoti
ADMUX |= 0x03;  //shunt
ADMUX |= 0x06;   //Platinenpoti

Kanäle abfragen.

Muss ich dazu vor dieser SChleife zwei der drei Kanäle deaktivieren? Ich 
denke ja, oder


Ich hoffe, ich konnte mein Anliegen verständlich rüber bringen.

Danke für die Hilfe im Vorraus,

Matthias.

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Auch wenns jetzt nicht mit deinem eigentlichen Problem zu tun hat...

Hast du dir eigentlich beim Layouten mal darüber Gedanken gemacht wie du 
deine Anschlussleitungen in die Schraubklemmen gesteckt bekommst?

http://www.mikrocontroller.net/attachment/118664/DSCF1935.jpg

Gruß,
Magnetus

von Floh (Gast)


Lesenswert?

Matthias H. schrieb:
> ADMUX |= 0x04;    //Motorpoti
> ADMUX |= 0x03;  //shunt
> ADMUX |= 0x06;   //Platinenpoti

Böse. Dein ADMUX sieht danach so aus:
ADMUX = 0x03 | 0x04 | 0x06 = 0x07;
Das willst du sicher nicht.

Meine Empfehlung, kapsle die komplette AD-Wandlung mit Einstellung des 
Kanals in eine Funktion (wie z.B. im Tutorial vorgemacht).
Und dann benutze zum AD-Wandeln nur noch diese Funktion, ohne in den 
Registern wild rumzuschreiben.

Übrigends gibt ADMUX immer den aktuellen Kanal an, da kann man nix 
voreinstellen, was der ADC als nächstes machen soll.
:-)

von Matthias H. (maethes26)


Angehängte Dateien:

Lesenswert?

Magnus Müller schrieb:
> Auch wenns jetzt nicht mit deinem eigentlichen Problem zu tun hat...
>
> Hast du dir eigentlich beim Layouten mal darüber Gedanken gemacht wie du
> deine Anschlussleitungen in die Schraubklemmen gesteckt bekommst?
>
> http://www.mikrocontroller.net/attachment/118664/DSCF1935.jpg
>
> Gruß,
> Magnetus



Guten Morgen Magnetus,

das war mein absolut erstes Layout. Da war es mir dann egal, wenn ich 
nciht überall 100%igen Zugang habe. Die Zeit war dann auch knapp und die 
Fläche begrenzt. Um ein wenig zu programmieren, dafür reicht das Board 
allemal. Ich muss dazu nicht an alle optionalen Schraubklemmen gelangen. 
:-)

Das nächste Board wird weitaus verbessert werden. Zum einen wird eine 5V 
Referenzspannungsquelle an den ADC angeschlossen.

Auch wird da Boadlayout hinsichtlicht einer taktung von 16MHZ optimiert 
werden müssen. Ich denke da an die Masseverlegung siehe Bild.
mehr kann ich Dir zu dem Bild gar nicht so sagen. Die darf wohl nur von 
einer Seite rein in den uC.

Viele Grüße,

Matthias.

von Matthias H. (maethes26)


Angehängte Dateien:

Lesenswert?

Hallo,

danke ich werde die Routine vom Tutorial verwenden.

so sähe das wohl aus, wenn ich alle gleihczeitig aktivieren würde.

ADMUX = (1<<REFS0) ;     // interne Spannung nutzen
ADMUX |= 0x04;    //Motorpoti
ADMUX |= 0x03;  //shunt
ADMUX |= 0x06;   //Platinenpoti

da hatte ich noch zu wenig ERfahrung. Jetzt ist mir klar, dank Deines 
Tipps, das man immer nur einen aktivieren kann!!

Sonst kommt eine ganz andere Konfiguration raus. :-)


Viele GRüße,

Matthias.

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.