Gibt es bei SPI zwischen NANO und MEGA einen Unterschied?

Hallo und guten Abend zusammen,
es liegt zwar schon ne längere Zeit zurück...aber der ein oder andere erinnert sich bestimmt an die verrückte Rennbahngeschichte.... bin immer noch nicht fertig :joy:

Wollte mal versuchen auf eigenden Füßen zu laufen....hat mit meiner Ampel auch ganz gut funktioniert( Bilder gibt es mal vom Ganzen...). Aber jetzt bei dem Versuch eine 8x32 Matrix und einen NRF24 am MEGA 2560 SPI-BUS ans laufen zu bekommen verzweifel ich.

Am Nano habe ich zur Zeit 4 x 8x32Matrix Streifen und den NRF24 am laufen. Nun wollte ich das ganze an einen MEGA anschließen um auf 8 Streifen zu erweitern. Aber da bekomme ich nicht mal den NRF24 mit einer Matrix zum laufen.

Das Problem, lasse ich die Teile alleine laufen.... Alles gut, aber sobald ich die Matrix mit am SPI-Bus hänge, läuft zwar die Matrix aber der NRF24 empfängt nur noch Müll oder auch garnichts.

Daher meine Frage ist der SPI-BUS unterschiedlich? Der vom MEGA empfindlicher?
Da die Leitungen von der Matrix ca.80cm lang ist. Aber wie schon gesagt am NANO klappt es auch mit den langen Leitungen. Am Nano habe ich keine LCD...aber das kann es doch nicht sein oder...?

Bedanke mich im voraus, weil muss jetzt Bettkarte stempeln...
Dankeeeee

// Matrix auf MEGA 2560Pro
const char ver[] = {"MATRIXANZEIGE"};// 19.12.2022
const char Version[] = {"V-1.00"};
#include <Wire.h>
#include <EEPROM.h>
#include <SPI.h>
#include <printf.h>


// Empfänger
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(4, 5);                              // CE=4, CS=5, SCK=52, MO=51, MI=50
byte address[6] = "00101";             


// Matrix-Anzeige
#include <Adafruit_GFX.h> // TH
#include <Max72xxPanel.h> // TH
Max72xxPanel matrix =  Max72xxPanel(31, 4, 1); // CS 31, DIN (MO=51) , CLK(SCK=52) Beim MEGA
// Max72xxPanel matrix =  Max72xxPanel(4, 4, 1); // CS 4, DIN (MO=11) , CLK(SCK=13) Beim NANO
const byte numberOfHorizontalDisplays = 4;
const byte numberOfVerticalDisplays = 1;
const byte spacer = 1;
const byte width = 5 + spacer;         // The font width is 5 pixels

// LCD
#include <LiquidCrystal_I2C.h>
const uint8_t lcdRow = 16;
const uint8_t lcdCol = 2;
LiquidCrystal_I2C lcd(0x27, lcdRow, lcdCol);

// RotaryEncoder
#include <rotary.h>
Rotary r = Rotary(2, 3, 6);       // Rotary(Encoder Pin 2, Encoder Pin 3, Button Pin 6)
const uint8_t bounce = 10;


// Uhr
#include <DS1307RTCB.h>           // auf die TimeLibB angepasste 1307 von Paul Stoffregen
#include <TimeLibB.h>             // auf deutsch umgeschriebene TimeLib von Paul Stoffregen


// Gespeicherte Werte lesen
//uint8_t Helligkeit_Segment = EEPROM.read(1);                // Helligkeit für alle 7-Segment Anzeigen
//uint8_t NRF_Kanal = EEPROM.read(2);                         // Kanal für NRF24 Empfänger
//uint8_t ID_Steuerung = EEPROM.read(3);                      // ID_Steuerung für Fernsteuerung vom Converter
//uint8_t Einschalt_Display = EEPROM.read(4);                 // Anzeigebild Turm nach dem Einschalten
//uint8_t AnzahlSpuren = EEPROM.read(5);                      // Anzahl der Fahrspuren
//uint8_t NRF24_Leistung = EEPROM.read(6);                    // Empfangsleistung für NRF24 Sender
//uint8_t Datenherkunft = EEPROM.read(7);                     // NRF24 = 1 / Serial-1 = 2
//uint8_t Helligkeit_Led = EEPROM.read(9);                    // Helligkeit für Turm Beleuchtungs-Led's
//uint8_t lumiPole = 7;                                       // Helligkeit für führenden Fahrer bzw. Spur bei der Rundenanzeige



