Forum: Mikrocontroller und Digitale Elektronik SPI mit ESP8266 und AD1217


von Olaf (Gast)


Angehängte Dateien:

Lesenswert?

Ich versuche seit ein paar Tagen ein Problem mit der SPI Kommunikation 
zwischen einem ESP8266 und einem ADS1217 zu loesen und komme da Leider 
nicht recht weiter. Also dachte ich ihr loest mal eben mein Problem. :-)

Der ADS1217 ist mit POL=1 verdrahtet. Damit sollte er im SPI-MODE3 
laufen,
das erste Bild zeigt einen ausschnitt aus dem Datenblatt wie sich TI das 
vorgestellt hat.

Das Bild Oszi1.gif zeigt die Uebertragung sowohl des Logiganalyser wie 
auch nochmal das SCK-Signal auf dem analogen Eingang.

Das sieht nach meiner Meinung so aus wie es laut Datenblatt aussehen 
sollte. Widerspruch?

Der ADS1217 ist ein AD-DA Wandler der zusaetzlich noch einen 8Bit 
Datenport enthaelt. Um die Sache einfach zu halten beschreibe und lese 
ich erstmal diesen Datenport. Ich habe an den oberen drei Bits dieses 
Ports eine RGB-Led angeschlossen, D2 liegt auf high und alles andere auf 
low.

Das Kommando 0x56 0x00 0x80 beschreibt als Beispiel den Port mit 0x80 
und schaltet so z.B meine gruene LED ein. Ich gebe so einmal pro Sekunde 
immer abwechselnd 0x20 0x40 und 0x80 aus. Das sollte also dazu fuehren 
das die LED munter blinkt. Das tut sie aber in der Regel nicht. Sie 
blinkt manchmal garnicht, manchmal nur in einer Farbe und manchmal auch 
genau wie sie soll.

Ignoriere ich einfach mal die Vorgaben laut Datenblatt und probiere alle 
Modi durch so kann ich in Mode0, was auf dem Oszi dann total falsch 
aussieht die LED korrekt und zuverlaessig ans blinken bringen. Lese ich 
dann aber testweise den Port ein so liefert der erste Versuch immer 
Unsinn und danach bekomme ich dann den richtigen Wert. Lese ich 
zwischendurch etwas anderes werden die reinkommenden Daten immer ander 
verwuerfelt. So kann es z.B sein das ich einen ADC-Wert lesen will, aber 
den den Inhalt des Portregisters bekomme wenn ich das zuvor versucht 
habe.

Mit anderen Worten es sieht so aus als wenn keiner der vier moeglichen 
Modis funktioniert. Ich sollte vielleicht noch erwaehnen das ich am 
selben Anschluss, aber nicht gleichzeitig, vollkommen problemlos diverse 
Grafik-LCDs ans laufen bringen konnte.
Schalte ich POL=0 bekomme ich genau dasselbe Ergebnis aber dann in 
anderen SPI_Modes. In keiner der acht denkbaren Kombinationen kann ich 
immer zuverlaessig lesen UND schreiben.

Ich hab daher den Eindruck als wenn sich der ADS1217 nicht ganz an sein 
Datenblatt haelt. Hat schon mal jemand mit diesem IC (oder ADS1216, 
ADS1241, ADS1241) aehnliche Erfahrungen gemacht?

Olaf

von Olaf (Gast)


Lesenswert?

Noch was..wer das Datenblatt dieser AD-Wandler liesst wird erkennen das
man beim lesen eines Wertes vor der letzten lesenden SPI-Uebertragung 
eine kleine Pause einlegen muss. Daran halte ich mich!

  SPI.transfer(SendData); //Schreibkommando für das gewünschte Register
  SPI.transfer(0x00);     //0x00 bedeutet das wir ein Register lesen 
wollen

  //Wartezeit laut Datenblatt seite 20
  //fuer ReadReg ist das 50xOscilatorperioden = 50x 1/4Mhz = 12.5us
  delayMicroseconds(30);

  ReadData = SPI.transfer(0x00);

Ich hab zu Testzwecken auch schon sehr viel laenger gewartet ohne das 
dies einen Unterschied machte.

von Michael U. (amiga)


