Hallo, wir arbeiten gerade an einem Studienprojekt. Es soll ein Fahrpult für eine digitale Modelleisenbahn erstellt werden (CCD-Protokoll). Hierzu verwenden wir eine selbergelötete Platine mit einem PIC18f1220. Um die gewünschte Geschwindigkeit zu ermitteln, wird ein analoger Wert eines Potis (10kOhm) eingelesen, umgewandelt, daraus eine Rechteckspannung erzeugt und soll ausgegeben werden. Um das Board zu testen, habe ich den 10Bit-ADU sozusagen auf 1Bit Genauigkeit beschränkt und das Bit an dem Ausgangsport ausgegeben, an dem sich eine LED befindet. Diese LED ist die einzige Debugging-Möglichkeit, die wir haben! Bewege ich nun das Poti über die Mittelstellung hinaus, beginng die LED zu leuchten! so soll es sein. Allerdings leuchtet sie nicht permanent, sondern blinkt. Es scheint als würde der ADU ab und zu falsche Werte liefern. Kennt jemand das Problem oder eine geeignete Lösung dazu? Zum Programmieren verwenden wir die MCC18-Studenten-Version. Zum Programmieren das PIKKIT2 (weil wir es leihen konnten..). In dem Datenblatt steht etwas davon, dass der ADU über höchstens 2,5kOhm geladen werden darf - wir verwenden aber 10kOhm. Daher habe ich versucht diesen zu überbrücken. Leider ließ sich der Fehler dadurch nicht beheben. Die LED am Ausgang wird ohne externen Vorwiderstand betrieben. Ich meine a ber, dass die verwendeteten LEDS einen besitzen. Wird beispielsweise der Ausgang nur auf HIGH gesetzt, leuchtet die LED durch, sodass ich nicht davon ausgehe, dass die Spannung zusammenbricht, weil die LED zuviel Strom zieht o.ä. . Vielen Dank. MfG
Hi 1. LEDs brauchen immer einen Vorwiderstand!!!! Ansonst zerstörst du die LED und den Pin! 2. 10kOhm sind schon recht hoch. Hast du dir mal TAD Ausgerechnet? Die Formel dazu findest du im Datenblatt. Ich hab jetzt nicht nachgerechnet oder mit deinem Code verglichen... aber verlänger einmal die Wartezeit. Falls dir das zu lange dauert, musst du dann entweder das Poti kleiner machen, oder aber eine Treiber vorschalten. mfg Schoasch
Vielen Dank für die Antwort. Die LEDs haben einen Vorwiderstand eingebaut - habe nochmal nachgesehen. die TAD habe noch nicht ausgerechnet. Habe aber alle möglichen TAD-Zeiten durchprobiert und konnte keine Veränderung des Problems feststellen. Außerdem habe ich ja das Poti überbrückt und dieselben Probleme erhalten. Andere Ideen? MfG
Hi Ich will nicht unhöflich sein, aber dein C-Code ist sehr unangenhem zu lesen. Kannst du mal ein File anhängen in dem nur der Code drinn ist, der für das PRoblem wirklich gebraucht wird. Was mir abgeht, ist die Initialisierung der TRIS-Registers.Soll das das sein?:
1 | DDRB = 0x0E; |
2 | DDRA = 0x03; |
(DDRx kenn ich nur von den ATMega... bei den PIC hab ich so ein register noch nie gsehen ;-)) Hast du schon mal Probiert, ohne den Funktionen aus der adc.h das AD-Wandlermodul zu betreiben. Also echt von Hand die ganzen Bits setzen? Ich würd dir da eifnach empfehlen, dass du dir selbst deine Init routine zusammenstellst. ISt nicht viel aufwand, aber dann lernst du was und die Fehlersucher wird einfacher. mfg schoasch PS.: Ich habs nochmal überflogen... ich seh hier nirgends einen Zugriff auf ein TRIS-Regsiter! Ausserdem solltest du beim schreiben nicht ins Port-Register sondern ins LAT-Register schreiben. Damit vermeidest du read-modify-write Probleme.
Ja, der Code hat etwas "Baustellen-Charakter" .. Ich habe ihn mal etwas gesäubert. Ich hatte eigentlich gehofft, durch die Verwendung der herstellereigenen Libraries das manuelle Setzen einzelner Bits zu vermeiden. Ich gehe davon aus, dass die Libraries fehlerfrei implementiert sind. Habe aber keine Ahnung, ob ich mich darauf unbedingt verlassen könnte. Vielleicht findet jetzt jemand das Problem. Ich werde die manuelle Methode morgen testen. MfG
1 | #include <stdlib.h> |
2 | #include <adc.h> |
3 | #include <delays.h> |
4 | #include <p18f1220.h> |
5 | |
6 | #pragma config WDT = OFF
|
7 | |
8 | #define __OUTPIN PORTBbits.RB0
|
9 | |
10 | void init (void) { |
11 | OSCTUNE = 0x00; |
12 | |
13 | |
14 | DDRB = 0x0E; |
15 | DDRA = 0x03; |
16 | |
17 | OpenADC ( ADC_FOSC_RC // Umsetzung mit dem Oszillatortakt |
18 | & ADC_RIGHT_JUST // Rechtsbündiges Ergebnis in Integer |
19 | & ADC_12_TAD, |
20 | ADC_CH0 // Kanal 0 |
21 | & ADC_INT_OFF // Interrupts deaktivieren |
22 | & ADC_VREFPLUS_EXT // Referenzspannung ist die Versorgungsspannung |
23 | & ADC_VREFMINUS_EXT // Negativ aus masse.. |
24 | ,15 ); |
25 | Delay10TCYx(50); |
26 | |
27 | return; |
28 | }
|
29 | |
30 | |
31 | void main (void) { |
32 | |
33 | int speed=0; |
34 | |
35 | |
36 | // Initialisierungen durchführen:
|
37 | init(); |
38 | |
39 | |
40 | blink(100, 3); |
41 | |
42 | |
43 | while (1) { |
44 | |
45 | |
46 | ConvertADC(); |
47 | // Auf die Umsetzung warten:
|
48 | while(BusyADC()) |
49 | ;
|
50 | //speed = (ReadADC() >> 5);
|
51 | speed = ReadADC(); |
52 | |
53 | // der eingelesene wert an dieser stelle schwankt zwischen dem eingestellten wert und
|
54 | // irgendwelchem müll (vermutlich null)
|
55 | speed = (speed >> 9); |
56 | //if ((speed > 20) || (speed < 10)) {
|
57 | if (speed) { |
58 | __OUTPIN = 1; |
59 | } else { |
60 | __OUTPIN = 0; |
61 | }
|
62 | |
63 | }
|
64 | }
|
Um möglichen Antworten zuvorzukommen: blink() ist jetzt nicht mehr im Code, wird aber verwendet. An der LED soll nur das MSB des ADU-Werts ausgegeben werden. Danke.
Hi Hier mal so die Fehler die mir auffallen:
1 | #define __OUTPIN PORTBbits.RB0
|
Wie schon erwähnt... schreib nicht in die PORT-Register sondern in die LAT-Register! So... ich hab mal folgendes geschrieben:
1 | void init() |
2 | {
|
3 | TRISA = 0x01; //RA0 = Input |
4 | |
5 | //Analogwandler Einstellungen
|
6 | ADCON1 = 0x01; //RA0 = Analog Input |
7 | ADCON0 = 0x00; //Enspricht deinen einstellungen |
8 | ADCON2 = 0xAF; //-------||--------------- |
9 | |
10 | ADCON0 = 0x01; // Enable ADC |
11 | |
12 | Delay10TCYx(50); |
13 | }
|
14 | |
15 | int read_ADC_bool () |
16 | {
|
17 | ADCON0bits.GO = 1; //Start ADC |
18 | |
19 | while(ADCON0bits.GO); //Wait for A/D conversion to complete |
20 | |
21 | return ADRESH>>1; |
22 | }
|
Ich hab den Code jetzt nicht ausprobiert... aber so in etwa sollte das funktionieren. mfg Schoasch
Hallo, heute habe ich mit meinem Kommilitonen alle Probleme beseitigen können. Mit Hilfe eines Oszilloskops, konnten wir relativ schnell die Lösung des Fehlers finden. Den ADU initialisieren wir jetzt manuelle. Der Fehler lag leider an einer ganz anderen Stelle. Entweder war dieser ein Problem des C-Compilers oder war "hausgemacht": Der Code
1 | (ad_val & 0x0008) |
soll beispielsweise Bit(3) auf "Gesetzt-Sein" prüfen und gibt ja (meine ich jedenfalls normalerweise) 1 zurück, sodass man diesen Rückgabewert einem Bit (beispielsweise einem Ausgangsbit) zuweisen kann. -> Dem ist scheinbar gar nicht so! Ersetzt man diesen Code jetzt durch folgendes:
1 | (ad_val & 0x0008)?1:0; |
kann dieser Wert problemlos einem Ausgang zugewiesen werden. Ein Bit einem Ausgang zuweisen sieht also folgendermaßen aus:
1 | PORTBbits.RB0 = (ad_val & 0x0008)?1:0; |
(Weist dem Ausgang Bit(0) an PORTB das Bit(3) von ad_val zu..) Ob der ADU nun mit der Initialisierung, die wir zunächst durch die Libraries vorgenommen hatten, funktioniert hätte oder nicht, sei dahingestellt - vermutlich schon. Das Problem war also nur, dass die abgefragten Bits gar nicht am Ausgang erscheinen konnten, weil o.g. Ausdruck nicht das erwartete Ergebnis lieferte.. Auf den Fehler kamen wir, nachdem wir zunächst versucht hatten die Bits des ADU-Ergebnisses "seriell" am Ausgang auszugeben und, durch einen weiteren Port getriggert, auf dem Oszilloskop anzeigen zu lassen (was zunächst nicht gelang) und wir anschließend den Wert durch eine Konstante ersetzten, die ebenfalls gar nicht angezeigt wurde. Ein Geistesblitz konnte den Fehler beheben. Ich hoffe, dass dieser Thread anderen über dieses Problem hinweghelfen kann. Ansonsten danke ich der freundlichen Unterstützung.
Hi Naja.. es ist schon klar, dass
1 | (ad_val & 0x0008) |
nicht 1 zurück gibt. Denn es gibt ja entweder 0x0000 oder 0x0008 zurück. Ich will ja nicht pingelig sein... aber um weitere Fehler zu vermeiden solltest du in LAT-Register schreiben. Denn wenn du :
1 | PORTBbits.RB0 = (ad_val & 0x0008)?1:0; |
2 | PORTBbits.RB1 = 1; |
schreibst, kann es dir passieren das dir nur RB1 gesetzt wird und RB0 ignoriert wird. WEnn du die LAT-Register verwendest, passiert das nicht.
Ja, das fiel mir geestern Abend dann auch noch ein. Das Programm ist fertig und funktioniert. MfG
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.