enum {uhrzeit, runde, fahrer, laps};    // was angezeigt werden kann
uint8_t displayNum = uhrzeit;           // was beim Start angezeigt wird

// Wer bin ich
const uint8_t Id = 4;                   // Jeder Empfänger bekommt eine eigene einmalige ID
uint8_t meineSpur = 4;                  // auf welche Spur höre ich

// Renndaten
const uint8_t charNum = 26;             // max Anzahl Zeichen (derzeit Fahrername (25+1))
uint16_t RZvk;                          // Vorkommastellen Rundenzeit
uint16_t RZnk;                          // Nachkommastellen Rundenzeit
uint16_t R;                             // Runde
char F[charNum] = {0};                  // Fahrername

void setup()
{

  // LCD Einschalten
  lcd.init();
  lcd.backlight();


  
  pinMode(53, OUTPUT);                  // verhindert den SPI-SlaveMode
  printf_begin();                       // für NRF-debug Ausgaben
  Serial.begin(115200);
  Serial.println(F("Start..."));

  // Startsequenz nach dem Einschalten
  lcd.setCursor(0, 0); lcd.print(ver);
  lcd.setCursor(0, 1); lcd.print(F("  BLACK SERIES  "));

  
  matrix.setIntensity(1);                  // Helligkeit Matrix 0 und 15 0=schwach, 15=sehr hell
  matrix.setRotation(0, 1);                   // The first display is position upside down
  matrix.setRotation(1, 1);                   // The first display is position upside down
  matrix.setRotation(2, 1);                   // The first display is position upside down
  matrix.setRotation(3, 1);                   // The first display is position upside down
  matrix.write();
  delay(1000);
  matrix.fillScreen(LOW);
  matrix.setCursor(0, 0);
  matrix.print("Spur1");
  matrix.write();
  delay(2000);


  // Empfänger Einstellungen  
  radio.begin();
  radio.enableDynamicPayloads();        // wichtig! Es werden nur Nutzdaten übertragen!
  radio.setPALevel(RF24_PA_HIGH);        // der Sender muss nicht hoch sein(MAX,HIGH,LOW,MIN)
  radio.setChannel(77);  
  radio.setDataRate(RF24_250KBPS);
  radio.setAutoAck(0);                  // NoACK - ein Sender multiple Empfänger
  radio.openReadingPipe(0, address);
  radio.startListening();               // Start des Empfängermodus
}

void loop()
{
  leseEmpfang();                        // spaltet Payload auf
  zeigDisplay(displayNum);              // ausgabe
}

void zeigDisplay(const uint8_t anzeige)
{
  static uint16_t lastsecond = 10000;
  switch (anzeige)
  {
    case uhrzeit:
      if (lastsecond != (uint16_t) second())
      {
        lastsecond = (uint16_t) second();
        //***** Ausgabe Uhrzeit *****
        matrix.fillScreen(LOW);
        matrix.setCursor(1, 0);
        if ((hour()) < 10) {
          matrix.print("0");
        }
        matrix.print(hour());
        matrix.setCursor(13, 0);
        matrix.print(":");
        if ((minute()) < 10) {
          matrix.print("0");
        }
        matrix.print(minute());
        matrix.write();
        LCD_UHR();
      }
      
      break;
    case runde:
      if (meineSpur != 0)
        matrix.fillScreen(LOW);
      matrix.setCursor(0, 0);
      matrix.print("R");
      if ((R) < 10) {
        matrix.setCursor(25, 0);
        matrix.print(R);
      }
      if (((R) > 9) & ((R) < 100)) {
        matrix.setCursor(20, 0);
        matrix.print(R);
      }
      if (((R) > 99) & ((R) < 1000)) {
        matrix.setCursor(14, 0);
        matrix.print(R);
      }
      if (((R) > 999) & ((R) < 10000)) {
        matrix.setCursor(8, 0);
        matrix.print(R);
      }
      matrix.write();
      break;

    case fahrer:
      //Anzeige_Driver();
      break;

    case laps:
      if ((RZvk) > 98) {
        //over();
      }

      else {
        matrix.fillScreen(LOW);
        if (RZvk < 10) {
          matrix.setCursor(6, 0);
        }
        else {
          matrix.setCursor(0, 0);
        }
        matrix.print(RZvk);
        matrix.drawPixel(12, 6, HIGH);
        matrix.drawPixel(12, 7, HIGH);
        matrix.setCursor(14, 0);
        if (RZnk < 100) {
          matrix.print("0");
        }
        if (RZnk < 10) {
          matrix.print("0");
        }
        matrix.print(RZnk);
        matrix.write();
      }
      break;
  }
}

