Forum: Mikrocontroller und Digitale Elektronik ESP32 - SPI funktioniert nicht


von Marius S. (fhler)


Lesenswert?

Hallo,

wie schon im Betreff erwähnt verwende ich einen ESP32 (DevKitC). Ich 
will per SPI Daten übertragen nur leider funktioniert es mit der 
SPI-Bibliothek nicht. Grund: unbekannt.

Noch nicht einmal das mitgelieferte SPI-Beispiel funktioniert. Das Board 
habe ich schon getauscht, das Netz durchwühlt aber keine der Lösungen 
funktioniert. Lediglich das BitBangedSPI im ArduinoISP-Beispiel 
funktioniert aber das ist "händisches SPI" und damit kann ich nur Daten 
rausschicken aber keine empfangen (was ich aber zwingend muss).

In der Arduino IDE hatte ich bisher das "DOIT ESP32 DEVKIT V1" 
ausgewählt kann es sein das ich ein anderes auswählen muss? Auf dem 
Board steht "ESP32-WROOM-32". Daher fällt für mich das "ESP32 DevModule" 
und das "ESP32 Wrover Module " weg / kommt eigentlich nicht in Frage.

Habt ihr evtl noch Lösungsvorschläge?

Gruß Marius

von John P. (brushlesspower)


Lesenswert?

Welches Board du auswählst ist "eigentlich" egal.

Für jedes Board ist eine "pins_arduino.h" hinterlegt. In der steht z.B. 
welche Pins für SPI genutzt werden.

fürs DOIT ESP32 DEVKIT V1 sind das:

static const uint8_t SS    = 5;
static const uint8_t MOSI  = 23;
static const uint8_t MISO  = 19;
static const uint8_t SCK   = 18;

welche Pins du tatsächlich verwendest, musst du wissen.

: Bearbeitet durch User
von Marius S. (fhler)


Lesenswert?

Hallo John,

Genau diese Pins verwende ich / will ich verwenden. Nur es tut sich 
absolut nichts.

von John P. (brushlesspower)


Lesenswert?

Dann solltest du mal deinen Code posten.
Eventuell auch sagen was du mit der SPI machen willst?
Eventuell auch wie du was verbunden hast?

Hast du ein Oszi zur verfügung?


Ohne diese Angaben ist es Rätsel raten.

von Michael U. (amiga)


Lesenswert?

Hallo,

mit welchem Sketch hast Du getestet? SPI am ESP32 macht eigenlich kein 
mir bekannten Probleme. Sonst würden auch meine SPI-Displays mit 
SPI-Touchcontroller und auch die SD-Karte nicht gehen.

Die Standard-Pins wurden oben schon genannt, Board ist völlig egal, 
"ESP32 Dev Module" kann man für alle nutzen solange man die GPIO-Nummern 
des ESP32 benutzt. Die boardspezifischen Einstellungen werden erst 
interessant, wenn man mit den bei einigen aufgedrucken Dx Bezeichungen 
arbeiten will oder fest verdrahtete Zusatzhardware (OLED usw.) direkt 
auf dem Board sind und man mit deren speziellen Beispielen arbeiten 
will.

Alles bezogen auf die IDE 1.8.8 und ESP32 Boardmanagerversion 1.0.1.

Was hast Du denn wie oder womit testen wollen?

Gruß aus Berlin
Michael

von Thomas F. (thomas_82)


Lesenswert?

Evtl. die Pinzuordnung, der Aufdruck auf den ESP, NodeMCU und Co Boards 
ist teilweise verwirrend wenn es mir seltsam vorkommt teste ich 
mittlerweile mit einer Led und einem blink Sketch ob es der richtige 
ist.

von Marius S. (fhler)


Lesenswert?

John P. schrieb:

> Dann solltest du mal deinen Code posten.

Selbst den Heartbeat macht er nicht mehr.
1
#include <SPI.h>
2
3
#include "Arduino.h"
4
#include "FS.h"
5
#include "SPIFFS.h"
6
7
#define PIN_SCK 18
8
#define PIN_MOSI  23
9
#define PIN_MISO  19
10
#define RESET 22
11
12
13
uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
14
  SPI.transfer(a);
15
  SPI.transfer(b);
16
  SPI.transfer(c);
17
  return SPI.transfer(d);
