Forum: Mikrocontroller und Digitale Elektronik AD Wandler liest falsch PIC


von Hans W. (coglione)


Lesenswert?

Hallo zusammen, ich hab da ein 'komisches' Problem.
Evtl. hatte das auch schon mal jemand von euch.

Ich starte via Timerinterrupt den AD-Wandler. Alles funktioniert tip 
top. Das Problem ist nur, dass der gelesene Wert falsch ist.

Die ADRES Variable hat bei 2.5V am Eingang einen Wert von ca 660.
Der Fehler ist an jedem AN identisch. Er zeigt bei allen Spannungen 
immer zuviel an.

Zum Aufbau:

   +5
   |
  1k
   |_______PIC
   |
  Poti
   |
   0V


Was kann das sein?

von WehOhWeh (Gast)


Lesenswert?

ich tippe drauf, dass das Samplen nicht korrekt funktioniert und du 
immer den gleichen Kanal samplest.
Speziell einige PIC24 mit Pipline-ADC sind komliziert, da können 
durchaus schon mal Fehler passieren...

gib mal ein paar Informationen heraus:
- genauer PIC
- genauer Code
- genaue Beschaltung

von Hans W. (coglione)


Angehängte Dateien:

Lesenswert?

PIC ist PIC18F6722

Hier der Code:
1
//Includes
2
#include <xc.h>
3
#include <stdlib.h>
4
#include <delays.h>
5
#include <string.h>
6
7
// set Config bits
8
#pragma config OSC    = INTIO67     // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7)
9
// CONFIG2L
10
#pragma config PWRT   = ON          // Power-up Timer Enable bit (PWRT disabled)
11
#pragma config BOREN  = OFF         // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
12
// CONFIG2H
13
#pragma config WDT    = OFF         // Watchdog Timer (WDT disabled (control is placed on the SWDTEN bit))
14
// CONFIG3H
15
#pragma config MCLRE  = OFF         // MCLR Pin Enable bit (RG5 input pin enabled; MCLR disabled)
16
// CONFIG4L
17
#pragma config STVREN = OFF         // Stack Full/Underflow Reset Enable bit (Stack full/underflow will not cause Reset)
18
#pragma config LVP    = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
19
#pragma config XINST  = OFF         // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
20
21
// Definitions
22
#define _XTAL_FREQ       8000000            // Frequenz der CPU
23
//LCD Definition
24
#define SW12             PORTCbits.RC3
25
#define ADGoDone         ADCON0bits.GO      // Start AD - Wanlder
26
#define ESC              0x1B               // ESC Programmbefehl fuer LCD
27
#define CURSOR_POSITION  0x4F               // Cursor an eine Stelle setzen
28
#define DISPLAY_MODE     0X4D               // Command Display Mode
29
#define CURSOR_FORM      0x43               // Art des Cursors
30
31
// Global Variablen
32
33
34
// Funktionen
35
void ini();
36
void ad_ini();
37
void delay_ms(int a);
38
39
// Interrupts
40
void interrupt ISR()
41
{
42
    // AD Inetrrupt
43
    if(PIR1bits.ADIF)
44
    {
45
        ADGoDone = 1;
46
        PIR1bits.ADIF = 0;
47
    }
48
}
49
50
// Main Prog
51
void main()
52
{
53
    // Initials
54
    ini();                  // Ini PIC
55
    ad_ini();               // Ini AD - Wandler
56
    ADGoDone = 1;
57
58
    while (1)
59
    {
60
61
    }
62
}
63
64
//Controller ini
65
void ini()
66
{
67
    OSCCON = 0xFF;
68
69
    TRISA = 0xEF;
70
    TRISB = 0xFF;
71
    TRISC = 0x0F;
72
    TRISD = 0x00;
73
    TRISE = 0xF8;
74
    TRISF = 0x01;
75
    TRISG = 0x00;
76
77
    LATA = 0x00;
78
    LATB = 0x00;
79
    LATC = 0x00;
80
    LATD = 0x00;
81
    LATE = 0x00;
82
    LATF = 0x00;
83
    LATG = 0x00;
84
}
85
86
// AD Wandler ini
87
void ad_ini()
88
{
89
    INTCONbits.PEIE  = 1;        // Enable peripheral interrupt
90
    INTCONbits.GIE   = 1;        // enable global interrupt
91
    // Analog Kanal
92
    ADCON0bits.CHS0  = 1;
93
    ADCON0bits.CHS1  = 1;
94
    ADCON0bits.CHS2  = 0;
95
    ADCON0bits.CHS3  = 0;
96
97
    ADCON1bits.VCFG0 = 0;
98
    ADCON1bits.VCFG1 = 0;
99
    ADCON1bits.PCFG0 = 1;
100
    ADCON1bits.PCFG1 = 0;
101
    ADCON1bits.PCFG2 = 0;
102
    ADCON1bits.PCFG3 = 1;
103
104
    ADCON2bits.ACQT0 = 0;
105
    ADCON2bits.ACQT1 = 0;
106
    ADCON2bits.ACQT2 = 1;
107
108
    ADCON2bits.ADFM  = 1;   //right justified
109
    ADCON2bits.ADCS0 = 1;
110
    ADCON2bits.ADCS1 = 0;
111
    ADCON2bits.ADCS2 = 0;
112
    delay_ms(200);
113
    PIE1bits.ADIE    = 1;
114
    ADCON0bits.ADON  = 1;
115
}
116
117
//Zeitverz?gerung
118
void delay_ms(int a)
119
{
120
    for (a;a>=0;a--)
121
    {
122
        __delay_ms(1);
123
    }
124
}

