mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PIC18f1220 ADU Problem


Autor: Fff Ttt (teichert)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Fff Ttt (teichert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?:
        DDRB = 0x0E;
  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.

Autor: Fff Ttt (teichert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

#include <stdlib.h>
#include <adc.h>
#include <delays.h>
#include <p18f1220.h>

#pragma config WDT = OFF

#define __OUTPIN PORTBbits.RB0

void init (void) {
  OSCTUNE = 0x00;


  DDRB = 0x0E;
  DDRA = 0x03;

  OpenADC ( ADC_FOSC_RC      // Umsetzung mit dem Oszillatortakt
        & ADC_RIGHT_JUST   // Rechtsbündiges Ergebnis in Integer
        & ADC_12_TAD,
          ADC_CH0          // Kanal 0
        & ADC_INT_OFF      // Interrupts deaktivieren
        & ADC_VREFPLUS_EXT // Referenzspannung ist die Versorgungsspannung
        & ADC_VREFMINUS_EXT // Negativ aus masse..
    ,15  ); 
  Delay10TCYx(50);

  return;
}


void main (void) {
  
  int speed=0;
  

  // Initialisierungen durchführen:
  init();


  blink(100, 3);


  while (1) {
    

    ConvertADC();
    // Auf die Umsetzung warten:
    while(BusyADC())
      ;
    //speed = (ReadADC() >> 5);
    speed = ReadADC();
    
    // der eingelesene wert an dieser stelle schwankt zwischen dem eingestellten wert und
    // irgendwelchem müll (vermutlich null)
    speed = (speed >> 9);
    //if ((speed > 20) || (speed < 10)) {
    if (speed) {
      __OUTPIN = 1; 
    } else {
      __OUTPIN = 0;
    }
    
  }
}

Autor: Fff Ttt (teichert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Hier mal so die Fehler die mir auffallen:
#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:
void init()
{
  TRISA = 0x01;  //RA0 = Input
   
  //Analogwandler Einstellungen
  ADCON1 = 0x01;   //RA0 = Analog Input
  ADCON0 = 0x00;  //Enspricht deinen einstellungen
  ADCON2 = 0xAF; //-------||---------------

  ADCON0 = 0x01; // Enable ADC

  Delay10TCYx(50);
}

int read_ADC_bool ()
{
  ADCON0bits.GO = 1; //Start ADC

  while(ADCON0bits.GO); //Wait for A/D conversion to complete

  return ADRESH>>1;
}

Ich hab den Code jetzt nicht ausprobiert... aber so in etwa sollte das 
funktionieren.

mfg Schoasch

Autor: Fff Ttt (teichert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
(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:
(ad_val & 0x0008)?1:0;
kann dieser Wert problemlos einem Ausgang zugewiesen werden.

Ein Bit einem Ausgang zuweisen sieht also folgendermaßen aus:
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.

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Naja.. es ist schon klar, dass
(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 :
PORTBbits.RB0 = (ad_val & 0x0008)?1:0;
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.

Autor: Fff Ttt (teichert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das fiel mir geestern Abend dann auch noch ein.

Das Programm ist fertig und funktioniert.

MfG

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.