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?
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
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 | }
|
Hat ihnen der Code und das Schema weitergeholfen? Das Problem besteht leider noch immer
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.
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.
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?
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?
Also ich seh da keine ADRES Variable. Wo liest du den dieAD Register aus?
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%
Nein ich habe bloss einen 1uF Kondensator für alle zusammen eingesetzt, kann das so viel ausmachen?
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
Hans Wiederkehr schrieb: > Nein ich habe bloss einen 1uF Kondensator für alle zusammen eingesetzt, > kann das so viel ausmachen? Unter Umständen - JA.
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!
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
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.
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]
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 ;)
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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.