von Hans Wiederkehr (Gast)


Lesenswert?

Hat ihnen der Code und das Schema weitergeholfen?

Das Problem besteht leider noch immer

von WehOhWeh (Gast)


Lesenswert?

Da fehlt noch etwas.
Leider bin ich jetzt kein Experte für die 8-Bitter, aber meiner Meinung 
nach sampelt der nur einen Wert, und den nach dem Starten.

Du wirst irgendeine Art von Code benötigen, der wiederholtes Samplen 
anstößt. So wie ich nach kurzem Blick in das Datenblatt sehe, muss man 
ADCON0bits.GO (ist das ADGoDone?) oder wie das heißt manuell sezten, um 
einen neuen Wert zu erhalten.

Das müsste meiner Meinung nach in die While-schleife rein. Also grob 
sowas:
ADGoDone = 1             //Wert anfordern
while(!ADGoDone){}       //Warten, bis er fertig ist
Wert lesen               //irgendwas mit dem Wert machen

Siehe auch S275 im Manual, dort ist es beschrieben.

Der erste Wert ist immer Mist, weil kurz nach dem Einschalten sich die 
Versorgungen noch nich stabilisiert haben. Außer du verwendest einen 
externen Brown-Out-Detector.

von Hans Wiederkehr (Gast)


Lesenswert?

Ja genau ADGoDone ist dieses ADCON0bits.Go.
Dieses setze ich jedoch immer wieder in dem Interrupt, welches ausgelöst 
wird, sobald der ADC fertig gerechnet hat.
Im meinem DEBUGGER ändert sich der Wert des ADRES auch immer wieder, 
also der rechnet immer wieder neu.

von WehOhWeh (Gast)


Lesenswert?

Ah, ok, ich habe das Problem völlig missverstanden. Lesen und verstehen 
sind doch zwei paar Stiefel.

Wenn alle Werte zu hoch sind (unabhängig vom Kanal) und trotzdem 
unterschiedlich dann ist irgendwas mit der Referenz falsch oder es gibt 
ein Hardwareproblem.

Folgendes würde ich mal anschauen:
- Alle analogen Spannungen und AVDD mit dem Multimeter kontrollieren und 
mal nachrechnen, ob es nicht doch stimmt
- Nochmal schauen, ob du wirklich den richtigen Pin auswählst
- Die Aquisition Time hochdrehen (Siehe S276)
- Werden ADRESH/ADRESL richtig zusammengepfriemelt?

von Chris B. (dekatz)


Lesenswert?

Acquisition Time und  A/D Conversion Clock dürften für 8MHz richtig 
ausgelegt sein.
Sind alle Vss und Vdd Pins angschlossen, diese auch jeweils mit einem 
100nF Kondensator versehen?
Und wie "sauber" ist die Versorgungsspannung aus dem DC/DC Wandler?

von ginger (Gast)


Lesenswert?

Also ich seh da keine ADRES
 Variable. Wo liest du den dieAD Register aus?

von Hans Wiederkehr (Gast)


Lesenswert?

Ich habe alle Spannungen nochmal gemessen und sie stimmen alle überein.
Pin ist der richtige gewählt, sonst gibt es erst recht Müll raus.
Mit der Zeit habe ich schon herumgespielt und alle mögliche probiert, 
doch nichts will so recht.
Ja werden sie, ich habe mit ADRES, ADRESL und ADRESH während dem 
debuggen als variable anzeigen lassen, doch es stimmte zu 100%

von Hans Wiederkehr (Gast)


Lesenswert?

Nein ich habe bloss einen 1uF Kondensator für alle zusammen eingesetzt, 
kann das so viel ausmachen?

von Hans Wiederkehr (Gast)


