Forum: Mikrocontroller und Digitale Elektronik PCF8591 ich werd wahnsinnig!!!!!


von Kowalkowski (Gast)


Lesenswert?

Ich versuch seit einer geschlagenen Woche diesen Drecks-Wandler zum
Laufen zu bringen - unmöglich! Und beim Googeln hab ich zig Leute
gefunden, die ähnliche Probleme haben.

Ich will nichts weiter, als die 4 Kanäle des A/D-Wandlers über I2C-Bus
auslesen. Ich verwende sogar die offizielle I2C-Biliothek von
Microchip:

char readAD(char devadr,char channel)
{  unsigned char n;

// write control word to PCF8591

  IdleI2C();
  StartI2C();
  while ( SSPCON2bits.SEN ); // wait until START condition over
  IdleI2C();
  WriteI2C(0x90 | (devadr<<1));
  IdleI2C();
  WriteI2C(0x40 | channel);
  IdleI2C();
  StopI2C();
  while ( SSPCON2bits.PEN );  // wait until stop condition is over

// Read A/D channel

  IdleI2C();
  StartI2C();
  while ( SSPCON2bits.SEN );//wait until start condition over
  WriteI2C((0x91 )| (devadr<<1)));
        IdleI2C();
  ReadI2C(); // don't use first value read
  IdleI2C();
  AckI2C();
  IdleI2C();
  n = ReadI2C();
  IdleI2C();
  NotAckI2C();
  IdleI2C();
  StopI2C();
  while (SSPCON2bits.PEN);// wait until stop condition is over
  return (unsigned char) n;
}

3 von 4 Kanälen kann ich so wunderbar auslesen. Nur einer spinnt rum:
Kanal 2 geht nicht bis auf 0 runter. Selbst wenn ich ihn auf Masse
lege, gibt der Wandler 55 zurück. Was noch schlimmer ist: Dieser Kanal
wird irgendwie von Kanal 1 beeinflusst; wenn ich an Kanal 1 die
Spannung erhöhe, wächst auch der Wert von Kanal 2.

Es wäre ja naheliegend, dass ich das Controlbyte irgendwie falsch
eingestellt habe, und der PCF8591 auf differentielle Eingänge
eingestellt ist - nur: laut Datenblatt gibts überhaupt keine
Konfiguration, wo Kanal 1 und 2 differenziell geschaltet sind!

Ich werd echt noch wahnsinnig. Hab den IC schon 2x ausgetauscht weil
ich dachte ok, vielleicht hab ich den vorher mal zerschossen - aber
genau dasselbe!

Zusammen mit der Tatsache, dass ich bei RS-Komponents diese Mistdinger
für insg. 25 Euro gekauft habe werd ich echt langsam sauer...

von Kowalkowski (Gast)


Lesenswert?

Hier zur Einfachheit halber nochmal im Pseudocode, was ich auf dem Bus
mache:

START
WRITE PCF8591_WRITE_ADDRESS
WRITE CONTROL_BYTE (0x40)
STOP

START
WRITE PCF8591_READ_ADDRESS
READ
ACK
value := READ
NACK
STOP
return value

von TheMason (Gast)


Lesenswert?

hallo kowalskowski,

ich hatte auch das problem das die kanäle ab und zu spinnen.
es ist wichtig das der ad-mode auf 4 single ended inputs steht (müsste
laut deinem statuswort ja auch so sein). bei mir hab ich wohl immer den
dac aus (also statuswort auf 0x00). das einzige problem was ich habe ist
das die kanäle bei mir verwürfelt sind.

hier mal mein code fragment :