Lesenswert?

Hallo,

mit den SPI-Modi 2 und 3 gab es mehrere Probleme, speziell aus der 
Arduino-IDE. Auch im SDK gab es wohl Unklarheuten bei der Beschreibung 
der Registerbits.
Ich weiß nicht, ob das behoben wurde, ich habe hier nichts zur Hand, was 
nicht mit Mode 0 oder 1 läuft.

Gruß aus Berlin
Michael

von Olaf (Gast)


Angehängte Dateien:

Lesenswert?

> mit den SPI-Modi 2 und 3 gab es mehrere Probleme, speziell aus der
> Arduino-IDE.

Mode2 und Mode3 sind vertauscht. Ist aber nur eine Zeile im source das 
richtig zu biegen. Ist auch irrelevant weil ich ja das als Referenz 
ansehe was mein Oszi anzeigt und das scheint mir richtig zu sein.

Ich hab mal mein Testprogramm geaendert:

1. Digital-PORT auf 0 setzen.
2. Digital-PORT auf 0x40 setzen
3. Digital-PORT auf 0 setzen
4. 200ms Pause dann wieder von vorne.

Der gelbe Kanal zeigt den Portausgang D6 an. Man wuerde also erwarten 
das der Port nach (2) auf high geht und nach (3) wieder auf low.

Die drei Bilder zeigen nun drei beliebige Triggerevents. Jedesmal anders 
und nie wie man es erwartet.

An dieser Stelle wuerde ich jetzt darauf wetten das etwas mit dem SCK 
nicht stimmt. Das sieht aber (Analogkanal, Tastkopf mit Massefeder) 
absolut perfekt aus. Keine Ueberschwinger nichts. Entweder ich bin zu 
doof das Datenblatt zu lesen oder das IC hat eine Macke. Ich hab das IC 
allerdings auch schonmal gewechselt....

Olaf

von Olaf (Gast)


Lesenswert?

Ich habs jetzt zuverlässig und gut laufen. :-)

Mein Problem war das ich zwei Bugs hatte. Der eine war eigene Bloedheit, 
ich hatte einen der Pinne (!DSYNC) fuer einen Ausgang gehalten und 
nirgendwo angeschlossen. ARGH! Nachdem ich den angeschlossen habe lief 
es erstmal, bis auf eine sehr faszinierende Kleinigkeit. Bei jeder 
Uebertragung kamen immer alle Bits korrekt im ADS1217 an, aber beim 
auslesen war Bit0 des jeweils letzten uebertragenen Bytes im ESP8266 
immer 0. Egal was ich gelesen habe!
Dabei sah auf meinem Oszi alles korrekt aus und wurde auch vom Oszi 
korrekt
dekodiert.

Die Loesung sah dann so aus:

  SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODUS));
  digitalWrite(CS, LOW);
  SendData = RREG | (RegisterNumber & 0x0f);
  SPI.transfer(SendData); //Schreibkommando für das gewünschte Register
  SPI.transfer(0x00);     //0x00 bedeutet das wir ein Register lesen 
wollen
  delayMicroseconds(20);
  ReadData = SPI.transfer(0x00);

  delayMicroseconds(5);   //DAS IST WICHTIG

  digitalWrite(CS, HIGH);
  SPI.endTransaction();


Aus Gruenden die mir ein echtes Raetzel sind braucht der ESP8266
zumindest mit dem ADS1217 eine kleine Wartezeit bevor er CS wieder 
hochsetzt. Dafuer kann ich mir keinen logischen Grund vorstellen weil
das einlesen mit der Rueckkehr aus der transfer Methode bereits 
abgeschlossen sein sollte.

Falls also jemand aehnliche Probleme hat empfehle ich ihn das mal 
auszuprobieren.

Olaf

von Werner P. (Gast)


Lesenswert?

Olaf schrieb:
> Aus Gruenden die mir ein echtes Raetzel sind braucht der ESP8266
> zumindest mit dem ADS1217 eine kleine Wartezeit bevor er CS wieder
> hochsetzt. Dafuer kann ich mir keinen logischen Grund vorstellen weil
> das einlesen mit der Rueckkehr aus der transfer Methode bereits
> abgeschlossen sein sollte.
>
> Falls also jemand aehnliche Probleme hat empfehle ich ihn das mal
> auszuprobieren.

