Sprintf und nrf24 schiessen MEGA ab? / UNO funktioniert

[edit 3.6. 18:20: Nur Betreff angepasst]
[edit 3.6. 22:30: Das lässt sich auch mit einer vollkommenden anderen Herangehensweise nachstellen - Danke an J-M-L - Der Code hier im Ausgangspost läuft ggfls. durch. Das nachzubauen geht ab #6 mit dem Code dort. bzw. ab J-M-L in #17 - Letzter Stand für UNO/MEGA sowohl als Sender und Empfänger in #34]
[edit 4.6. 19:25: Unter Windows wird ein anderes Binary erstellt als unter Ubuntu. Auch die Debugausgaben sind ganz anders - getestet mit einem Sketch in #46 ff.]

Hat jemand ne Erklärung dafür, das ein sprintf irgendwo im Code den MEGA abschiesst?

Kurzsketch in #6 oder ab #25:

Verwendete lib:

Das einkommentieren von neueFunktion() macht jeder selber für sich...

Was ist das Problem genau?

NB: %i ist nicht geeignet für uint8_t, das könnte dein problem sein (du musst "%u" benutzen)

1 Like

Nicht wirklich, da ich den Fehler nicht reproduzieren kann, aber ich würde mal snprintf() versuchen:

void neueFunktion()
{
  const byte anzahl = 30;
  char zeige[anzahl] = {0};
  uint8_t a = 1;
  snprintf(zeige, anzahl, "%i", a);
  Serial.println(zeige);
}

Weiterer Versuch wäre eine Bremse in loop, weil Serial eventuell überlastet sein könnte.

Ich gehe mal davon aus, dass "den MEGA abschiessen" (was auch immer da passiert) nur in genau dieser Kombination bei dir zu beobachten ist. Um @J-M-L 's Hinweis zu verwerten, könntest du deinen Test mit
sprintf(zeige, "%i", 1);
machen.

Ohne RF24 radio kann ich übrigens kein Problem feststellen.

Ja. Das Problem liegt wahrscheinlich woanders

("%u" wäre besser als "%i", aber das uint8_t wird wahrscheinlich zu einem int hochgestuft)

Sorry fürs späte antworten - musst emich erstmal sammeln und das nochmal runterbrechen.

Bei der Benutzung von sprintf führt radio.begin() zum Reeboot des MEGA. Der Bootloader ist dann zerschossen.

Nein tut es auch nicht.

Ja, das ist das Problem...
Der Sketch war eine minimalistische Zusammenfassung, da muss irgendwas anders bei gewesen sein - hab jetzt mal Eure Tipps mit eingearbeitet und noch weiter runtergekürzt und auf einem Ubuntu mit einer 1.8.13, einer 1.8.15 sowie einer 1.8.8 am laufen gehabt.
Mittlerweile bin ich schneller im Bootloader flashen, als im Code hochladen :wink:

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

const byte cePin = 8;
const byte csPin = 7;
const byte address[6] = "00001";

RF24 radio(cePin, csPin);
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));

  pinMode(53, OUTPUT);

  // Setup Sender Start
  radio.begin();
  Serial.println(F("RadioStart..."));
  radio.setPALevel(RF24_PA_LOW);
  radio.setDataRate(RF24_1MBPS);
  radio.openWritingPipe(address);
  radio.setAutoAck(0);
  radio.stopListening();
  // Setup Sender Ende
}

void loop()
{
  //delay(100);
  Serial.println(F("tik"));
  uint8_t a = 1;
  char sende[] = {"test"};
  char stb[30] = {0};
  //snprintf(stb,"%i", a);
  radio.write(sende, sizeof(sende));
}

Wenn ich bei delay(100) und s(n)sprintf kommentiere, läuft es wie Biene. (so wie jetzt im code)

Wenn ich bei delay(100) den Kommentar entferne, läuft es auch - nur eben langsamer aber auch stundenlang.
Setze ich den wieder ein und entferne jetzt bei snprintf den Kommentar, öffne den Seriellen Monitor und dann den Sketch hochlade:

13:37:46.757 -> Start...
13:37:47.686 -> RadioStart...
13:37:47.686 -> tik
[SELBER INHALT NOCH 22X] (Jeweils mit gleicher Zeitangabe...)
13:37:47.719 -> tik
[SELBER INHALT NOCH 44X]
13:37:47.796 -> tik
[SELBER INHALT NOCH 101X]
13:37:47.818 -> tik
[SELBER INHALT NOCH 25X]
13:37:47.852 -> tik
[SELBER INHALT NOCH 44X]
13:37:47.885 -> tik
[SELBER INHALT NOCH 44X]
13:37:47.918 -> tik
[SELBER INHALT NOCH 44X]
13:37:47.951 -> tik
[SELBER INHALT NOCH 44X]
13:37:47.984 -> tik
[SELBER INHALT NOCH 37X]
13:37:48.017 -> tik
[SELBER INHALT NOCH 44X]
13:37:48.050 -> tik
[SELBER INHALT NOCH 44X]
13:37:48.083 -> tik
[SELBER INHALT NOCH 44X]
13:37:48.116 -> tik
[SELBER INHALT NOCH 44X]
13:37:48.149 -> tik
[SELBER INHALT NOCH 44X]
13:37:48.182 -> tik
[SELBER INHALT NOCH 20X]
13:37:48.182 -> tik
13:37:48.182 -> tik
13:37:48.182 -> tik
13:37:49.043 -> Start...
13:37:49.870 -> Start...
13:37:50.732 -> Start...
13:37:51.560 -> Start...
13:37:52.422 -> Start...

Kommt jetzt das delay(100) noch mit rein, wird es kürzer:

// ungekürzt
13:48:27.620 -> Start...
13:48:27.620 -> RadioStart...
13:48:27.720 -> tik
13:48:27.819 -> tik
13:48:27.918 -> tik
13:48:28.017 -> tik
13:48:28.117 -> tik
13:48:28.977 -> Start...
13:48:29.805 -> Start...
13:48:30.667 -> Start...
13:48:31.527 -> Start...
13:48:32.354 -> Start...

setze ich das delay auf 1000 nur noch einen tik bis zum Dauerrestart. Vergrößere ich das delay auf 2000 dauerst 22 Ausgaben / 44 Sekunden.

Er kommt genau bis radio.begin() - und das wars.

Vor allem muss ich jedes Mal den Bootloader neu flashen.

Und ich hab keine Compilerwarnungen und extra nachgesehen ob die richtigen .h .cpp aus den Verezichnissen geholt werden.
Ja tun sie.

Nein!

Das ist nur ein untrügliches Indiz dafür, dass du in der falschen Richtung suchst.

Tipp:

wer in die falsche Richtung läuft, braucht sich nicht zu beeilen.

Fehlt bei dem Aufruf von snprintf nicht der zweite Parameter für die Länge?

Ja, in #3 ist er drin.

snprintf(zeige, anzahl, "%i", a);

die Variable a ist ein uint8_t --> Wert liegt also zwischen 0 und 255.
--> char zeige [30] ist groß genug, um a . darzustellen

sprintf oder snprintf ist nicht das Problem

Wenn Du snprintf ohne den Parameter Anzahl aufrufst, dann unter Umständen schon. Dann wird die Formatzeichenkette fehlinterpretiert.

Gruß Tommy

ja natürlich musst du die funktion richtig nutzen. Aber in diesem Fall es gibt kein Pufferüberlaufproblem

Nein - es ist ein Zeichen dafür, das ich den halben Satz weggelassen habe.

Der Code funktioniert solange die nrf nicht involviert.
Das radio.write() führt nur in Verbindung mit einem irgendwo im Code stehenden s(n)printf dazu, das der Bootloader hin ist und zum Neustart führt.