VOID BD_vGetFaders (UCHAR *pucValues)
{
  UCHAR ucC, ucV, ucBuff;

  for (ucC = 0; ucC < 8; ucC ++)
  {
    BD_vRD_I2C_Start ();
    ucBuff = BD_ucI2C8591WriteAddress (ucC >> 2);
    BD_bWR_I2C (1, (UCHAR *) &ucBuff);
    // control - wort für adc setzen
    ucBuff = (ucC & 0x03)      << 0 | // kanal
              0                << 2 | // kein autoincrement
              0                << 4 | // 4 single-ended inputs
              0                << 6 ; // kein dac
    BD_bWR_I2C (1, (UCHAR *) &ucBuff);
    BD_vRD_I2C_End ();


    BD_vRD_I2C_Start ();
    ucBuff = BD_ucI2C8591ReadAddress (ucC >> 2);
    BD_bWR_I2C (1, (UCHAR *) &ucBuff);
    ucBuff = BD_bRD_I2C (1, (UCHAR *) &ucV);
    BD_vRD_I2C_End ();

    switch (ucC)
    {
      case 0 : pucValues [3] = ucV; break;
      case 1 : pucValues [0] = ucV; break;
      case 2 : pucValues [1] = ucV; break;
      case 3 : pucValues [2] = ucV; break;
      case 4 : pucValues [7] = ucV; break;
      case 5 : pucValues [4] = ucV; break;
      case 6 : pucValues [5] = ucV; break;
      case 7 : pucValues [6] = ucV; break;
      default: break;
    }
  }
}

Gruß
Rene

von Kowalkowski (Gast)


Lesenswert?

case 0 : pucValues [3] = ucV; break;
      case 1 : pucValues [0] = ucV; break;
      case 2 : pucValues [1] = ucV; break;
      case 3 : pucValues [2] = ucV; break;

Sieht aus als wäre es um 1 versetzt, weil man ja wenn man vom Wandler
liest, immer den letzten Wert kriegt. Also wenn Du Kanal 1 selektierst
und den Wandler ausliest, dann fängt er da erst an Kanal 1 zu wandeln,
gibt Dir aber den Wert des letzten Samples zurück (in dem Fall von
Kanal 0).

Du könntest versuchen, einfach 2x zu lesen und den ersten Wert
wegschmeissen, dann müsste das mit dem Umsortieren unnötig werden.

Ansonsten herzlichen Glückwunsch dass Du schon so weit gekommen bist!!!
:) bin da noch meilenweit von entfernt

Was mir auffällt, Du sendest gar kein NACK nach dem letzten Lesen.
Braucht man vielleicht auch nicht, wenn Du nur einen Wert liest, weil
danach die STOP-Bedingung kommt.

von Benedikt (Gast)


Lesenswert?

Ich hatte diesen Wandler auch mal verwendet.
Nach einer Woche habe ich das Drecksteil entsorgt.

Zum Glück gibt es genügend andere ADC mit SPI o.ä. und zum Glück haben
AVRs ADCs eingebaut...

Was spricht eigentlich dagegen einen AVR als ADC zu verwenden ?
Man kann ja einen Software I2C oder SPI Slave einbauen (oder den USI
verwenden) und so die Daten auslesen.

von Kowalkowski (Gast)


Lesenswert?

Ganz einfach: Ich brauch nicht einen Wandler, auch nicht 2, sondern 12
Stück!

Ich hatte schon mit dem Gedanken gespielt, CD4066 analoge Switches zu
benutzen, um die zu messenden Pegel nacheinander auf den ADC zu
schalten. Problem ist nur: ich hab kaum noch I/Os frei. Also brauch ich
dafür nen Schieberegister mit Latch, frisst wieder 3 Pins und 1 IC mehr
auf der Platine; dann noch 1-of-16 decoder um einen der Switche
auszuwählen => noch ein IC auf der Platine (und die Dinger sind richtig
eklig fett). Ich hatte das sogar mal aufgebaut und hat auch geklappt,
aber ich hab keinen Platz mehr auf der Platine! Für diese Lösung brauch
ich nämlich:

3x4066
1xSchieberegister
1xDecoder

macht 5 ICs. Nein danke.

von Christoph Kessler (Gast)


Lesenswert?

LTC1290 hat 8 umschaltbare Eingänge, gibts bei den üblichen Verdächtigen
zu kaufen. 12 Bit seriell 50 kHz Durchsatzrate, den hab ich schon in
Assembler auf AVR benutzt.
http://www.linear.com/pc/productDetail.do?navId=H0,C1,C1155,C1001,C1158,P1594

von TheMason (Gast)


Lesenswert?

Hallo Kowalkowski,