Lesenswert?

Ich kann mit dem Compiler ADRES als solches direkt zusammenadiert 
herauslesen, habe es aber auch schon so probiert:
ADRES = (ADRESH * 256) + ADRESL;
was zum genau gleichen Ergebnis  geführt hat

von Chris B. (dekatz)


Lesenswert?

Hans Wiederkehr schrieb:
> Nein ich habe bloss einen 1uF Kondensator für alle zusammen eingesetzt,
> kann das so viel ausmachen?

Unter Umständen - JA.

von Uwe N. (ulegan)


Lesenswert?

Hast du AVDD und AVSS überhaupt angeschlossen? Pin 19 und 20 scheinen an 
deinem Prozessorsockel frei zu sein.
Wie hoch ist AVDD? Wirklich 5V oder nur etwa 3,9V ?
AVDD wird als Referenzspannung verwendet!

von Jochen-paul S. (picfan)


Lesenswert?

Hallo,
wenn ich mir Deinen Code so anschaue, denke ich, dass in der adc-ISR, 
nachdem das ADIF abgefragt wird, nicht sofort das ADCON0bits.GO gesetzt 
werden darf, da es ja sonst keinerlei aquisition-time gibt.
Vor dem Setzen des ADCON0bits.GO könnte man ja vorher noch die 
delay-routine aufrufen, c.a. 5mikrosek. dürften genügen.
          freundliche Grüsse J.P.Schloter

von WehOhWeh (Gast)


Lesenswert?

Jochen-paul S. schrieb:
> Hallo,
> wenn ich mir Deinen Code so anschaue, denke ich, dass in der adc-ISR,
> nachdem das ADIF abgefragt wird, nicht sofort das ADCON0bits.GO gesetzt
> werden darf, da es ja sonst keinerlei aquisition-time gibt.
> Vor dem Setzen des ADCON0bits.GO könnte man ja vorher noch die
> delay-routine aufrufen, c.a. 5mikrosek. dürften genügen.
>           freundliche Grüsse J.P.Schloter

Ich denke, dass das mit den ACQT-Bits schon definiert wurde.

Auf S275 im Datenblatt steht tatsächlich sowas:
"3. Wait the required acquisition time (if required)."

Andererseits steht auch das direkt drin:
"The ADCON2 register allows the user to select an
acquisition time that occurs each time the GO/DONE
bit is set. It also gives users the option to use an
automatically determined acquisition time."
(S277)

Das ist mindestens verwirrend formuliert.
Ich denke, das der Text auf S277 richtig ist, weil sonst wären die 
ACQT-Bits komplett sinnlos.

von Hans Wiederkehr (Gast)


Lesenswert?

Wie Uwe Nagel gesehen hat habe ich tatsächlich die AVDD und AVSS nicht 
angeschlossen gehabt, dies ist mir aber neu, dass das define im 
ADWandler nicht auf die Speisung sondern auf diese 2 Pins zugreift.
Jedenfalls funktioniert das Ganze jetzt einwandfrei und ich möchte mich 
herzlich bei allen für die Geduld und den Einsatz bedanken :D

[Problem gelöst]

von Uwe N. (ulegan)


Lesenswert?

Freut mich, dass ich helfen konnte...
Grundsätzlich sind immer alle Versorgungspins anzuschliessen,
auch, wenn die manchmal intern verbunden sind.
Ausnahmen, wie der Vref-Pin beim AVR bestätigen die Regel ;)

von Meckerziege (Gast)


Lesenswert?

Hans Wiederkehr schrieb:
> Layout.png

Das einzige, was diese Ansammlung von Pin-Outs zu einer graphischen 
Netzliste macht, ist saumäßig zu lesen.

Hast du auch einen vernünftigen Schaltplan?

von Toxic (Gast)


Angehängte Dateien:

Lesenswert?

Meckerziege schrieb:
> Das einzige, was diese Ansammlung von Pin-Outs zu einer graphischen
> Netzliste macht, ist saumäßig zu lesen.
>
> Hast du auch einen vernünftigen Schaltplan?

Wozu noch Meckerziege?
Problem wurde doch schon geloest.....
Aber hier ist der Versuchsaufbau dazu - siehe Anhang :-)

==============================================
Hans Wiederkehr schrieb:
> Jedenfalls funktioniert das Ganze jetzt einwandfrei und ich möchte mich
> herzlich bei allen für die Geduld und den Einsatz bedanken :D
>
> [Problem gelöst]
==============================================






copyright:
hochgeladenes Bild stammt von diesem Thread
https://www.muffwiggler.com/forum/viewtopic.php?p=136848&sid=d99d5b641c63b42e7581bb92a32c159e

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.