die Probleme hatte ich auch. Die Transfer Methode wird verlassen auch 
wenn der Transfer noch nicht abgeschlossen ist.

ich habe das mit einer Funktion gelöst:

void HSPI::wait(uint16_t timeout) const
{
    while (timeout > 0) {
        if (spi_busy(E_HSPI)) {
            os_delay_us(1);
            timeout--;
        } else {
            timeout = 0;
        }
    }
}

spi_busy ist definiert:

//Expansion Macros
#define spi_busy(spi_no) READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR

das ist jetzt ein Ausschnitt aus meiner HSPI HAL. Allerdings nicht mit 
Arduino.

Grüße, Werner

von Olaf (Gast)


Lesenswert?

> die Probleme hatte ich auch. Die Transfer Methode wird verlassen auch
> wenn der Transfer noch nicht abgeschlossen ist.

Das ist aber dann ein schwerer Bug. Wo befindet sich denn der 
Rueckgabewert wenn die Methode bereits verlassen ist?

Ich hab schon ueberlegt ob ich zeitweise in einem Universum bin wo 
Ursache und Wirkung vertauscht sind. :)

Olaf

von Werner P. (Gast)


Lesenswert?

das kann ich Dir jetzt so direkt nicht beantworten. Wir hatten immer das 
Problem dass wenn wir nach dem Transfer CS auf High gesetzt haben der 
Slave Probleme machte.

Wir stellten dann fest, dass wenn wir nach dem Transfer CS auf High 
setzen , die Übertragung aber noch nicht abgeschlossen war. Nach langem 
Suchen im Internet fanden wir dann die Lösung.

Ist aber jetzt schon 2 Jahre her.

von Olaf (Gast)



Lesenswert?

Ich hab gerade noch etwas experementiert.

Das Problem haengt nicht an einer Wartezeit bevor man CS wieder setzt, 
es ist von der SCLK-Frequenz abhaengig.

Bei 100khz liesst der ESP8266 das letzte bit immer als 0 ein, bei 110khz 
flackert es lustig rum, bei 130khz ist es meistens, aber nicht immer 
korrekt und ab 140khz liesst er immer korrekt ein.

Das finde ich sehr bemerkenswert weil die Uebertragung ja von der 
Hardware erfolgt und man sieht auf den Oszibildern deutlich das CS erst 
lange nach der Uebertragung hoch geht und der AD1217 das Bit noch sehr 
lange stehen laesst. Im Extremfalle, bei einem Takt von 1Mhz laesst er 
das Bit sogar noch kurz stehen waehrend CS schon wieder high ist. Das 
ist IMHO von Analog auch nicht ganz sauber implementiert.
Auf jedenfall hat das Bit bei der fallenden Flanke, ich nutze SPIMODE=0 
(POL =GND) immer den korrekten Pegel. Deshalb dekodiert es der Oszi auch 
richtig.
Auch wenn ich auf SPIMODE=3 und POL=high umstelle aendert sich am 
Fehlverhalten nichts.

Andererseits sind die anderen Bits im Register immer korrekt. Sowohl 
Pegel wie auch Position. Ich gehe jetzt davon aus das die SPI-Hardware 
im ESP8266 einen Bug hat.

Der Code der Transfer funktion sieht im uebrigen so aus:

uint8_t SPIClass::transfer(uint8_t data) {
    while(SPI1CMD & SPIBUSY) {}
    // reset to 8Bit mode
    setDataBits(8);
    SPI1W0 = data;
    SPI1CMD |= SPIBUSY;
    while(SPI1CMD & SPIBUSY) {}
    return (uint8_t) (SPI1W0 & 0xff);
}

Da wird also auch explizit gewartet bevor das Register gelesen wird.
Allerdings ist es etwas befremdlich das man das Busybit von Hand setzen 
muss. Jetzt waer eigentlich der Moment wo man ein gutes Datenblatt 
braeuchte und den Assemblercode von Hand durchgehen muesste um 
auszuschliessen das der Compiler da etwas erzeugt das man so nicht 
erwartet. Seufz.

Olaf

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.