also bis auf diesen versatz (um einen Kanal) hatte ich eigentlich keine
größeren Probleme mit dem PCF8591. Hab den schon vor Jahren benutzt und
der hats immer getan. Kanns denn vielleicht sein das in der beschaltung
was nicht ok ist ?
Was mit softwaremässig noch einfällt : Ich hatte kurzzeitig mal
probleme. Das lag daran das ich einen Software-I2C verwendet habe und
der einfach zu schnell war. Da kamen dann auch ganz komische effekte
bei raus. Sonst mach doch mal einfach eine SW-I2C und das gaaaanz
langsam (I2C geht ja runter bis DC).
Wäre ja echt ärgerlich wenn du deine ganzen PCFs wegschmeißen kannst.

Gruß
Rene

PS. Mal eine Frage zu den SPI-Wandlern. Gibt es kostengünstige A/D
Wandler mit SPI ? Mit kostengünstig meine ich ca. 1/5 oder 1/10 des
preises was ein PCF8591 (ca 3 Euros) kostet ? Die Geschwindigkeit ist
egal (selbst 2kHz bei 8bit reichen) es geht nur um fader und Potis ...

von Benedikt (Gast)


Lesenswert?

>Gibt es kostengünstige A/D Wandler mit SPI

Da wäre z.B. meine Idee mt dem AVR:
Ein ATTiny26 bietet 10x  10bit ADCs. Ein SPI Interface kann man mit dem
USI leicht bauen. Das ganze kostet dann 2€.
Wenn man mehr Kanäle braucht, hängt man halt noch ein paar Multiplexer
dran, die der AVR ansteuert. So kann man leicht 20 und mehr Kanäle
erreichen.

von Sven (Gast)


Lesenswert?

Hi,

nichts für ungut, aber ich habe Riesenprobleme mit dem LTC1290
gehabt, obwohl da auch Bausätze angeboten werden...
(siehe ELV oder Conrad)

Mein Favorit ist der von TI ADS7828, der hat I2C, kostest ca. 6-8 Euro
und ist SMD. Kann 8 Kanäle und funktionierte mit AVR Mega.
(AVR Experimentierboard aufgebaut und Adapter Platine gelötet;
insgesamt mit viel Ruhe ca. 1 Stunde...)

Zum PCF kann ich nichts direktes sagen, da das alles auf den ersten
Blick gut aussieht.

Ich unterstütze aber das mit dem Timing. Wenn Du zu schnell arbeitest
treten bei bestimmten ICs solche Nebeneffekte auf. Versuchen mal mit
Delays die Taktrate runterzusetzen...

Gruß Sven

von TheMason (Gast)


Lesenswert?

Hallo Benedikt,

prinzipiell würde ich dir ja auch zustimmen. Ich weiß nur nicht ob sich
das rechnet. Man benötigt für einen AVR-ADC-mit-irgendwas-Interface ja
auch immer eine Platine (je nachdem welchen AVR man verwendet) und mit
der Platine ists ja auch nicht getan. Der uC will ja auch noch seine
SW. Und wie ich gestern erfahren hab ist das mit dem Debugging von AVRs
ja so eine Sache. Also ich weiß nicht ob der Preisunterschied von sagen
wir mal 4 Euro (2 PCF8591 = 8 Kanäle = 6Euro <-> AVR 8-10 Kanäle = 2
Euro) die Software "mal eben" enstehen lässt. Zumal man dann ja an 2
Baustellen gleichzeitig ist, während man bei fertigen Chips (bis auf
eventuelle Hardware-Fehler, die beim AVR aber genausoauftreten können)
nur noch 1 Baustelle hat.

@kowalkowski :

Ich hab gerade noch einen evtl. interessanten Wandler gefunden :
TLC541. Scheint ganz lustig zu sein. Problem : der braucht 2 Takte
(System-Takt und IO-Takt), aber den kann man ja evtl. in einem
bestehenden System an einen Port Pin erzeugen, da der System-Takt wie
der IO Takt praktisch (laut Datenblatt) bis zu DC runtergehen kann. Und
was ich ganz praktisch finde : Ich brauche keine neg.
Versorgungsspannung.

Für was für eine Anwendung brauchst du denn soviele Kanäle ? Poti/Fader
Feld ?! :-)

Gruß
Rene

von TheMason (Gast)


Lesenswert?

ach ja ... zum thema tlc540/tlc541 noch was ...

