Forum: Mikrocontroller und Digitale Elektronik ESP-32 SPI sendet falsche bits


von Alexander L. (alexander_l228)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche zurzeit die GPIO-Pins eines ESP32-Slaves mit einem 
ESP32-Master über SPI fernzusteuern. Konkret soll der Master die 
digitalRead- und digitalWrite-Methode fernsteuern. Für die 
SPI-Kommunikation nutze ich diese Library hier: 
https://github.com/hideakitai/ESP32DMASPI/

Nun zu meinem Problem. Es passiert recht häufig, dass Bits, die über den 
Bus geschickt werden, nicht korrekt übertragen werden. Das Interessante 
ist, dass bei einer Übertragungsfrequenz von 1 MHz nur selten ein Fehler 
passiert. Ist die Übertragungsrate kleiner oder größer, schleichen sich 
Fehler oft in fast jede Nachricht ein. Ich habe leider überhaupt keine 
Idee mehr, woran das liegen könnte.

Warum die Übertragungsqualität so sehr davon abhängt, dass ich mit 1 MHz 
übertrage, verstehe ich nicht. 100 kHz oder 2 MHz funktionieren kaum. 
Kann man das irgendwie beheben?

*Hier ist mein Protokoll:*
Ich kodiere jeden Befehl und die Nachricht dazu in einem Byte.
Das Befehls-Byte vom Master zum Slave sieht so aus:
- Bit 1: Der Identifier des Befehls. 0 bedeutet schreiben, 1 bedeutet 
lesen.
- Bit 2: Falls der Befehl ein Schreibbefehl ist, ist das hier der Wert, 
der geschrieben werden soll.
- Bit 3 - 8: Die Pin-Nummer.

Der Slave sendet dann mit der nächsten Nachricht die Antwort.
Diese sieht dann so aus:
- Bit 1: Die Gültigkeit der Antwort.
- Bit 2: Der gelesene Wert.
- Bit 3 - 8: Die Pin-Nummer.

Wenn der Befehl 'Lesen' ist, wird der Befehl vom Master so lange 
wiederholt, bis der Slave eine gültige Antwort gesendet hat.

Momentan übertrage ich trotzdem immer 4 Bytes. Das liegt daran, dass die 
Library das so vorschreibt. Das werde ich aber später noch ändern. Im 
Moment möchte ich erstmal die Daten zuverlässig übertragen bekommen.

Vielen Dank für eure Hilfe. Mein Aufbau/Schaltplan ist im Anhang.

*Master-Code:*
1
#include <ESP32DMASPIMaster.h>
2
3
ESP32DMASPI::Master master;
4
5
static const uint32_t BUFFER_SIZE = 4;
6
7
/*
8
Tx byte:
9
 bit 1: 1 == cmd
10
 bit 2: 1 == pin is high
11
 bit 3 - 8: pin_nr
12
*/
13
uint8_t* spi_master_tx_buf;
14
/*
15
Rx byte:
16
 bit 1: 1 == valid message
17
 bit 2: 1 == pin is high
18
 bit 3 - 8: pin_nr
19
*/
20
uint8_t* spi_master_rx_buf;
21
22
void setup() {
23
  Serial.begin(115200);
24
  Serial.println("Master program!");
25
  delay(2000);
26
27
  spi_master_tx_buf = master.allocDMABuffer(BUFFER_SIZE);
28
  spi_master_rx_buf = master.allocDMABuffer(BUFFER_SIZE);
29
  memset(spi_master_tx_buf, 0, BUFFER_SIZE);
30
  memset(spi_master_rx_buf, 0, BUFFER_SIZE);
31
32
  master.setDataMode(SPI_MODE0);
33
  master.setFrequency(1000000);
34
  master.setMaxTransferSize(BUFFER_SIZE);
35
  master.setDutyCyclePos(96);
36
37
  master.begin(HSPI); 
38
}
39
40
void loop() {
41
  Serial.println("Start write HIGH!");
42
  write_spi_pin(4, true);
43
44
  Serial.println("Start read (should) HIGH!");
45
  Serial.print("Response ");
46
  Serial.println(read_spi_pin(4));
47
  delay(1000);
48
49
  Serial.println("Start write LOW!");
50
  write_spi_pin(4, false);
51
52
  Serial.println("Start read (should) LOW!");
53
  Serial.print("Response ");
54
  Serial.println(read_spi_pin(4));
55
  delay(1000);
56
}
57
58
bool read_spi_pin(uint8_t pin_nr) {
59
  spi_master_tx_buf[0] = pin_nr & 0b00111111;
60
  spi_master_tx_buf[0] = spi_master_tx_buf[0] | 0b10000000;
61
  master.transfer(spi_master_tx_buf, spi_master_rx_buf, BUFFER_SIZE);
62
63
  bool response_valid = false;
64
  bool response_high = false;
65
  uint8_t response_pin = 0;
66
  while (!response_valid || response_pin != pin_nr) {
67
    master.transfer(spi_master_tx_buf, spi_master_rx_buf, BUFFER_SIZE);
68
    uint8_t response = spi_master_rx_buf[0];
69
70
    Serial.print("Full intermediate response: ");
71
    for (int i = 7; i >= 0; i--)
72
    {
73
        bool b = bitRead(response, i);
74
        Serial.print(b);
75
    }
76
    Serial.println();
77
78
    response_valid = (response & 0b10000000) >> 7;
79
    response_high = (response & 0b01000000) >> 6;
80
    response_pin = response & 0b00111111;
81
82
    Serial.print("Read intermediate response: ");
83
    Serial.print("pin_nr ");
84
    Serial.print(pin_nr);
85
    Serial.print(", response_valid ");
86
    Serial.print(response_valid);
87
    Serial.print(", response_pin ");
88
    Serial.print(response_pin);
89
    Serial.print(", response_high ");
90
    Serial.println(response_high);
91
92
  }
93
  return response_high;
94
}
95
96
void write_spi_pin(uint8_t pin_nr, bool write_high) {
97
  spi_master_tx_buf[0] = pin_nr & 0b00011111;
98
  if (write_high) {
99
    spi_master_tx_buf[0] = spi_master_tx_buf[0] | 0b01000000;
100
  }
101
  master.transfer(spi_master_tx_buf, spi_master_rx_buf, BUFFER_SIZE);
102
}