18
}
19
20
void setup() {
21
  Serial.begin(115200);
22
    if(SPIFFS.begin())
23
  {
24
    Serial.println("SPIFFS Initialisierung....OK");
25
  }
26
  else
27
  {
28
    Serial.println("SPIFFS Initialisierung...Fehler!");
29
  }
30
31
  SPI.begin();
32
  
33
  pinMode(PIN_SCK, OUTPUT);
34
  pinMode(PIN_MOSI, OUTPUT);
35
  pinMode(PIN_MISO, INPUT);
36
  pinMode(RESET, OUTPUT);
37
 
38
   //Just for testing
39
  digitalWrite(RESET, HIGH);
40
  delay(1000);
41
  digitalWrite(RESET, LOW);
42
43
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); //SPI-BUS einrichten: max 1 MHz, MSB zuerst, MODUS 0 
44
  SPI.transfer(0xFF);
45
  SPI.endTransaction();
46
47
     
48
}
49
50
void loop() {
51
  //"Heartbeat"
52
  delay(1000);
53
  digitalWrite(22, HIGH);
54
  delay(1000);
55
  digitalWrite(22, LOW);
56
  
57
58
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); //SPI-BUS einrichten: max 1 MHz, MSB zuerst, MODUS 0 
59
  SPI.transfer(0xFF);
60
  SPI.transfer(0b10010101010101010110111111110000011110000);
61
  SPI.endTransaction();
62
63
  String debugLogData;
64
  
65
  if (SPIFFS.exists("/250.hex"))
66
  {
67
     Serial.println("File gefunden");
68
      File f = SPIFFS.open("/250.hex", "r");    
69
      
70
          while (f.available()){
71
            debugLogData += char(f.read());
72
          }
73
          f.close();
74
  }
75
76
  Serial.println(debugLogData);
77
78
    int maxIndex = debugLogData.length() - 1;
79
    int index=0;
80
    int next_index;
81
    String data_word;
82
    int anzahl_zeilen = 0;
83
    
84
    do{
85
        anzahl_zeilen++;
86
        next_index=debugLogData.indexOf('\r\n',index);
87
        data_word=debugLogData.substring(index, next_index);
88
        Serial.print("Output line: ");
89
        Serial.println(data_word);
90
        index=next_index+1;
91
     }while((next_index!=-1)&&(next_index<maxIndex));
92
     Serial.println(anzahl_zeilen);
93
     
94
     String Array[anzahl_zeilen];
95
     index=0;
96
     int i = 0;
97
     
98
     do{
99
        next_index=debugLogData.indexOf('\r\n',index);
100
        Array[i]=debugLogData.substring(index, next_index);
101
        Serial.print("Output Array line: ");
102
        Serial.println(Array[i]);
103
        i++;
104
        index=next_index+1;
105
     }while((next_index!=-1)&&(next_index<maxIndex));
106
107
      Serial.println("anzahl datenbytes (HEX)");
108
      char a = Array[0].charAt(1);
109
      char b = Array[0].charAt(2);
110
      String str = (String) a + (String) b;
111
      switch(str){}
112
      {
113
        case 00
114
        }
115
116
        Serial.println(str)
117
118
}

> Eventuell auch sagen was du mit der SPI machen willst?
  Mit den gesendeten Daten einen AtTiny programmieren
  Beitrag "ESP32 als ISP"

> Eventuell auch wie du was verbunden hast?
PIN ESP32    <->   PIN AtTiny45

22 -> 5 RESET
18 -> 2 CLK
23 -> 0 MOSI
19 -> 1 MISO

> Hast du ein Oszi zur verfügung?
  JA.

von Mike R. (thesealion)


Lesenswert?

Ohne jetzt deinen kompletten Code zu lesen:
1
SPI.begin();
2
  
3
pinMode(PIN_SCK, OUTPUT);
4
pinMode(PIN_MOSI, OUTPUT);
5
pinMode(PIN_MISO, INPUT);
6
pinMode(RESET, OUTPUT);


Sieht meiner für die SPI Schnittstelle deutlich anders aus
1
SPI.begin(SPI_CLK, SPI_MISO, SPI_MOSI);

Wie soll die SPI Hardware denn etwas über die Pins ausgeben, wenn du sie 
gleich wieder als normale Outputs definierst?

von Marius S. (fhler)


Lesenswert?

Mike R. schrieb:

> Sieht meiner für die SPI Schnittstelle deutlich anders aus
>
1
> SPI.begin(SPI_CLK, SPI_MISO, SPI_MOSI);
2
>
>
> Wie soll die SPI Hardware denn etwas über die Pins ausgeben, wenn du sie
> gleich wieder als normale Outputs definierst?

Danke. Mit der Änderung macht er wieder den Herzschlag. Aber trotzdem 
keine Änderung der Signale auf der Clock-/MOSI-/MISO-Leitung.

von Michael U. (amiga)


Lesenswert?

Hallo,

SPI.begin(); setzt die Pins auf die oben schon erwähnten Pins und nutzt 
Hardware SPI. Die Pins muß man nur angeben, wenn man andere nutzt.

Die Pins da selber und dann auch falsch anzufassen ist nicht sinnvoll.

Interessant wäre wohl dann auch, was da auf dem Tiny45 läuft. Ich kenne 
es eigentlich so (aber nicht auf einem Tiny), daß mit SS/CS dem Slave 
mitgeteilt wird, daß der Master was von ihm will.

Gruß aus Berlin
Michael

von holger (Gast)


Lesenswert?

>Interessant wäre wohl dann auch, was da auf dem Tiny45 läuft.

Das will er doch erst reinflashen.

>  SPI.transfer(0b10010101010101010110111111110000011110000);

Das sind 41Bits wenn ich mich nicht verzählt habe.
Sicher dass es eine SPI.transfer() gibt die dann vermutlich
64Bits überträgt?

von Michael U. (amiga)


Lesenswert?

Hallo,

holger schrieb:
> Das sind 41Bits wenn ich mich nicht verzählt habe.
> Sicher dass es eine SPI.transfer() gibt die dann vermutlich
> 64Bits überträgt?

Nein, gibt es nicht. Aus SPI.h vom ESP32:
1
    void beginTransaction(SPISettings settings);
2
    void endTransaction(void);
3
4
    void transfer(uint8_t * data, uint32_t size);
5
    uint8_t transfer(uint8_t data);
6
    uint16_t transfer16(uint16_t data);
7
    uint32_t transfer32(uint32_t data);
8
  
9
    void transferBytes(uint8_t * data, uint8_t * out, uint32_t size);
10
    void transferBits(uint32_t data, uint32_t * out, uint8_t bits);

Gruß aus berlin
Michael

von fhler (Gast)


Lesenswert?

holger schrieb:
>  SPI.transfer(0b10010101010101010110111111110000011110000);
>
> Das sind 41Bits wenn ich mich nicht verzählt habe.
> Sicher dass es eine SPI.transfer() gibt die dann vermutlich
> 64Bits überträgt?

Ich muss sagen da habe ich mir keine Gedanken drüber gemacht und einfach 
nur auf der Tastatur rumgetippt ohne zu zählen.

von Mike R. (thesealion)


Lesenswert?

Dann mach dir jetzt mal Gedanken und erstelle einen Sketch der alle 
1000ms 8bit per SPI versendet.

Wenn du den fertig hast kannst du ihn hier Posten bzw. Gleichzeitig mit 
deinem Oszilloskop messen ob er denn funktioniert.

Oder dann sehen wir wie man dir helfen kann.

von Marius S. (fhler)


Angehängte Dateien:

Lesenswert?

Mike R. schrieb:
> Dann mach dir jetzt mal Gedanken und erstelle einen Sketch der alle
> 1000ms 8bit per SPI versendet.
1
#include <SPI.h>
2
#include "Arduino.h"
3
4
#define PIN_SCK 18
5
#define PIN_MOSI  23
6
#define PIN_MISO  19
7
#define RESET 22
8
9
void setup() {
10
  // put your setup code here, to run once:
11
  
12
  pinMode(PIN_SCK, OUTPUT);
13
  pinMode(PIN_MOSI, OUTPUT);
14
  pinMode(PIN_MISO, INPUT);
15
  pinMode(RESET, OUTPUT);
16
  
17
  SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI);
18
  //SPI.begin();
19
}
20
21
void loop() {
22
  // put your main code here, to run repeatedly:
23
  
24
  digitalWrite(22, HIGH);  
25
  delay(1000);
26
  digitalWrite(22, LOW);
27
  digitalWrite(5, LOW);
28
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); //SPI-BUS einrichten: max 1 MHz, MSB zuerst, MODUS 0 
29
  SPI.transfer(0x0F);
30
  SPI.endTransaction();
31
  digitalWrite(5, HIGH);
32
  delay(1000);
33
34
}

> Wenn du den fertig hast kannst du ihn hier Posten bzw. Gleichzeitig mit
> deinem Oszilloskop messen ob er denn funktioniert.

s. Anhang