11 kanäle (allerdings multiplexed) und bei reichelt 2,80 euros (zwar
nicht billiger, aber dafür knapp 3mal soviele eingänge :-)))

von Kowalkowski (Gast)


Lesenswert?

Mhmm darf man die Taktrate beliebig einstellen? Ich dachte es gibt nur 3
verschiedene Versionen: 100Khz, 400Khz und 1.irgendwas Mhz (high-speed).
Aber guter Tip, ich versuch mal das runterzuschrauben. Laut Datenblatt
sollte der aber 100Khz vertragen...

Software-I2C könnte ich zur Not auch machen; gibts jede Menge
Sourcecode für, aber der PIC hat das hardwaremäßig und wäre unsinn das
nicht auch zu benutzen!

Zur Beschaltung: Ich hab 2x 10K Pull-Up's in der Daten und
Taktleitung, sonst eigentlich nix besonderes. Als
Referenzspannungsquelle eine Zenerdiode, allerdings ungepuffert; der
PCF zieht aber laut DB nur einige Mikroampere.

von Kowalkowski (Gast)


Lesenswert?

Die Kanäle brauch ich für mein digitales symmetrisches Netzteil: 2x
Spannung & Strom messen für + und - Ausgang (macht 4 Kanäle), dann noch
Festspannungen (5V,12V,15V) je Spannung und Strom macht nochmal 6, und
noch welche um das Poti auszulesen.

von Marcus (Gast)


Lesenswert?

I2C kannsde auch mit 1Hz machen wenn du lustig bist (und zeit hast)...

meine probleme bei I2C waren zB, dass die STOP Cond. zu schnell erzeugt
wurde... also die flanken von SDA und SCL zu schnell hintereinander
kamen... das wird bei dir aber nicht der fall sein, da ja nur ein kanal
spinnt...

von TheMason (Gast)


Lesenswert?

hallo kowalkowski,

also hw-i2c sollte es auch tun (obwohl ich es bis jetzt noch nicht
ausprobiert habe, da ich keinen prozi habe der hw-i2c hat, nutze den
msp430f149). aber 1.irgendwas MHz kann der PCF keinesfalls. hatte mit
dem r8c board aus der elektor mein i2c grab (3 pcf8574 und 2 pcf8591)
per sw-i2c angesteuert. ohne delay funktionierten nur die 8574, aber
die 8591 haben rumgesponnen. nach groben überschlagen kam ich dann zu
der einsicht das ich mit mehr als 400kHz arbeite, und das mögen die
wohl nicht. nach einfügen einiger nop's funktionierten dann auch die
8591 tadellos.
interessantes projekt dein universal-netzteil. wie hast du denn die
strom-messung gemacht ? einfach nen shunt und dann nen op dahinter ?
mich würde sowas auch interessieren, allerdings bin ich eher auf der
suche nach einem ic das in strom und spannung regelbar ist, aber ob
sich der aufwand für mich lohnt weiß ich noch nicht. mal schauen

gruß
rene

von Kowalkowski (Gast)


Lesenswert?

Shunt iss gut, bei geplanten 20A kannste das vergessen - selbst bei
0.1Ohm kannste den als Heizung benutzen ;) Ein genau abgemessenes Stück
Draht auf der Platine, mit OP-Amp gepuffert, mehr nicht.
Bessere Lösung wäre ein Hallsensor, aber die sind sauteuer (15 Euro).
Dann lieber ein Stück Kupferdraht :)

von Kowalkowski (Gast)


Lesenswert?

Die Stromregelung ist übrigens sehr einfach zu realisieren; man koppelt
einen Teil der am Shunt/Draht abgefallenen Spannung zurück auf einen
Transistor, der dem Längstransistor den Basisstrom "klaut". Ab
Überschreiten der Schwellspannung kann der Längstransistor nicht mehr
weiter aufmachen, und der Strom kann nicht steigen. Den Maximalstrom
kann man mit einem Poti einstellen, welcher die am Shunt abgefallene
Spannung runterteilt.

Übrigens: Die brutalste Lösung für ein 20A Netzteil sind einfach 20
78319 einstellbare Spannungsregler auf ein fettes Kühlblech zu packen
:)))

Besser wäre es, anstatt eines Längstransistors einen FET zu nehmen,
aber da fehlt mir noch das nötige Wissen zu...

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.