*Slave-Code:*
1
#include <ESP32DMASPISlave.h>
2
3
ESP32DMASPI::Slave slave;
4
5
static const uint32_t BUFFER_SIZE = 4;
6
/*
7
Tx byte:
8
 bit 1: 1 == valid message
9
 bit 2: 1 == pin is high
10
 bit 3 - 8: pin_nr
11
*/
12
uint8_t* spi_slave_tx_buf;
13
/*
14
Rx byte:
15
 bit 1: cmd
16
 bit 2: 1 == pin is high
17
 bit 3 - 8: pin_nr
18
*/
19
uint8_t* spi_slave_rx_buf;
20
21
22
#define LED 2
23
24
void setup() {
25
  Serial.begin(115200);
26
  Serial.println("Slave program!");
27
  delay(2000);
28
29
  spi_slave_tx_buf = slave.allocDMABuffer(BUFFER_SIZE);
30
  spi_slave_rx_buf = slave.allocDMABuffer(BUFFER_SIZE);
31
32
  slave.setDataMode(SPI_MODE0);
33
  slave.setMaxTransferSize(BUFFER_SIZE);
34
35
  slave.begin(HSPI);
36
  // clear buffers
37
  memset(spi_slave_tx_buf, 0, BUFFER_SIZE);
38
  memset(spi_slave_rx_buf, 0, BUFFER_SIZE);
39
  pinMode(4, OUTPUT);
40
}
41
42
void loop() {
43
  Serial.print("Response:");
44
  for (int i = 7; i >= 0; i--) {
45
    bool b = bitRead(spi_slave_tx_buf[0], i);
46
    Serial.print(b);
47
  }
48
  Serial.println();
49
50
  slave.wait(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);
51
52
  uint8_t cmd;
53
  uint8_t data;
54
  uint8_t pin_nr;
55
  while (slave.available()) {
56
    // show received data
57
    Serial.print("Command Received: ");
58
59
    cmd = (spi_slave_rx_buf[0] & 0b10000000) >> 7;
60
    data = (spi_slave_rx_buf[0] & 0b01000000) >> 6;
61
    pin_nr = (spi_slave_rx_buf[0] & 0b00111111);
62
63
    Serial.print("cmd ");
64
    Serial.print(cmd);
65
    Serial.print(", data ");
66
    Serial.print(data);
67
    Serial.print(", pin_nr ");
68
    Serial.println(pin_nr);
69
    slave.pop();
70
71
    if (cmd == 0) {
72
      spi_slave_tx_buf[0] = 0;
73
      if (data == 0) {
74
        digitalWrite(pin_nr, LOW);
75
      } else {
76
        digitalWrite(pin_nr, HIGH);
77
      }
78
    } else {
79
      if (digitalRead(pin_nr) == HIGH) {
80
        Serial.println("Sending HIGH!");
81
        spi_slave_tx_buf[0] = 0b11000000 | pin_nr;
82
      } else {
83
        Serial.println("Sending LOW!");
84
        spi_slave_tx_buf[0] = 0b10000000 | pin_nr;
85
      }
86
    }
87
  }
88
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Ich habe leider überhaupt keine Idee mehr, woran das liegen könnte.
Allererster Schritt bei der Inbetriebnahme serieller Schnittstellen:
man nimmt das Oszilloskop und kontrolliert Spannungsverlauf und Timing.

Hast du das gemacht? Ist da alles im grünen Bereich? Siehst du auf dem 
Oszi den richtigen SPI-Mode? Passt der zu dem, was der Empfänger 
erwartet?

> Kann man das irgendwie beheben?
Dazu muss man erst mal wissen, was man beheben muss. Wenn man 
Überschwinger oder Unstetigkeiten in den Flanken sieht, dann muss man 
die Terminierung anpassen. Wenn die Pegel nicht passen, dann gibts evtl. 
irgendwo eine Buskollision.

: Bearbeitet durch Moderator
von Alexander L. (alexander_l228)


Lesenswert?

Das kann ich leider nicht tun. Ich bin eigentlich eher weniger im 
Hardware-Bereich tätig und habe kein Oszilloskop. Eventuell kann ich mal 
an der Uni schauen, ob ich dort irgendwo eines finde, womit ich kurz 
testen kann.

Gibt es vielleicht häufige Fehler, die bei so etwas auftreten, die man 
mal probieren könnte?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Eventuell kann ich mal an der Uni schauen, ob ich dort irgendwo eines finde
Tu das. Wenn da alles unfraglich passt, **dann** suche auf der SW-Seite 
weiter.

> Gibt es vielleicht häufige Fehler
Fehlerhafte Terminierung und falscher SPI-Mode sind die häufigsten 
Fehler. Aber das ist blindes Stochern im Trüben, solange die 
Datenintegrität auf der Hardwareseite nicht sichergestellt ist.

Alexander L. schrieb:
> nur selten ein Fehler passiert.
Meine SPI-Schnitten müssen im Labor und im Klimaschrank über mehrere 
Tage absolut ohne jeglichen Übertragungsfehler laufen. Dann bin ich 
zufrieden und traue mich damit raus ins Feld.

: Bearbeitet durch Moderator
von Peter (pittyj)


Lesenswert?

Auch meine Erfahrungen: ohne Scope geht da nichts.
Alles andere ist Stochern im Nebel.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Gibt es vielleicht häufige Fehler
Wenn deine Schaltung so aussieht, wie du sie oben gezeichnet hast, dann 
wundert mich, dass die überhaupt was tut.

Denn da fehlt ja jegliche Masseverbindung zwischen den µc und auch die 
Versorgung der µC.

Oder der Schaltplan ist falsch. Und mit falschen Schaltplänen Fehler 
suchen ist ein spannendes Unterfangen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Denn da fehlt ja jegliche Masseverbindung zwischen den µc und auch die
> Versorgung der µC.

Mich würde auch mal die Länge/Art der Verbindungen interessieren.

von Alexander L. (alexander_l228)


Lesenswert?

Der Schaltplan ist genau das was ich auch in echt gebaut habe. Den habe 
ich selbst gezeichnet. Eine Masseverbindung bzgl. der SPI Kommunikation 
existiert wirklich nicht. Ich bin eigentlich Informatiker und meine 
Hardware-Kenntnisse kommen aus genau einem Vertiefungsmodul, wo wir das 
am Rande mal angesprochen haben. Deshalb bin ich bei so etwas vermutlich 
etwas unbeholfen.

Das Grafik aus der ich diesen Aufbau abgeleitet habe ich diese hier: 
https://puu.sh/JNejs/a0800d4add.png (Steht so bei uns im Skript.)

Da sehe ich jetzt keine Masserverbindung. Wo genau müsste die dann sein?
Ich finde auch online keine Pläne, wo eine Masseverbindung dabei ist.
Ich nehme auch mal an, dass da dann noch ein Widerstand zur 
Masseverbindung gehört, damit das nicht zum Kurzschluss wird.

Die Länge der Verbindung ist nicht weit. Das dürften etwa 15cm sein.

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Alexander L. schrieb:
> Eine Masseverbindung bzgl. der SPI Kommunikation
> existiert wirklich nicht.

Und keiner der beiden ESP32 ist mit irgendeiner Art Netzteil verbunden?

Wie soll das dann funktionieren?

: Bearbeitet durch User
von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Der Schaltplan ist genau das was ich auch in echt gebaut habe. Den habe
> ich selbst gezeichnet. Eine Masseverbindung bzgl. der SPI Kommunikation
> existiert wirklich nicht. Ich bin eigentlich Informatiker

Aha, mal wieder die typische Einstellung vieler Informatiker, die sich 
einbilden, dass für sie die physikalischen Gesetze nicht gelten.

> Das Grafik aus der ich diesen Aufbau abgeleitet habe ich diese hier:
> https://puu.sh/JNejs/a0800d4add.png (Steht so bei uns im Skript.)

Das ist nur eine Vereinfachung, die die reinen Nutzsignale darstellt.

> Da sehe ich jetzt keine Masserverbindung. Wo genau müsste die dann sein?

Dann musst Du Dich wohl mal mit den elektrotechnischen Grundlagen 
befassen. Hierfür gibt es unzählige Lehrbücher.

> Ich finde auch online keine Pläne, wo eine Masseverbindung dabei ist.

Dann benötigt man wohl auch keine, und tausende professioneller 
Elektronikentwickler haben einfach keine Ahnung.

> Ich nehme auch mal an, dass da dann noch ein Widerstand zur
> Masseverbindung gehört, damit das nicht zum Kurzschluss wird.

Aha. Gewagte Behauptung für jemanden, der schon mit seiner tatsächlichen 
Unwesenheit so kokettiert. Offenbar scheinen die Autoren unzählige 
Fachpublikationen über das Thema Masseführung, Signalintegrität und 
Elektromagnetische Verträglichkeit keine Ahnung zu haben. Deren 
Berechnungen, Simulationen und Messungen scheinen auch alle fehlerhaft 
zu sein.

> Die Länge der Verbindung ist nicht weit. Das dürften etwa 15cm sein.

Aha. Gewagte Behauptung für jemanden, der jegliche physikalischen bzw. 
elektrotechnischen Grundlagen konsequent ignoriert. Aber Du musst es ja 
wissen.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Alexander L. schrieb:
> Der Slave sendet dann mit der nächsten Nachricht die Antwort.

Das kann er schon rein zeitlich nicht. Der Master schickt immer den 
Takt. Nach dem ersten Byte kriegt der Slave einen Interrupt und kann das 
Byte auswerten. Dazu nutzt er die Zeitdauer des 2. Bytes, d.h. der 
Master kriegt im 1. und 2. Byte Müll zurück. Erst im 3. Byte kann der 
Slave was zurück senden.

Einen Oszi braucht man nicht fürs SPI. Nur etwas Lesen des Datenblattes 
und logisches Denken.
Terminiert wird beim SPI auch nichts.

Ich würde aber erstmal nur dumme Slaves ansprechen (74HC595, 74HC165) 
und zum Laufen bringen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Da sehe ich jetzt keine Masserverbindung. Wo genau müsste die dann sein?

Verbinde GND ("Ground" = "Masse") des linken ESP-32 mit GND des rechten 
ESP-32, falls das nicht sowieso über ein gemeinsam genutztes Netzteil 
bereits der Fall ist.

Immerhin hast Du GND des rechten ESP-32 (obere rechte Ecke) ja mit dem 
FE_Srly-Modul verbunden. So muss das auch sein.

Du brauchst Masseverbindungen, damit Pegel (Low, High) ein gemeinsames 
Grundniveau haben. Spannungspegel sind Potentialdifferenzen. Diese 
können nur existieren bzw. eine gemeinsame Grundlage haben, wenn beide 
dasselbe Bezugspotential haben. Das ist eben GND.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Terminiert wird beim SPI auch nichts.

Bei langen Verbindungen, insbesondere wenn dann auch noch externe 
Leitungen enthalten sind, wirken sich kleine Serienwiderstände (z.B. 33 
Ohm) sehr vorteilhaft auf die Signalintegrität aus. Gerade die 
SPI-Taktleitung ist diesbezüglich sehr empfindlich und kann ggf. schon 
leichtes "Klingeln" als weitere Impulse ansehen. Daher kann es je nach 
Aufbau sogar ratsam sein, am Takteingang zusätzlich einen Tiefpass 
vorzusehen, d.h. mit wenigen Picofarad und ebenfalls kleinem 
Serienwiderstand. Natürlich darf man dabei den Takt nicht so stark 
verzögern, dass die Empfangsrichtung aus dem Tritt gerät.

> Ich würde aber erstmal nur dumme Slaves ansprechen (74HC595, 74HC165)
> und zum Laufen bringen.

Genau. Und sinnvollerweise verbindet man diese Bausteine nicht nur mit 
den SPI-Leitungen, sondern auch den parallelen Ein- und Ausgängen, so 
dass man munter Bitmuster generieren und zurücklesen kann. Das 
ermöglicht dann auch quantitative Aussagen über die Signalintegrität. 
Vorzugsweise sind natürlich die Parallelverbindungen gespiegelt, um 
sicherzustellen, dass man nicht durch Softwarefehler versehentlich die 
zu schreibenden Daten statt der ausgelesenen Daten miteinander 
vergleicht.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Peter D. schrieb:
> Einen Oszi braucht man nicht fürs SPI. Nur etwas Lesen des Datenblattes
> und logisches Denken.
> Terminiert wird beim SPI auch nichts.
Aua!

Dir reicht Fantasie zum Debuggen einer SPI Verbindung
Du Glücklicher!

von Alexander L. (alexander_l228)


Angehängte Dateien:

Lesenswert?

Der ESP hat natürlich Strom. Der hängt bis das funktioniert per USB am 
PC, der auch die Programme flasht.

@schweigstill Genau so motiviert man Leute, die einer neuen Community 
beitreten. /s

@peda. Das wird soweit ich weiß von der Library gehandelt. Die 
allermeisten Befehle kommen auch durch und die allermeisten Antworten 
auch.

@ukw Ich habe das Schaltbild mal geupdated. So sieht es jetzt aus. 
(Anhang)
Der Fehlerverhalten ist allerdings geblieben.

von Thilo L. (bc107)


Lesenswert?

Dem linken ESP fehlt die Spannungsversorgung.

von Alexander (alecxs)


Lesenswert?

Hört doch mal auf zu mobben. Natürlich hat er eine Masseverbindung und 
auch VCC. Mir wurde gesagt die Dupont-Leitungen seien nicht so gut 
geeignet, und ich solle lieber Kieselsteine sammeln. Am besten wäre mal 
ein Foto wenn Du Dich traust, da kann der ein oder andere vielleicht was 
erkennen was stört.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Ich habe das Schaltbild mal geupdated. So sieht es jetzt aus.
Auch im upgedateten Schaltplan fehlt was ganz Elementares: die 
Verbindung zum und die Versorgung über USB.

> Der ESP hat natürlich Strom. Der hängt bis das funktioniert per USB am
> PC, der auch die Programme flasht.
Und auch der zweite ESP wird über USB versorgt? Und auch die 
Masseverbindung zwischen den beiden ESP läuft über diese beiden USB?

: Bearbeitet durch Moderator
von Alexander (alecxs)


Lesenswert?

Wenn es nicht gerade zwei unterschiedliche PCs sind? Frank hat es ja gut 
erklärt, denke es wird angekommen sein. Wenn's nicht so wäre würde es 
mit 1 MHz auch nicht funktionieren.

: Bearbeitet durch User
von Alexander L. (alexander_l228)



Lesenswert?

Das ist die aktuelle Verkabelung nochmal als Foto. Nicht wundern, dass 
das nicht mehr zu der Pinbelegung aus dem Code passt. Ich habe den HSPI 
mit dem VSPI-Bus getauscht.

Der ESP bei dem man den Chip sieht ist der Slave. Der andere ist der 
Master.

von Harald K. (kirnbichler)


Lesenswert?

Sind die Stiftleisten da einfach nur lose in die ESP32-Platinen 
reingesteckt, oder warum sind die im einen Fall auf der Oberseite, und 
im anderen Fall auf der Unterseite?

von Alexander L. (alexander_l228)


Lesenswert?

@kirnbichler Die sind richtig verlötet. Die sind nur deshalb einmal auf 
der Unterseite, weil ich erst dachte, dass ich den kompletten ESP auf 
mein Breadboard stecken kann. Dafür war der dann allerdings zu breit. 
Beim 2. ESP habe ich das dann gewusst und ihn andersrum verlötet, damit 
ich die Kabel anschließen kann und gleichzeitig einfacher an den 
Reset-Knopf komme.

von Alexander (alecxs)


Lesenswert?

Es gibt auch solderless Stiftleisten zum einklicken, die halten 
eigentlich ganz gut.

von Sebastian W. (wangnick)


Lesenswert?

Ich glaube deine Slave-Programmierung ist nicht sauber. Bin grad am 
Handy, aber kann es so wie du es machst nicht passieren dass der Master 
von Slave einen veralteten Buffer bekommt?

LG, Sebastian

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Das ist die aktuelle Verkabelung nochmal als Foto
Du verbindest da die internen 3V3 vom Einen mit den 3V3 vom Anderen? 
Spannend...

Hast du mal die Versorungsspanungen mal gemessen?

Was passiert, wenn du die beiden ESP programmierst, sinnvoll mit den 
nötigen 5V aus 1 Netzteil versorgst und dann die USB-Kabel aussteckst?

von Alexander (alecxs)


Lesenswert?

Lothar M. schrieb:
> Du verbindest da die internen 3V3 vom Einen mit den 3V3 vom Anderen?
> Spannend...

Das habt ihr doch so vorgeschlagen!?

Ich denke nicht dass es am Aufbau liegt. Wird wohl eher so ein Software 
Ding sein. Die Frequenz wird ja letztendlich in Takte herunter geteilt, 
und da gibt es naturgemäß nur Näherungswerte. Kenne mich absolut nicht 
aus, aber könnte doch an der Library liegen? Mal die Warnings auf github 
gelesen?

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander schrieb:
> Das habt ihr doch so vorgeschlagen!?
Nein, es wurde vorgeschlagen, beide aus der selben einzigen Versorgung 
zu versorgen. Denn zu diesem Zeitpunkt war ja nicht klar, das an beiden 
ein USB-Kabel steckt...

> Die Frequenz wird ja letztendlich in Takte herunter geteilt, und da gibt
> es naturgemäß nur Näherungswerte.
Bei SPI völlig uninteressant, weil da der Takt mitübertragen wird. Du 
musst dich über die Bussysteme und ihre Funktion schlau machen, wenn du 
sie einsetzen willst.

Alexander schrieb:
> Mal die Warnings auf github gelesen?
1
There is also a known issue that received data is bit shifted depending on the SPI mode
2
Please try SPI mode 0 for this issue
3
But SPI mode 1 or 3 is required based on the official doc
4
Please use this library and SPI modes for your own risk
Sagte ich ja: falscher SPI-Mode. Das betrifft dann alle empfangenen 
Datenbits eines der beiden Teilnehmer. Nicht nur einzelne Bits.

Allerdings ist diese Anmerkung ein Indiz dafür, dass der Programmierer 
da auch nicht so richtig wusste, was er tat...

: Bearbeitet durch Moderator
von Alexander L. (alexander_l228)


Lesenswert?

@wangnick Das sollte eigentlich passen. Das kann nur auftreten, wenn 
zwei Read-Requests hintereinander kommen. Dabei gibt es zwei 
verschiedene Fälle:

1. Der Read-Request ist für denselben Pin: In diesem Fall stammt der 
Buffer zwar von der letzten Request, aber da zwischendrin keine 
Write-Request stattgefunden hat, ist das Ergebnis trotzdem aktuell.

2. Der Read-Request ist für einen anderen Pin: Hier ist zwar das 
Valid-Bit gesetzt, aber da es auch die Pin-Nummer in der Antwort 
mitschickt, erkennt der Master, dass sich die Antwort auf einen anderen 
Pin bezieht, und verwirft das Ergebnis.

Wenn die vorherige Request eine Write-Request war, antwortet der Slave 
mit einem 0-Byte. Dabei ist dann auch das Valid-Bit 0.


Was die zusammengeschalteten VCC-Pins der ESPs angeht: Ich hatte die 
Antwort vorhin so interpretiert, dass ich das machen soll. Der einzige 
Effekt, den das hat, ist dass ich jetzt einen ESP vom USB trennen kann 
und er trotzdem weiterläuft. Funktional macht es allerdings keinen 
Unterschied.

Was die Warnung auf GitHub angeht: Ich hatte zuerst diese Library 
verwendet: https://github.com/hideakitai/ESP32SPISlave. Da ich mit 
dieser bereits Probleme hatte, dachte ich, ich probiere mal die andere 
aus (also die, die ich gerade nutze). Ich habe auch die known Issues 
gesehen und die entsprechenden Workarounds implementiert.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Alexander schrieb:
> Lothar M. schrieb:
>> Du verbindest da die internen 3V3 vom Einen mit den 3V3 vom Anderen?
>> Spannend...
>
> Das habt ihr doch so vorgeschlagen!?

Wenn das Modul über den 3V3-Pin versorgt wird, dann ja.

Du versorgst aber beide Module über USB (5V). Diese Info kam erst jetzt. 
In diesem Fall werden die 3V3-Pins zu Ausgängen durch den jeweiligen auf 
der Platine befindlichen Spannungswandler (5V -> 3V3). In diesem Falle 
solltest Du tunlichst die 3V3-Verbindung kappen, denn hier treiben dann 
2 Ausgänge gegeneinander. Schon bei geringen 
Spannungsdifferenzen/Toleranzen fließt dann ein nicht unerheblicher 
Strom, welche die 3V3-Wandler unnötig belastet.

Also: Nimm die 3V3-Verbindung zwischen den ESP32 raus - zumindest 
solange Du die über USB versorgst. Wenn später die USB-Versorgung 
wegfällt, versorge die Module über den 5V-Pin mit 5V, denn ich kenne 
nicht den Schaltplan des Moduls. Unter Umständen lässt sich der 3V3-Pin 
lediglich als Output nutzen und nicht, um das komplette Modul mit 3V3 zu 
versorgen.

Die 3V3-Verbindung zum FE_SRly-Modul ist okay. Dieses wird hier über den 
3V3-Output des rechten ESP32-Moduls mit Spannung versorgt.

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> Der einzige Effekt, den das hat, ist dass ich jetzt einen ESP vom USB
> trennen kann und er trotzdem weiterläuft. Funktional macht es allerdings
> keinen Unterschied.
Doch, ja, einen gewichtigen. Du musst dir einfach mal die interne 
Schaltung der Boards mit einzeichnen...

Du meinst vermutlich nur, dass sich die Funktion dadurch nicht 
verbessert/ändert. Das hat mit der Funktionalität aber nur am Rande zu 
tun.

Alexander L. schrieb:
> Das werde ich ausprobieren.
Hatte ich den Trick mit dem Oszi schon mal erwähnt? Damit kannst du 
nämlich sehen, was auf dem Bus los ist. Und schauen ob es zu dem 
passt, was dein Programm macht.

Derzeit ist es, wie wenn du mit verbundenen Augen nach Gehör mit dem 
Auto fährst. Das kann eine Zeit lang gut gehen. Du siehst und erkennst 
dann allerdings nicht, warum es wieder mal nicht gut gegangen ist.

von Alexander L. (alexander_l228)


Lesenswert?

Okay, ich habe die 3.3V Pins wieder getrennt.

Was allerdings ein Problem ist, ist dass diese ganze Geschichte nur eine 
Komponente von einem größerem Open-Source Projekt ist, welches ich 
entwickle.
Besagtes Projekt läuft auf einem RaspberryPi und es wäre ganz nett 
gewesen eine Möglichkeit zu haben die GPIO-Pins des Pis erweitern zu 
können.
Der Pi wäre dann der Master und der ESP würde als GPIO Erweiterung 
funktionieren. Die Master-Komponente müsste ich allerdings nochmal in 
Java neu schreiben. Der Aufbau hier war eigentlich nur für mich gedacht, 
damit ich mich mal etwas in das Thema SPI einfinden kann.
Ich baue die Komponente jetzt mal lieber nochmal direkt mit Java auf der 
Master Seite. Bevor ich hier die Arbeit doppelt mache.

Wichtig ist vor allem, dass man das ganze am Ende auch als dritter 
reproduzierbar nachbauen kann.

von Harald K. (kirnbichler)


Lesenswert?

Alexander L. schrieb:
> Besagtes Projekt läuft auf einem RaspberryPi und es wäre ganz nett
> gewesen eine Möglichkeit zu haben die GPIO-Pins des Pis erweitern zu
> können.

Der Raspberry Pi kann sicherlich auch I2C, und für I2C gibt es fertige 
ICs, die man als Portexpander verwenden kann. Die müssen dafür nicht 
eigens programmiert werden und sind deutlich unkomplizierter zu 
handhaben als ausgerechnet ein ESP32.

Hier ein willkürlich ausgesuchtes "Tutorial" dazu:

https://tutorials-raspberrypi.de/raspberry-pi-gpios-erweitern-mittels-i2c-port-expander/

von Alexander L. (alexander_l228)


Lesenswert?

@kirnbichler Das stimmt zwar, allerdings ist SPI wesentlich schneller 
als I2C. An diesen Erweiterungskarten hängen im Worst Case schnell 
laufende Schrittmotoren und der Pi unterstützt für I2C leider nur eine 
Bandbreite von 400kBit/s. Wobei man die Step-Pin auf auf den nativen 
Pi-Pins lassen könnte und nur Direction und Enable auf die Karte legt. 
Das würde vermutlich gehen. Aber es wäre schon irgendwie cooler, wenn 
auch die Step-Pin dort liegen könnte. Ist halt die Frage ob das den 
Aufwand wert ist.

von Stefan F. (Gast)


Lesenswert?

Alexander L. schrieb:
> SPI_remote_wiring_Steckplatine.png

Betreibst du das Relais wirklich mit den kaum belastbaren 3,3V des ESP 
Boardes?

von Alexander L. (alexander_l228)


Lesenswert?

@stefanus Das Relay kommt laut Datenblatt mit 3,3V klar und hat ne 
Flyback Diode. Hab ich da was übersehen? Noch steht alles.

von Stefan F. (Gast)


Lesenswert?

Alexander L. schrieb:
> Hab ich da was übersehen?

Dass das USB Kabel und ESP Modul wahrscheinlich nicht genug Strom für 
das Relais liefern. Die Stromaufnahme des ESP Moduls alleine ist schon 
für viele USB Kabel zu viel. Kurzzeitig brauchen die Module etwa 500 mA.

Mit einem Oszilloskop könntest du die Stabilität der Stromversorgung 
prüfen.

Deine GND Verbindungen über das Steckbrett und Dupont Kabel würde ich 
durch gelötete Kupferkabel ersetzen, welche erheblich besser leiten. Wie 
viel Spannung auf dieser GND Verbindung abfällt, könntest du auch wieder 
mit einem Oszilloskop prüfen. Ein Multimeter taugt dazu nicht, denn es 
geht um hohe Frequenzen die sich zum DC Anteil überlagern.

von Robert M. (r_mu)


Lesenswert?

Schrittmotor-Signale über einen per SPI angebundenen Port-Expander von 
einem Raspberry Pi auszugeben ist Unsinn, das wird nur umständlich (wenn 
überhaupt) irgendwie stabil und bleibt immer langsam. Vernünftiger 
funktioniert das so wie hier mit externem µC der sich um das Timing 
kümmert https://github.com/scottalford75/Remora oder gleich FPGA z.B. 
mesa 7i90, 7c80 oder 7c81.

von Alexander (alecxs)


Lesenswert?

Alexander L. schrieb:
> @stefanus Das Relay kommt laut Datenblatt mit 3,3V klar und hat ne
> Flyback Diode. Hab ich da was übersehen? Noch steht alles.

Ja, die Stromaufnahme beträgt 120 mA und es muss 03 drauf stehen. Dann 
sollte es klappe(r)n.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander L. schrieb:
> ESP als GPIO Erweiterung
Technischer Overkill.
Nimm doch handelsübliche LVTTL Schieberegister wie der Rest der Welt. 
Die kannst du auch per SPI ansteuern.

: Bearbeitet durch Moderator
von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Robert M. schrieb:
> Vernünftiger
> funktioniert das so wie hier mit externem µC der sich um das Timing
> kümmert https://github.com/scottalford75/Remora oder gleich FPGA z.B.
> mesa 7i90, 7c80 oder 7c81.

Oder mit einem speziell für solche Anwendungen entwickelten Schritt- und 
Rampengenerator, z.B. Trinamic TMC429, TMC4210 oder TMC4361:

https://www.trinamic.com/products/integrated-circuits/

: Bearbeitet durch User
von Robert M. (r_mu)


Lesenswert?

Andreas S. schrieb:
> Oder mit einem speziell für solche Anwendungen entwickelten Schritt- und
> Rampengenerator, z.B. Trinamic TMC429, TMC4210 oder TMC4361:
>
> https://www.trinamic.com/products/integrated-circuits/

oder gleich Arduino-kompatibel, Rampengenerator mit eingebauter 
Schrittmotor-Endstufe in Form eines Nucleo mit STM Powerstep01 (falls 
das wieder lieferbar ist). Damit kann man alles was mit Schrittmotoren 
von der Leistung her Sinn macht ansteuern.

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.