Also entweder kein s(n)printf oder kein radio.
Ich denk noch drüber nach.
Und ich muss mich ja nicht beeilen....

Dein Wort in Gottes Gehörgang......

Der Weg in die Hölle ist mit falschen Annahmen gepflastert.

Falsch!

Bei einem MEGA kann man eigentlich den Bootloader nicht zerschießen.
Jedenfalls nicht, wenn man es als normaler Sketch gar nicht vorhat.
Es könnte am ehesten der Bootloader selber sein, der aus irgendeinem Grund sich weigert, nichts zu tun und den aktuellen Sketch laufen zu lassen....

Das hatte ich auch gedacht.
Der Code lief vorher ohne Probleme auf einem UNO-Clone. (Pin 10 dann als OUTPUT gesetzt)

Dann geht der eben wieder dahin.

Danke Euch fürs mitsuchen.

könntest du den folgenden Code versuchen:

#include <RF24.h> // https://nrf24.github.io/RF24/
const byte CEPin = 7;
const byte CSNPin = 8;
RF24 radio(CEPin, CSNPin);

uint8_t address[] = {0xCC, 0xCE, 0xCC, 0xCE, 0xCC};

struct __attribute__ ((packed)) message_t {
  char text[20];    // large enough for an uint32_t
  uint32_t chrono;  // timestamp
} message;

const uint32_t period = 5000ul;

void sendMessage(message_t &msg)
{
  if (!radio.write( &msg, sizeof(message_t) )) {
    Serial.println(F("Error sending message"));
  } else {
    Serial.println(F("---------------------------"));
    Serial.print(F("I sent \"")); Serial.print(message.text);
    Serial.print(F("\", timing = ")); Serial.println(message.chrono);
  }
}

void setup() {
  Serial.begin(`115200`);

  if (!radio.begin()) {
    Serial.println(F("radio missing!!"));
    while (true) ; // die here
  }

  radio.setPALevel(RF24_PA_LOW);
  radio.setPayloadSize(sizeof(message_t));
  radio.openWritingPipe(address);
  radio.stopListening();
  Serial.println(F("**** READY ****"));
}

void loop() {
  static unsigned long previousChrono = 0;
  if (millis() - previousChrono >= period) { // every 5 seconds
    previousChrono = millis();
    snprintf(message.text, sizeof message.text, "%lu", previousChrono);
    // or more efficient than sprintf
    // ultoa(previousChrono, message.text, 10); // https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga34f41757388f40e340f31e370ac009b5
    message.chrono = previousChrono;
    sendMessage(message);
  }
}
1 Like

Geht nicht.
Ich hab im setup noch ergänzt:

  pinMode(53, OUTPUT);

Und das loop() erweitert:

void loop() {
  static unsigned long previousChrono = 0;
  if (millis() - previousChrono >= period) { // every 5 seconds
    Serial.println("tik");
    previousChrono = millis();
    snprintf(message.text, sizeof message.text, "%lu", previousChrono);
    // or more efficient than sprintf
    // ultoa(previousChrono, message.text, 10); // https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga34f41757388f40e340f31e370ac009b5
    Serial.println(message.text);
    message.chrono = previousChrono;
    sendMessage(message);
  }
}

Ausgabe:

17:20:42.598 -> **** READY ****
17:20:47.599 -> tik
17:20:47.599 -> 5⸮

Phänomen wie vor.
Versuche ich den Sketch erneu zu starten (mit reset oder durch neu flashen mit dem Sketch) kommt er nicht bis zum READY.

Nur der Bootloader wieder rauf - dann gehts. Einmal.

Warum?

Kannst du deine Verbindungen beschreiben und wie der Gig mit Strom versorgt wird?

Der MEGA wird via USB versorgt.
Das Externe mit 5V aus einem LiteOn 4250.
Der NRF mit Adapterplatine.

Hinweis: Der Aufbau mit einem UNO funktioniert fehlerfrei.