Ich sehe es nicht

Vor einer Weile schrieb ich mal von Problemen mehre von diesen 8x8 LED-Quadraten mit MAX7219 zum arbeiten zu bewegen. Das klappt jetzt sicher indem ich a) jeden MAX mit 10µF abgeblockt habe und b) das Timing in der MAX72xx Lib pro Byte etwas verlangsamt habe.

Das ganze soll eine Jux Anwendung für einen Bekannten werden. Jetzt soll das ganze mit einer Fernbedienung auf nrf24 bedient werden. Der Fernbedienungssender ist schon seit 3 Jahren fertig und
arbeitet mit einer anderen Anwendung Problemlos zusammen. Auch die Empfangsroutinen waren flux
eingebaut und dann ging die ParolaLib für die LEDs nicht mehr. An der Fernbedienung habe ich eine
Error LED die mir anzeigt ob das Paket angekommen ist. Die blieb aus ! Also ging der Empfänger.

Ach so alles läuft auf einem ProMini dessen Bootloader als UNO geflasht wurde.

Also wollte ich nachschauen ob auch wirklich empfangen wurde.
Serial.begin rein und ein paar Testausgaben.
Und was passiert : Alles funktioniert. Die Texte scrollen brav durch die Anzeige und Kommandos
der Fernbedienung kommen einwandfrei durch.

Testausgaben raus. Nix geht mehr. Nur das Serial.begin(9600) drin gelassen und es funktioniert.

Das da war faul ist ist mir klar. Nur ich sehe nicht wo. Die Hardware tut es einwandfrei daher schiebe
ich das rein auf die Software. Erst dachte ich ja das sich irgendwelche Hardwarekonflikte zwische NRF-Lib und Parola lib da rein geschlichen haben. Aber Parola nutzt SoftSPI und NRF HardSpi.

Könnte es einfach so lassen aber es macht mich verrückt.
Die Source : (musste Kommentare raus nehmen weil sonst > 9000)

#define SOFT_SPI 1

#ifdef SOFT_SPI
#define DATA_PIN 7
#define CS_PIN   8
#define CLK_PIN  9
#else
#define CLK_PIN   13
#define DATA_PIN  11
#define CS_PIN    10
#endif

#define RCVLED    2

#define NUM_MAX 16

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

#include "RF24.h"
RF24 radio(A0, 10);
#define BASECHANNEL 111

//--------------------------------------------------------------------------------------------------
// Used to control whether this node is sending or receiving
//--------------------------------------------------------------------------------------------------

const uint64_t addresses[8] = {0xE8E8F0F0E1LL,0xE8E8F0F0E2LL,0xE8E8F0F0E3LL,0xE8E8F0F0E4LL,
                               0xE8E8F0F0E5LL,0xE8E8F0F0E6LL,0xE8E8F0F0E7LL,0xE8E8F0F0E8LL};

//--------------------------------------------------------------------------------------------------
// Struktur zum Senden und empfangen

typedef struct d
{
  uint16_t key;  
  uint16_t dip;  
  uint16_t pwr; 
} data;

data sendData; // Machen wir global und schreiben einmal initial die DIP-Schalter rein

//--------------------------------------------------------------------------------------------------
// Statische Variablen
//--------------------------------------------------------------------------------------------------

uint64_t sendQueue; // Variable Sendque


#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 16


#define SPEED_TIME  29   // 25
#define PAUSE_TIME  750  // 1000

#ifdef SOFT_SPI
MD_Parola p = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#else
MD_Parola p = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
#endif

#define ZAEHLER2 0
#define SAUF     1
#define ZAEHLER1 2

uint8_t readDip()
{
  uint8_t cnt;
  uint8_t retVal;

  retVal = 0;
  
  for (cnt = A3;cnt > A0;cnt--) // A4 nicht angeschlossen 
  {
    pinMode(cnt,INPUT);
    digitalWrite(cnt,HIGH); // PULL UP HIGH !

    retVal = retVal << 1;
    if (! digitalRead(cnt))
    {
      retVal = retVal | 1;
    }

    digitalWrite(cnt,LOW); // PULL UP Wieder weg ! um Energie zu sparen
  }
  return(retVal);
}

//--------------------------------------------------------------------------------------------------

void setup()
{
  uint8_t channel;
  uint8_t queue;
  uint8_t cnt;

  Serial.begin(9600);

  pinMode(RCVLED,OUTPUT);

  for (cnt = 0 ; cnt < 10 ; cnt++)
  {
    digitalWrite(RCVLED,!digitalRead(RCVLED));
    delay(250);
  }
  digitalWrite(RCVLED,LOW);

  channel = readDip();
  sendData.dip = channel; // Only for debuging send dip-status 

  queue = channel & 0x07;
  channel = BASECHANNEL + (channel & 0x08);

  sendQueue = addresses[queue]; 

  radio.begin();
  radio.setChannel(channel);
  radio.setRetries(15, 15);
  
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate(RF24_2MBPS);

  radio.openReadingPipe(1, addresses[queue]);

  radio.startListening();

  pinMode(DATA_PIN,OUTPUT);
  pinMode(CS_PIN,OUTPUT);
  pinMode(CLK_PIN,OUTPUT);
  delay(500);
  
  p.begin(3);
  p.setInvert(false);

  p.setZone(ZAEHLER2,0,3);
  p.setZone(SAUF,4,11);
  p.setZone(ZAEHLER1,12,15);
  p.displayZoneText(ZAEHLER2,"4 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
  p.displayZoneText(SAUF,"Saufspiel V0.9",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
  p.displayZoneText(ZAEHLER1,"1 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);

}

int flag = 0;
char VarText[80];

void loop()
{
  uint8_t  pipeNr;
  uint16_t taste;
  uint16_t extTaste;
  data     DataRead;
  uint8_t  received;
  uint32_t lastMillis;  

  while (!p.getZoneStatus(0))    p.displayAnimate();
  while (!p.getZoneStatus(1))    p.displayAnimate();
  while (!p.getZoneStatus(2))    p.displayAnimate();

  lastMillis = millis();
  received = 0;

  while ( (!received) && ((millis() - lastMillis) < 3000) )
  { 
     received = radio.available(&pipeNr);
  }

  if (received)
  {
    digitalWrite(RCVLED,!digitalRead(RCVLED));
    radio.read(&DataRead,sizeof(data));  
    taste    = DataRead.key & 0x00FF;
    extTaste = DataRead.key & 0xFF00;
    sprintf(VarText,"Taste %c Ext %d",taste,extTaste >> 8);
  }
  else
  {
    strcpy(VarText,"Nothing on air !");
  }
  
  switch(flag)
  {
    case 0:
    {
      p.displayClear(SAUF);

      p.displayClear(ZAEHLER2);
      p.displayClear(ZAEHLER1);
      p.displayZoneText(ZAEHLER2,"4 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
      p.displayZoneText(ZAEHLER1,"1 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);

      p.displayZoneText(SAUF,VarText,PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
    }
    break;

    case 1:
    {
      p.displayClear(SAUF);

      p.displayClear(ZAEHLER2);
      p.displayClear(ZAEHLER1);
      p.displayZoneText(ZAEHLER2,"9 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
      p.displayZoneText(ZAEHLER1,"12 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);

      p.displayZoneText(SAUF,VarText,PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
    }
    break;

    case 2:
    {
      p.displayClear(SAUF);

      p.displayClear(ZAEHLER2);
      p.displayClear(ZAEHLER1);
      p.displayZoneText(ZAEHLER2,"3 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
      p.displayZoneText(ZAEHLER1,"2 Pkt",PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);

      p.displayZoneText(SAUF,VarText,PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_SCROLL_LEFT);
    }
    break;
  }
  flag++;
  if (flag == 3) flag = 0;
}

Ulli

Testausgaben raus. Nix geht mehr. Nur das Serial.begin(9600) drin gelassen und es funktioniert.

Hatte ich auch mal, daß ein Serial.print() einen Sketch zum korrekten funktionieren brachte.
Bei Mir war der Fehler ein Overflow eines Indexes eines Arrays.
Jetzt hab ich weder das Hirn um biese Zeit mir das Hirn zu zermartern und mir tiefere Gedanken Deines Sketches und vor allem der Verwendeten Bibliotheken zu machen.

char VarText[80];

void loop()
{
  ...
  data     DataRead;
...
while ( (!received) && ((millis() - lastMillis) < 3000) )
  {
     received = radio.available(&pipeNr);
  }

  if (received)
  {
    digitalWrite(RCVLED,!digitalRead(RCVLED));
    radio.read(&DataRead,sizeof(data)); 
    taste    = DataRead.key & 0x00FF;
    extTaste = DataRead.key & 0xFF00;
    sprintf(VarText,"Taste %c Ext %d",taste,extTaste >> 8);
  }

Grüße Uwe

beeblebrox:
... ... Nur ich sehe nicht wo. ...

Meine Erfahrung: Je unerklärlicher und unlogischer Fehlfunktionen sind, desto wahrscheinlicher ist, dass kapper Speicher die Ursache ist. Was sagt die IDE zum Speicherbedarf?

Gruß

Gregor

PS:

beeblebrox:

...

uint64_t sendQueue; // Variable Sendque
...

Der Kommentar ist ja mal echt geil ...

Speicher sieht eigentlich gut aus :

Der Sketch verwendet 23988 Bytes (74%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 515 Bytes (25%) des dynamischen Speichers, 1533 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Ulli

beeblebrox:
Speicher sieht eigentlich gut aus :

Stimmt. Könntest Du mal das vollständige/übersetzbare Programm posten?

Gruß

Gregor

Das ist doch im ersten Posting !

Ulli

beeblebrox:
Das ist doch im ersten Posting !

Ja, Du hast dort halt erwähnt, dass Du es bearbeitet hast. Ich scrolle gerade mal quer, um nach etwas Auffälligem zu gucken. Wenn die Kommentare alle so sind wie das von mir zitierte Ding und Du wirklich nur Kommentare entfernt hast, hast Du nichts Wichtiges gelöscht :slight_smile:

Gruß

Gregor

Ich befürchte auch das der Hase in einer der Libs im Pfeffer liegt.

Wie gesagt die Einzelkomponenten laufen #ifdef-fe ich alles was NRF heißt aus geht
Parola. #ifdef ich parola aus geht NRF. (Dann natürlich ohne Serial.begin);

Ulli

Entschuldigt die naive Frage

uint64_t sendQueue; // Variable Sendque

Gibt es auf einem 8 Bit Controller eine 64 bit Variablentype? Laut Speicherbedarf scheint es ein ATmega328 zu sein.
Grüße Uwe

uwefed:
Entschuldigt die naive FrageGibt es auf einem 8 Bit Controller eine 64 bit Variablentype? Laut Speicherbedarf scheint es ein ATmega328 zu sein.

Naja, die Rückgabe von millis() ist 32 Bit breit.

Geht trotzdem :slight_smile:

Gruß

Gregor

PS: Ich kann zumindest auf die Schnelle nichts entdecken, was blöd aussieht. Gab es nicht einen „Trick“, mit dem man sich die Größen von Stack und Heap ausgeben lassen kann ...?

Moin Ulli,
hmm.

Im Zusammenhang mit Serial ist mir fast nix aufgefallen.
Allerdings verwendet die RF24_lib u.U. den Port:
RF24.cpp Zeile 300:

IF_SERIAL_DEBUG(printf("[Reading %u bytes %u blanks]\n", data_len, blank_len); );

Nebenbei bemerkt: Ich glaube, dass es mit HW-SPI nicht funktionieren kann:
Zeile 11:

#define CS_PIN    10

und

RF24 radio(A0, 10);
...
MD_Parola p = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

Da sehe ich eine doppelte Verwendung von Pin 10 in Zeile 23 und 62.

Im readDip() liest Du A3 bis A0 und nimmst dann den Pull-Up weg - auch für A0. Das ist aber der Chip Enable für radio (RF24). Hoffentlich dreht der radio.begin() in Zeile 119 das wieder gerade.

Gruß Walter

uwefed:
Entschuldigt die naive FrageGibt es auf einem 8 Bit Controller eine 64 bit Variablentype?

Ja!
Auch wenn Print sich etwas schwer tut, bei den Ausgaben.

Aber den Datentype gibt es.

Ausgaben von (u)int64_t habe ich hier mal gemacht für alle Kinder von Stream.

Gruß Tommy

Danke für die Erklährung.
Uwe

Also HARD Spi wird nicht gesetzt also ist die Doppelbelegung von Pin 10 nicht gegeben.
Die For-Schleife von ReadDip geht bis > A0. Also an A0 fummelt die auch nicht rum.

Die ganzen Codeteile von "NRF" laufen auch schon genau so in anderen Applikationen ohne
Probleme.

Ulli

beeblebrox:
Also HARD Spi wird nicht gesetzt also ist die Doppelbelegung von Pin 10 nicht gegeben.

Das scheint mir anders: Bei den #define-Zeilen definierst Du

#define CS_PIN    [color=red]10[/color]

etwas weiter unten dann

RF24 radio(A0, [color=red]10[/color]);

und noch etwas weiter unten

#ifdef SOFT_SPI
MD_Parola p = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, [color=red]CS_PIN[/color], MAX_DEVICES);
#else
MD_Parola p = MD_Parola(HARDWARE_TYPE, [color=red]CS_PIN[/color], MAX_DEVICES);
#endif

Das lese ich so, dass CS_PIN auf jeden Fall doppelt belegt wird, egal ob Soft-SPI oder nicht.

Oder übersehe ich etwas?

Gruß

Gregor

Aber oben steht :

#ifdef SOFT_SPI

#define CS_PIN 8

Ulli

beeblebrox:
Aber oben steht :

#ifdef SOFT_SPI

#define CS_PIN 8

Ulli

Ups, ja, Du hast recht.

Gruß

Gregor

Hallo,

du solltest nach > 500 Beiträgen anfangen die Libs so zu nutzen wie sie vorgesehen sind.
Auch hier gibt es eine begin Methode der Klasse die alles konfiguriert.
Du musst nicht anfangen das nochmal einzeln mit pinMode zumachen. Kommt nur Kaos bei raus.
Siehst du auch in keinem Bsp. der Lib.
Das erspart dir deine define Orgien, was aufgeräumten Code zur Folge hat.
Am Ende brauchst du nur 2 Zeilen wovon du eine auskommentierst.
Hier benötigst du keine Variablen, schreibst die Pinnummern direkt in die Parameterliste.

MD_Parola p = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
MD_Parola p = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

Das gleiche machst du mit allen anderen Libs die du verwendest.
Bei allen anderen Konstanten solltest du kein define verwenden sondern const + Datentyp ...

Du meinst :

  pinMode(DATA_PIN,OUTPUT);
  pinMode(CS_PIN,OUTPUT);
  pinMode(CLK_PIN,OUTPUT);
  delay(500);

Das hatte sich eingeschlichen als ich damals Probleme mit der Parola-Lib hatte.
Nehme ich gleich mal raus, glaube allerdings nicht das das Problem ist.

Abgesehen davon hatte ich das schon einige Male im Laufe der Jahre das man einigen Libs "Per Hand"
etwas nachhelfen musste. Oft kamen die Tipps hier aus dem Board.

Ulli