void leseEmpfang()
{
  if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, radio.getDynamicPayloadSize());
    char *c;                                      // Teilstring
    uint8_t zahl = 0;
    c = strtok(text, " ");                        // Lese bis erstes Leerzeichen
    Serial.println(c);
    if (c[0] - '0' == meineSpur)
    {
      switch (c[1])
      {
        case 'R':                                 // Runde für die Spur
          R = atoi(strtok(NULL, " "));
          break;
        case 'Z':                                 // Zeit für die Spur
          RZvk = atoi(strtok(NULL, " "));
          RZnk = atoi(strtok(NULL, " "));
          break;
        case 'F':                                 // Fahrername für die Spur
          strcpy(F, strtok(NULL, " "));
          strcat(F, " ");
          strcat(F, strtok(NULL, " "));
          break;
      }
    }
    else                                          // Ab hier nur zeigen Fernkonfiguration
    {
      switch (c[0])
      {
        case 'T': // T Zeit für RTC
          setTime(atol(strtok(NULL, " ")));     // übernimmt den Zeitstempel
          RTC.set(now());                       // setzt die RTC
          
          break;
        case 'i':
          //          zahl = atoi(strtok(NULL, " "));
          //          if  (zahl == Id)
          //          {
          //            meineSpur = atoi(strtok(NULL, " "));// Zuweisung der Spur für dieses Gerät
          //          }
          break;
        case 'r':
          zahl = atoi(strtok(NULL, " "));
          if (zahl == Id)
          {
            //lcd.clear();
            displayNum = runde;                 // Anzeige Runde
          }
          break;
        case 'f':
          zahl = atoi(strtok(NULL, " "));
          if (zahl == Id)
          {
            //lcd.clear();
            displayNum = fahrer;               // Anzeige Fahrername
          }
          break;
        case 'u':
          zahl = atoi(strtok(NULL, " "));
          if (zahl == Id)
          {
            //lcd.clear();
            displayNum = uhrzeit;              // Anzeige Uhrzeit
          }
          break;
        case 'l':
          zahl = atoi(strtok(NULL, " "));
          if (zahl == Id)
          {
            //lcd.clear();
            displayNum = laps;              // Anzeige Rundenzeit
          }
          break;
      }
    }
  }
}
void LCD_UHR()
{
  lcd.clear();
  lcd.setCursor(0, 1); lcd.print(hour());
  lcd.setCursor(3, 1); lcd.print(minute());
  
}

Ein LCD braucht Strom, möglicherweise sind die bis zu 100 mA nicht mehr übrig?

Ich fange immer bei der Stromversorgung an zu suchen, ein häufiges, aber leicht zu behebendes Problem.

Hallo agmue,
da hängt ein 5 Ampere Netzteil zur Versorgung dran von daher sollte genung sein. Hab es gerade mal Spaßeshalber mal abgezogen.... bleibt sich gleich.

Aber ein Versuch war's wert.

Einzig was ich bei SPI am Mega hatte, das zB., für SD wollte er unbedingt CS 48 oder 38, mit 4, und 10 wie bei Nano, Uno wollte er nicht warum? Gute Frage.
Normal wurde sagen, musste das egal sein. Das mit dem 48 habe damals im MC Forum gefunden.
Bei SoftSPI ist dem egal was für Pins man nimmt. Auch bei ESP ist egal welchen Pin man für CS / SS nimmt.

Wie sieht die Versorgung des nRF24 aus? Der braucht ja 3,3V. Woher kommen diese?

Guten Morgen ins Tal der ewig Unfertigen :slight_smile:

Ich hab mal den Code überflogen. Macht richtig Spaß drin zu lesen; Man erkennt einiges wieder...

Der zickige SPI am Mega kommt mir bekannt vor. Wenn er einmal lief, dann konnte auch nicht mehr nachgestellt werden, warum der vorher ausgestiegen ist.
Im setup() hab ich schon den OUTPUT für den 53 gefunden, Daran sollte es dann nicht liegen.
Auch sonst denke ich, ist der Aufbau eher unspektakulär.
Von daher nur zwei Ansatzpunkte:

Betreibst Du die NRF-Module mit einem 5V-Versorgungssockel oder direkt aus den 3,3V des MEGA? Ohne Sockel empfehle ich nen kleinen Elko zur Stabilisierung der Versorgung direkt am NRF.

Mit der AdafruitGFX hatten wir gerade letztens Probleme im Zusammenhang mit einem Grafikdisplay. Die benutzt die AdafruitIO und sobald die verwendet wird, passieren komische Dinge.
Ich finds blos nicht mehr. Aber da wurde für das Display gegen die U8G2 getauscht und schon war alles schick.

Nachbauen kann ich leider nicht - aber ich les mit und mach mir Gedanken drüber....

Ampel_Steuerung_KA-022_Version2.5_Black_Series.ino (95.4 KB)

Guten Morgen zusammen,
da kann ich Dir nur zustimmen... hab jetzt mal alle noch verfügbaren Pins ausprobiert. Leider überall das gleich Ergebnis.Aber eine neue Erkenntnis habe ich lasse ich den CS(DIN) weg, dann spinnt die Matrix mit alle LEDs an und ca. 1 A Stromverbrauch aber ich kann empfangen.

Ich stellte mir das soooo schön vor da beim Nano 4 Matrix-Streifen schon liefen, aber da hat mir der MEGA ein Strich durch die Rechnung gemacht.

@Plumps
Da habe ich einen 5V-Versorgungssockel

@my_xy_projekt
Einen schönen guten Morgen an meinem Lehrmeister.
Ja, Deine Handschrift ist doch sehr schön zu erkennen... :smiley:
Aber Deinen Satz" Der zickige SPI am Mega " wollte ich hören, gefühlt tausend mal die Verbindung gesprüft....war schon am verzweifeln und bin dann auf den Schluss gekommen doch mal hier nachzufragen.

Der Grund warum ich mehrere 8x32 Matrixanzeigen am Mega wollte....eben einen MEGA, ein Gehäuse, ein Netzteil eben. Aber wenn der so zigig ist.....nehme ich einzelne Nano's.

Im Anhang mal meine Startampel, die ich ohne Hilfe hinbekommen habe. Hat zwar etwas länger gedauert.....aber die kleinen Autos fahren mir ja nicht weg, die fahren nur im Kreis. :joy:


Wenn einer noch eine Idee hat wie ich/wir den zickigen Mega überzeugen können.....
Probiere gerne aus.

Grüße aus dem Tal wo die Züge ihre Räder auf dem Dach haben :wink:

Alter... ist die Montage geil geworden...
Da sieht man, wo Du Deine Handschrift hinterlässt.

Die Antenne ist für die NRF's?

Das mit dem SPI am MEGA ist eigentlich gar nicht das Problem, aber mal ne andere Frage: Wenn Du den 53 sonst nicht nutzt, hast Du mal versucht den als CS für das NRF-Modul zu setzen? (Im setup() dann deaktivieren...)

Danke für die Blumen, da hat mir einer zwei geschickte Hände mitgegeben.... :grinning:

Jupps, die Antenne ist für den NRF und ich kann Dir sagen alles was wir bisher zusammen gemacht haben funzt bis heute einwandfrei..Ein großen knicks an Dich an dieser stelle nochmal. :heart_eyes:

Das mit dem Mega....für mich schon.
Wenn ich Dich jetzt richtig verstanden habe...statt RF24 radio(4, 5); dann RF24 radio(4, 53);

Hab'gerade mal so angeschlossen....und getestet.
Matrix läuft, aber kein Empfang mehr auch ohne Matrix kein empfang mehr!

Hallo,

probiere den NRF24 alleine nochmal am Mega mit SPI.begin() im setup.
Pin 53 weiterhin auf Ausgang konfigurieren. Das trifft auch für Pin10 auf dem Uno zu.
Ob man Pin 53 oder einen anderen für CS nimmt muss egal sein.

Hallo Doc_Arduino,
vielen Dank für Deinen Tipp, der leider auch nicht zum Erfolg geführt hat.
Zwar läuft der NRF alleine am SPI-BUS (das tut er mit und ohne SPI.begin() )
Aber mit der Matrix zusammen, läuft nur noch die Matrix ohne Empfang des NRF's.

