SPI Probleme (?)

Hallo Leute,
beschäftige mich seit einiger Zeit mit den RFM69 Modulen und arbeite dabei mit der Bibliothek von RadioHead.
Möchte nun die empfangenen Daten auf mein TFT Display (Driver ILI9341) ausgeben.
Bereits bei meinem „Testsketch“ habe ich Probleme das RFM69 Modul und das TFT Display, welche ich beide mit SPI Bus an meinem ESP32 angeschlossen habe, gleichzeitig laufen zu bringen.

#include <Arduino.h>

/* ESP32                        RFM69W
GND--------------------------GND   (ground in)
VIN--------------------------3.3V  (3.3V in)
interrupt D0 pin GPIO17-------DIO0  (interrupt request out)
SS pin GPIO5----------------NSS   (chip select in)
SCK SPI pin GPIO18-----------SCK   (SPI clock in)
MOSI SPI pin GPIO23----------MOSI  (SPI Data in)
MISO SPI pin GPIO19----------MISO  (SPI Data out) */


//TFT Display
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
//RFM69
#include <RHReliableDatagram.h>
#include <RH_RF69.h>

#define CLIENT_ADDRESS 2
#define SERVER_ADDRESS 1

// For the Adafruit shield, these are the default.
#define TFT_DC 4
#define TFT_CS 16
#define TFT_RST 2
#define TFT_MISO 19         
#define TFT_MOSI 23           
#define TFT_CLK 18 

// Slave Select is GPIO pin 5, interrupt is GPIO pin 17
RH_RF69 driver(5, 17); 

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
// Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram manager(driver, SERVER_ADDRESS);

struct messwerte
{
  float feuchtigkeit;
  float temperatur;
} dht22_sensordaten;



unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}


void rfm_initialisierung()  {
  if (!manager.init())
    Serial.println("init failed");
    // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!driver.setFrequency(868.0))
    Serial.println("setFrequency failed");
  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  driver.setTxPower(14, true);
}


void tft_diagnostic() {
   // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 
  Serial.println(F("Benchmark                Time (microseconds)"));
  delay(10);
  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(3000);
  Serial.println(F("Done!"));
}


uint8_t data[] = "And hello back to you";
// Dont put this on the stack:
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];


void rfm_datenempfang()  {
   if (manager.available())
  {
    // Wait for a message addressed to us from the client
    uint8_t len = sizeof(buf);
    uint8_t from;
    if (manager.recvfromAck(buf, &len, &from))
    {
      /* Serial.print("got request from : 0x");
      Serial.print(from, HEX);
      Serial.print(": ");
      Serial.println((char*)buf);
      driver.printBuffer("Got:", buf, len); */
      memcpy(&dht22_sensordaten, buf, sizeof(dht22_sensordaten));
      Serial.print(dht22_sensordaten.temperatur);
      Serial.println("°C");
      Serial.print(dht22_sensordaten.feuchtigkeit);
      Serial.println("%");

      Serial.print("RSSI: ");
      Serial.println(driver.lastRssi(), DEC);

      // Send a reply back to the originator client
      /* if (!manager.sendtoWait(data, sizeof(data), from))
        Serial.println("sendtoWait failed"); */
    }
  }
}



void setup() {
  Serial.begin(9600);
    while (!Serial) 
    ;
  
  rfm_initialisierung();

  tft.begin();
  Serial.println("ILI9341 Test!"); 
  tft_diagnostic();
}



void loop(void) {
  rfm_datenempfang();
 
}

Konkret wird auf dem Display leider nichts angezeigt. Die Daten vom RFM69 Modul werden aber empfangen und an die serielle Schnittstelle ausgegeben.
Wenn ich in der setup () Funktion die Funktion rfm_initialisierung() kommentiere funktioniert die Ausgabe des Testextes in der Funktion tft_diagnostic().
Hat jemand von euch eine Ahnung was der Grund meines Problems sein könnte bzw. wo es Interferenzen gibt? Kann eine SPI transaction das Problem sein? Wie könnte ich das Problem beheben?
Vielen Dank bereits im Voraus für eure konstruktive Antworten.

Dann schreibe doch mal, wie du den RFM69 an SPI angeschlossen hast.
Das kann ich in deinem Sketch nicht finden.

Leider ist dein Sketch sehr unübersichtlich, was du durch eine bessere Struktur und Verwendung von Funktionen beheben könntest.

Hallo HotSystems,
Vielen Dank für deiner Hilfsbereitschaft.
Habe meinen Eingangspost nach deinen Wünschen abegändert.
Ich hoffe die Problemstellung und der elektronische Aufbau sind jetzt klarer.

Wenn beide Module für sich alleine funktionieren, aber nicht beide zusammen,
und wenn keine Pins versehentlich doppelt zugeordnet wurden,
und beide SS nicht gleichzeitig aktiv sind,
und die Stromversorgung ausreicht,
(sonst noch was?)
dann bleibt IMO nur noch eine Inkompatibilität der benutzten Bibliotheken.

BTW es ist ganz schlechter Stil und fehlerträchtig, für die Standard-Buspins (SCK, MISO, MOSI) eigene Definitionen zu erstellen.

Bei SPI gabs doch mal das Problem bei manchen Modulen, dass die die Datenleitungen nicht auf Tristate hochohmig stellen. Du müsstest dir die Kommunikation mit dem Oszi anschauen.

ElEspanol:
Bei SPI gabs doch mal das Problem bei manchen Modulen, dass die die Datenleitungen nicht auf Tristate hochohmig stellen. Du müsstest dir die Kommunikation mit dem Oszi anschauen.

Den Verdacht hatte ich auch erst, aber dann würde das Auskommentieren der Initialisierung nicht helfen. Deshalb vermute ich eher, daß ein SS stehen bleibt und damit den Ausgang aktiv hält.

Das könnte man ja testen, indem man den einen SS manuell steuert. Aber das sind typische Sachen, wo man halt mit dem Oszi, sofern vorhanden, leichter eingrenzt.

Danke für eure Hilfsbereitschaft.
Habe leider kein Oszi zur Verfügung… :fearful:
Habe jetzt meinen Sketch umgeschrieben und verwende die Hardware SPI, sicher die bessere Variante.
Jetzt wird auf meinem Display immer der Wert 0.00 dargestellt aber die Kommunikation mit dem RFM69 klappt leider weiter hin nicht. :roll_eyes: :blush:

#include <Arduino.h>

//arduinoinfo.mywikis.net/wiki/Esp32
/* ESP32                        RFM69W
GND--------------------------GND   (ground in)
VIN--------------------------3.3V  (3.3V in)
interrupt D0 pin GPIO27-------DIO0  (interrupt request out)
SS pin GPIO33----------------NSS   (chip select in)
SCK SPI pin GPIO18-----------SCK   (SPI clock in)
MOSI SPI pin GPIO23----------MOSI  (SPI Data in)
MISO SPI pin GPIO19----------MISO  (SPI Data out) */


//TFT Display
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
//RFM69
#include <RHReliableDatagram.h>
#include <RH_RF69.h>

#define CLIENT_ADDRESS 2
#define SERVER_ADDRESS 1

// For the Adafruit shield, these are the default.
#define TFT_DC 16
#define TFT_CS 17
#define TFT_RST 5
#define TFT_MISO 19        
#define TFT_MOSI 23          
#define TFT_CLK 18

// Slave Select is GPIO pin 33, interrupt is GPIO pin 27
RH_RF69 driver(33, 27);

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram manager(driver, SERVER_ADDRESS);

float oldTemperature;
//the colors we actually want to use
uint16_t Display_Text_Color       = ILI9341_GREEN;
uint16_t Display_Backround_Color  = ILI9341_BLACK; 


struct messwerte
{
  float feuchtigkeit;
  float temperatur;
} dht22_sensordaten;



void rfm_initialisierung()  {
  if (!manager.init())
    Serial.println("init failed");
    // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!driver.setFrequency(868.0))
    Serial.println("setFrequency failed");
  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  driver.setTxPower(14, true);
}





uint8_t data[] = "And hello back to you";
// Dont put this on the stack:
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];


void rfm_datenempfang()  {
   if (manager.available())
  {
    // Wait for a message addressed to us from the client
    uint8_t len = sizeof(buf);
    uint8_t from;
    //Serial.println("test1");
    if (manager.recvfromAck(buf, &len, &from))
    {
      /* Serial.print("got request from : 0x");
      Serial.print(from, HEX);
      Serial.print(": ");
      Serial.println((char*)buf);
      driver.printBuffer("Got:", buf, len); */
      memcpy(&dht22_sensordaten, buf, sizeof(dht22_sensordaten));
      Serial.print(dht22_sensordaten.temperatur);
      Serial.println("°C");
      Serial.print(dht22_sensordaten.feuchtigkeit);
      Serial.println("%");

      Serial.print("RSSI: ");
      Serial.println(driver.lastRssi(), DEC);

      // Send a reply back to the originator client
      /* if (!manager.sendtoWait(data, sizeof(data), from))
        Serial.println("sendtoWait failed"); */
    }
  }
  //Serial.println("test2");
}


unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}


void tft_diagnostic() {
  tft.begin();tft.setRotation(3);tft.fillScreen(ILI9341_BLACK); tft.setTextSize(3);tft.println("Starting...");delay(1000);
  tft.fillScreen(ILI9341_BLACK);
 /* // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 
  
  
  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(500); */
  Serial.println(F("Done!"));
}




void datenausgabe() {
  //tft.begin();
  
  tft.setTextSize(3);
  float newTemperature = 0;
  newTemperature = dht22_sensordaten.temperatur;
  //home the cursor
    tft.setCursor(1,200);
    //change the text colot to foreground color
    tft.setTextColor(Display_Text_Color);
    //draw the new temperatue value
    tft.print(newTemperature);
  if (newTemperature != oldTemperature)  {
    //yes! home the cursor
    tft.setCursor(1,200);
    //change the text color to the background color
    tft.setTextColor(Display_Backround_Color);
    //redraw the old value to erase
    tft.print(oldTemperature);
    //home the cursor
    tft.setCursor(1,200);
    //change the text colot to foreground color
    tft.setTextColor(Display_Text_Color);
    //draw the new temperatue value
    tft.print(newTemperature);
    //and remember the new value
    oldTemperature = newTemperature;
    tft.print("C");
  
  }
}



void setup() {
  Serial.begin(9600);
    while (!Serial)
    ;
  
  rfm_initialisierung();

  tft_diagnostic();
  
}



void loop(void) {
  rfm_datenempfang();

  datenausgabe();

}

Funktioniert denn die Kommunikation mit dem RFM69, wenn du das Display ausklammerst ?

Wenn ich die Funktionen tft_diagnostic() und datenausgabe() kommentiere bekomme ich Daten auf die serielle Schnittstelle. zB.
23.90°C
48.30%
RSSI: -45

Hat jemand eine Ahnung wo der Fehler stecken könnte?
Vielen Dank!

Bin bei meiner Fehlersuche auf diesen Forumeintrag gestoßen.
Obwohl der Benutzer eine andere Bibliothek und einen anderen Microkontroller verwendet, frage ich euch Experten ob dies ein möglicher Grund für das beschriebene Fehlverhalten sein könnte?
Vielen Dank!

Hat niemand von euch einen Tipp wie ich das Problem finden und lösen kann? :disappointed_relieved:

Hast Du meine Checkliste in #3 abgearbeitet?

Hallo DrDiettrich,
Habe deine Checkliste bestmöglich abgearbeitet, danke:

  • keine Pins wurden nach meiner Überprüfung versehentlich doppelt zugeordnet
  • wie kann ich ohne Oszi überprüfen ob beide SS gleichzeitig aktiv sind?
  • Stromversorgung mit dem ESP32 dürfe ausreichen
  • verwende auf deinen Tipp jetzt die Hardware SPI, klappt dennoch leider nicht

Eine Inkompatibilität der benutzten Bibliotheken könnte sicher eine mögliche Ursache sein.
Nur die Frage wie komme ich darauf bzw welche Alternativen zur Verwendung von airpsace radiohead library und einer tft ili9341 Library habe ich?

Mein derzeitiger Testsketch:

#include <Arduino.h>

//http://www.airspayce.com/mikem/arduino/RadioHead/classRH__RF69.html


/* ESP32                        RFM69W
GND--------------------------GND   (ground in)
VIN--------------------------3.3V  (3.3V in)
interrupt D0 pin GPIO27-------DIO0  (interrupt request out)
SS pin GPIO26----------------NSS   (chip select in)
SCK SPI pin GPIO18-----------SCK   (SPI clock in)
MOSI SPI pin GPIO23----------MOSI  (SPI Data in)
MISO SPI pin GPIO19----------MISO  (SPI Data out) */


// rf69_reliable_datagram_server.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple addressed, reliable messaging server
// with the RHReliableDatagram class, using the RH_RF69 driver to control a RF69 radio.
// It is designed to work with the other example rf69_reliable_datagram_client
// Tested on Moteino with RFM69 http://lowpowerlab.com/moteino/
// Tested on miniWireless with RFM69 www.anarduino.com/miniwireless
// Tested on Teensy 3.1 with RF69 on PJRC breakout board
#include <RHReliableDatagram.h>
#include <RH_RF69.h>
#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#define CLIENT_ADDRESS 1
#define SERVER_ADDRESS 2

#define _cs 15
#define _dc 2
#define _mosi 23
#define _sclk 18
#define _rst 4
#define _miso     //not connected

// Use hardware SPI
Adafruit_ILI9341 tft = Adafruit_ILI9341(_cs, _dc, _rst);


// Singleton instance of the radio driver
//RH_RF69 driver;

// Slave Select is pin 26, interrupt is Pin 27
RH_RF69 driver(26, 27);       // http://www.airspayce.com/mikem/arduino/RadioHead/classRH__RF69.html

//RH_RF69 driver(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1
//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
//RH_RF69 driver(8, 7); // Adafruit Feather 32u4
// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram manager(driver, SERVER_ADDRESS);



void setup() 
{
  Serial.begin(9600);
  Serial.println("ILI9343 Test");

  tft.begin();
  tft.setRotation(3);tft.fillScreen(ILI9341_BLACK); tft.setTextSize(3);tft.println("Starting...");delay(1000);
  tft.fillScreen(ILI9341_BLACK);

  while (!Serial) 
    ;
  if (!manager.init())
    Serial.println("init failed");
    // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!driver.setFrequency(868.0))
    Serial.println("setFrequency failed");
  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  driver.setTxPower(14, true);
}
uint8_t data[] = "And hello back to you";
// Dont put this on the stack:
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];


void loop()
{
  if (manager.available())
  {
    // Wait for a message addressed to us from the client
    uint8_t len = sizeof(buf);
    uint8_t from;
    if (manager.recvfromAck(buf, &len, &from))
    {
      Serial.print("got request from : 0x");
      Serial.print(from, HEX);
      Serial.print(": ");
      Serial.println((char*)buf);
      driver.printBuffer("Got:", buf, len);
     

      // Send a reply back to the originator client
      if (!manager.sendtoWait(data, sizeof(data), from))
        Serial.println("sendtoWait failed");

    }
  }
   //tft.setRotation(1);tft.fillScreen(ILI9341_RED); tft.setTextSize(3);tft.println("Test123...");
  
}

Manchmal funktioniert der Sketch und manchmal funktioniert er nicht… :fearful:
Manchmal bekomme ich diese Fehlerausgabe:

Guru Meditation Error: Core 0 panic’ed (Interrupt wdt timeout on CPU0)
Core 0 register dump:
PC : 0x4008643e PS : 0x00060034 A0 : 0x80086c48 A1 : 0x3ffbe140
A2 : 0x3ffbec34 A3 : 0x0000cdcd A4 : 0xb33fffff A5 : 0x00000001
A6 : 0x00060021 A7 : 0x0000abab A8 : 0x0000cdcd A9 : 0x3ffbe140
A10 : 0x00000003 A11 : 0x00060023 A12 : 0x00060021 A13 : 0x3ffb1ff0
A14 : 0x00060b20 A15 : 0x00000000 SAR : 0x0000001b EXCCAUSE: 0x00000005
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Core 0 was running in ISR context:
EPC1 : 0x400ec402 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x4008643e

Backtrace: 0x4008643e:0x3ffbe140 0x40086c45:0x3ffbe170 0x40087c43:0x3ffbe190 0x40087919:0x3ffbe1b0 0x4008166e:0x3ffbe1c0 0x400ec3ff:0x3ffbbff0 0x400d672b:0x3ffbc010 0x40086c12:0x3ffbc030 0x40087b55

Der Exeption Decoder gibt dabei folgendes aus:

PC: 0x4008643e: vTaskEnterCritical at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/include/freertos/portmacro.h line 285
EXCVADDR: 0x00000000

Decoding stack results
0x4008643e: vTaskEnterCritical at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/include/freertos/portmacro.h line 285
0x40086c45: xTaskIncrementTick at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/tasks.c line 2492
0x40087c43: xPortSysTickHandler at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/port.c line 289
0x400ec3ff: esp_pm_impl_waiti at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/pm_esp32.c line 487
0x400d672b: esp_vApplicationIdleHook at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/freertos_hooks.c line 63
0x40086c12: prvIdleTask at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/tasks.c line 3412

Ein Scope wäre schon sehr hilfreich, um die letzten Fehlerquellen auszuschließen. Im ESP steckt so viel Firmware, da wird das Suchen nach Softwarefehlern recht schwierig. Außerdem habe ich keinen zum Ausprobieren :frowning:

Danke für deiner Mühe.
Dann muss ich mir einen Plan B (?) zusammenstellen...