GELB: !RESET (PIN 22)
BLAU: SCK
ROSA: MOSI
GRÜN: MISO TEK07
GRÜN: CS/SS (PIN 5) TEK12

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

ich kenne zwar den TEK nicht, aber was erwartest Du bei einer Auflösung 
von 1s pro raster von den 1000000 mal schnelleren SPI-Signalen noch zu 
sehen?
Deine SpI-Signale sind in rund 1/100000 s nach der steigendewn Flanke 
von RESET fertig. Auch der SS/CS Impuls ist da dann durch und macht fast 
2 Sekunden Pause bis zum nächsten...

Nachdenken, was Du da siehst, was Du zu sehen erwartest und welche 
Einstellungen sinnvoll sind.

Trigger auf die fallende Flanke von SS/CS und stell die Auflösung auf 
2µs pro Raster oder so.
Wenn der TEK genau Speicher hat kannst Du natürlich auch größere Werte 
nehmen und dann reinzoomen.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von John P. (brushlesspower)


Lesenswert?

Marius S. schrieb:
> #include "Arduino.h"

hat vielleicht nichts mit dem SPI Problem zu tun. (da stimme ich erstmal 
dem Micheal zu)

Aber warum includest du eine arduino.h aus dem sketch verzeichnis?
die ist doch bereits in den ESP32 Hardware sourcen enthalten.

von Michael U. (amiga)


Angehängte Dateien:

Lesenswert?

Hallo,

so, ich wollte es sowieo mal machen, also war jetzt eine Gelegenheit 
dazu. ;)
Ich habe den uralten VB6-Kram installiert und meinen 
Eigenbau-Logicanalyzer ausgekramt...

Im Bild das, was Deine Software macht. Genau, das, was sie soll...

Weiß ich jetzt wenigstens, das mein 10 Jahre alter Kram immernoch geht 
und die Software auch unter Win7-64.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Marius S. (fhler)


Lesenswert?

Vielen Dank für eure Hilfe, der SPI-Bus funktioniert jetzt.

von Michael U. (amiga)


Lesenswert?

Hallo,

Danke für die Rückmeldung.
Ich bin auch froh, daß ich meinen alten LA wieder in Gang gebracht habe.
http://www.avr.roehres-home.de/logikanalyzer/index.html

Gruß aus Berlin
Michael

von Sinan (Gast)


Lesenswert?

Hallo Marius,

kannst du deinen fertigen Sketch posten?

Ich bin momentan auch damit beschäftigt eine Kommunikation mit dem SPI 
aufzubauen.

Gruß

Sinan

von Sinan (Gast)


Lesenswert?

Marius S. schrieb:
> Vielen Dank für eure Hilfe, der SPI-Bus funktioniert jetzt.

Hallo Marius,

kannst du deinen fertigen Sketch posten?
Ich bin momentan auch damit beschäftigt eine Kommunikation mit dem SPI 
aufzubauen.
Gruß
Sinan

von Hansjörg (Gast)


Angehängte Dateien:

Lesenswert?

Das läuft:

#include<SPI.h>       //Library for SPI

#define SPI_SCK 18 //Serial Clock(Master Output)
#define SPI_MOSI 23 //Master Output,Slave Input
#define SPI_MISO 19 //
#define SPI_CS 5 //Chip Select,Slave Transmit Enable(active low,Master 
Output)
#define SS 5

char retchr;

void setup (void) {
   Serial.begin(115200); //set baud rate to 115200 for usart
   pinMode(SPI_CS, OUTPUT);
   pinMode(LED, OUTPUT);
   pinMode(SPI_SCK, OUTPUT);
   pinMode(SPI_MOSI, OUTPUT);
   pinMode(SPI_MISO, INPUT);

   digitalWrite(SS, HIGH); // disable Slave Select
   SPI.begin (SPI_SCK,SPI_MISO,SPI_MOSI);
   SPI.setBitOrder(MSBFIRST);
   SPI.setDataMode(SPI_MODE0);
   SPI.setClockDivider(SPI_CLOCK_DIV8); //divide the clock by 8=2 MHz 
@ESP32
}

void loop (void) {
   char c;
   digitalWrite(SS, LOW); // enable Slave Select
   // send test string
   for (const char *p = "Hello, world! We are online over SPI\n\r" ; c = 
*p; p++)
   {
      retchr=SPI.transfer (c);
      Serial.print(c);
      Serial.print(retchr); // MOSI MISO Link gebt echo retour
   }
   digitalWrite(SS, HIGH); // disable Slave Select
   delay(500);
}

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.