Einzeln läuft alles wie es soll, nur zusammen nicht. Das witzige am Nano läuft es.
Verstehe nicht wo der Unterschied ist.

mach mal zwei einfache Sketche:

a)
nur NRF und die Max72xxPanel.h
--> Test auf Nano und MEGA

b)
nur NRF und eine andere MAX7219 lib die HW SPI verwendet.
--> Test auf Nano und MEGA

damit könntest du zumindest erkennen ob es einen Zusammenhang mit der Max72xxPanel.h gibt
und weiters testen, ob die Reihenfolge der Aufrufe deiner zwei konkurrierenden Libraries einen Einfluss hat.

Was ich so sehe die Max72xxPanel.h macht ein
SPI.begin(); und weitere HW Sachen im Constructor

Das fühlt sich für mich suboptimal an. die RF24 hab ich noch nicht gesichtet...

Hallo noiasca,

ich hab da mal was ausprobiert.....

// Program to demonstrate the MD_Parola library
//
// Simplest program that does something useful - Hello!
// Uses the Arduino Print Class extension
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <printf.h>

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4

#define CLK_PIN   52
#define DATA_PIN  51
#define CS_PIN    38

// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Empfänger
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(4, 5);                              // CE=4, CS=5, SCK=52, MO=51, MI=50
byte address[6] = "00101";  


void setup(void)
{
  P.begin();
  P.print("Hello!");
  pinMode(53, OUTPUT);                  // verhindert den SPI-SlaveMode
  SPI.begin(); 
  printf_begin();                       // für NRF-debug Ausgaben
  Serial.begin(115200);
  Serial.println(F("Start..."));  
  // Empfänger Einstellungen  
  radio.begin();
  radio.enableDynamicPayloads();        // wichtig! Es werden nur Nutzdaten übertragen!
  radio.setPALevel(RF24_PA_HIGH);        // der Sender muss nicht hoch sein(MAX,HIGH,LOW,MIN)
  radio.setChannel(77);  
  radio.setDataRate(RF24_250KBPS);
  radio.setAutoAck(0);                  // NoACK - ein Sender multiple Empfänger
  radio.openReadingPipe(0, address);
  radio.startListening();               // Start des Empfängermodus

}

void loop(void)
{
  leseEmpfang();
}

void leseEmpfang()
{
  if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, radio.getDynamicPayloadSize());
    char *c;                                      // Teilstring
    //uint8_t zahl = 0;
    c = strtok(text, " ");                        // Lese bis erstes Leerzeichen
    Serial.println(c);                            // Um zu sehen das Daten eintreffen und lesbar sind  ;-)
  }
}

Aber auch hier funktioniert wieder nur die Matrix am MEGA, dabei ist die Reihenfolge des Aufrufes egal. Was ich noch nicht versucht habe ist das hier:
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES)

Das werde ich gleich mal probieren.....
Bis später

nö bleib mal bei dem Konstruktor für HW SPI.

ja....aber :smile: Es geht doch auch nicht... mhmm.

hast du mal die Aufrufe im Setup umgedreht?

// 0
pinmode
SPI.begin()

// 1
und dann radio
und gleich was schicken?

//2
und dann matrix
und gleich was an die Matrix printen.

//3
noch mal radio schicken

//4
noch mal was an die Matrix schicken

alles im Setup.

wenn 1 noch klappt und 3 nicht mehr spießt sich vieleicht was mit den SPI Einstellungen.

Das verstehe ich nicht.

Der nRF24 braucht doch 3,3V.

Der Nano stellt die 3,3V anders bereit als der Mega. Vielleicht bricht die Spannung da eher zusammen.

Oder hast du einen Extra 3,3V Regler für dein nRF24?

... 0 habe ich gedreht.

...1 ich lese die Daten, aber da kommt schon Müll an.

@Plumps
Nein, es ist ein Adapter von 5Volt auf die 3,3V gibt es fast überall zu kaufen.

Zum verrückt werden.... :thinking:

1 Like

interessant.

und wenn du die Matrix komplett abschließt (aber den Code noch drinnen lässt) dann liest 1 wieder saubere Daten?

Jupps, genau so ist es.Verstehe es wer will.Selbst wenn ich nur anschließe ohne darauf zu schreiben, bleibt der NRF hängen. :sleepy: