Go Down

Topic: Hat jemand von euch NRF24L01+ zum laufen gebracht? (Read 11957 times) previous topic - next topic

KUCKY

Ich bin nun dahinter gekommen, warum der NRF24 manchmal den Geist aufgibt. Es lag an der Stromversorgung. Obwohl er lt. Datenblatt nur max 15mA benötigt, muss die Stromversorgung etwas mehr bereithalten. Mit einen extern 3.3V Supply und einem zusätzlich 10uF ist das Problem behoben.
Nun habe ich aber ein anderes Problem. Lt Datenblatt kann ich bis zu 32Byte übertragen. Wenn ich mein Datenarray auf 4 int Values (8Byte) beschränke, ist alles OK. Ab 5 streikt der Empfänger. D.h. es wird kein Interrupt, bzw. gerade noch einer ausgelöst. Ich habe es auch mit einer Struktur versucht, was viel besser wäre, aber auch kein Erfolg.

Code: [Select]

typedef struct __attribute__((__packed__)) { Sender und Empfänger
uint16_t throttle;
int8_t yaw;
int8_t pitch;
int8_t roll;
int16_t checkSum;
} rx_values_t;

rxvalues_t rxValues;

----------------------------------------------------------------

Sender

rxValues.throttle = analogread(A0);
rxValues.yaw = analogread(A1);
rxValues.pitch = analogread(A2);
rxValues.roll = analogread(A3);

rxValues.checkSum = (rxValues.throttle*2) + (rxValues.yaw*3) + (rxValues.pitch*4) + (rxValues.roll*5);

....

  if (role == role_sender)
  {
        radio.powerUp() ;
    radio.startWrite( &rxValues, sizeof(rxValues_t) );

  }


----------------------------------------------------------------

Emfänger

    if ( role == role_receiver )
    {
      radio.read( &rxValues, sizeof(rxValues_t) ); Geht nur mit "&" Opperator
     
      // Add an ack packet for the next time around.  This is a simple
      // packet counter
      radio.writeAckPayload( 1, &message_count, sizeof(message_count) );
      ++message_count;
    }

if(((rxValues.throttle*2) + (rxValues.yaw*3) + (rxValues.pitch*4) + (rxValues.roll*5)) == rxValues.ceckSum) {
   received = OK;
}



Gruß Kucky

combie

Leider sieht man nicht, was du da einstellst......

Meine Glaskugel sagt:
Code: [Select]
radio.setRetries(15,15);
könnte dein Problem beheben.

Aber wie gesagt, alles im Glaskugelmodus.
;)
Gefährlich, was Theorien aus Menschen machen können.
Schlimmer, was Menschen aus Theorien machen.

KUCKY

Danke für die Antwort,
aber sind diese Werte nicht optional?
Ich hätte eher gedacht "radio.setPayloadSize-8".  Aber den habe ich auch nicht gesetzt. Aber hier mal mein Code, der funktioniert:

Sender
Code: [Select]

/*
Transmitter for Quadrocopter
based on Arduino Mini Pro (328p 5v 16MHz)

write to an 9 channel RC

*/

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

#define NANO328

// sets the role of this unit in hardware.  Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter

#ifdef NANO328
// Nano 328
RF24 radio(9,10);
const short role_pin = 9;
#else
//MEGA2560
RF24 radio(46, 53);
const short role_pin = 41;
#endif

const uint64_t pipe = 0xE8E8F0F0E1LL;

typedef enum { role_sender = 1, role_receiver } role_e;

const char* role_friendly_name[] = { "invalid", "Sender", "Empfaenger" };

role_e role;
static uint32_t message_count = 0;

#define NUM_TXDATA 4
int tx_data[NUM_TXDATA];
const uint8_t readPin[NUM_TXDATA] = {A0, A1, A2, A3};   /// Yaw, Pitch, Roll, Throttle

//--------------------------- end of declration and initialisations--------------------------------

void setup(void)
{
  pinMode(role_pin, INPUT);
  digitalWrite(role_pin,HIGH);
  delay(20); // Just to get a solid reading on the role pin

  if ( digitalRead(role_pin) )
    role = role_sender;
  else
    role = role_receiver;

  Serial.begin(115200);
  printf_begin();
  printf("\n\rQuad_Transmitter/\n\r");
  printf("ROLE: %s\n\r",role_friendly_name[role]);

  radio.begin();

  radio.enableAckPayload();

  if ( role == role_sender ) {
    radio.openWritingPipe(pipe);
  }
  else {
    radio.openReadingPipe(1,pipe);
  }

  if ( role == role_receiver )
    radio.startListening();

  radio.printDetails();

  attachInterrupt(1, check_radio, FALLING);
}
//--------------------------- end of setup ------------------------------------

void loop(void)  {

tx_data[0] = map(analogRead(readPin[0]), 189, 898, -600, 600); ///< 1/10°  to set setpoint Yaw
tx_data[1] = map(analogRead(readPin[1]), 141, 839, -600, 600); ///< Pitch
tx_data[2] = map(analogRead(readPin[2]), 141, 866, -600, 600); ///< Roll

tx_data[3] = map(analogRead(readPin[3]), 176, 872, 1000 , 2000); ///< Throttle

  if (role == role_sender)
  {
    printf("Now sending data  %i %i %i %i \n\r",tx_data[0], tx_data[1], tx_data[2], tx_data[3]);
    radio.powerUp() ;
    radio.startWrite( tx_data, sizeof(tx_data) );

    delay(100);
  }
  // Receiver role: Does nothing!  All the work is in IR
}
//--------------------------- end of mainloop -----------------------------------------------------

void check_radio(void)  {

  bool tx,fail,rx;
  radio.whatHappened(tx,fail,rx);

  if ( tx )  {
    if ( role == role_sender )
      printf("Send: OK\n\r");

    if ( role == role_receiver )
      printf("Ack Payload: Sent\n\r");
  }

  if ( fail )  {
    if ( role == role_sender )
      printf("Send: Failed\n\r");

    if ( role == role_receiver )
      printf("Ack Payload: Failed\n\r");
  }

  if ( ( tx || fail ) && ( role == role_sender ) )
    radio.powerDown();

  if ( rx )  {
    if ( role == role_sender )  {
      radio.read(&message_count,sizeof(message_count));
      printf("Ack: %lu\n\r",message_count);
    }

    if ( role == role_receiver )  {
      radio.read( tx_data, sizeof(tx_data) );
      printf("Got payload %i %i %i %i n\r",tx_data[0], tx_data[1], tx_data[2], tx_data[3]);

      radio.writeAckPayload( 1, &message_count, sizeof(message_count) );
      ++message_count;
    }
  }
}
//--------------------------- end of check_radio --------------------------------------------------

/*-------------------------------- end of Quad_Transmitter --------------------------------------*/


Empfänger
Code: [Select]

//
//
//

#include "RC.h"
#include "RF24.h"

#ifdef NANO328
// Nano 328
RF24 radio(9,10);
const short role_pin = 9;
#else
//MEGA2560
RF24 radio(46, 53);

#endif

role_e role;

//--------------------------- end of initialation ans declaration ---------------------------------
void RCClass::init() {

  short role_pin = ROLE_PIN;
  pinMode(role_pin, INPUT);
  digitalWrite(role_pin,HIGH);
  delay(20); // Just to get a solid reading on the role pin

  uint64_t pipe = PIPE;
  const char* role_friendly_name[] = { "invalid", "Sender", "Empfaenger" };

  int tx_data[NUM_TXDATA];
  const uint8_t readPin[] = {A0, A1, A2, A3};   /// Yaw, Pitch, Roll, Throttle
  static uint32_t message_count = 0;

  if ( digitalRead(role_pin) )
    role = role_transmitter;
  else
    role = role_receiver;

    printf("\n\rQuad_Receiver /\n\r");
    printf("ROLE: %s\n\r",role_friendly_name[role]);

    radio.begin();
    radio.enableAckPayload();

  if ( role == role_transmitter ) 
radio.openWritingPipe(pipe);
  else
radio.openReadingPipe(1,pipe);

  if ( role == role_receiver )
radio.startListening();

  radio.printDetails();
}
//--------------------------- end of init ---------------------------------------------------------

void RCClass::check_radio(void)  {     /// Wird vom Interrupt aus Startprogramm aufgerufen

  bool tx,fail,rx;
  radio.whatHappened(tx,fail,rx);

  if ( tx )  {
    if ( role == role_transmitter )
      printf("Send: OK\n\r");

    if ( role == role_receiver )
      printf("Ack Payload: Sent\n\r");
  }

  if ( fail )  {
    if ( role == role_transmitter )
      printf("Send: Failed\n\r");

    if ( role == role_receiver )
      printf("Ack Payload: Failed\n\r");
  }

  if ( ( tx || fail ) && ( role == role_transmitter ) )
    radio.powerDown();

  if ( rx )  {
    if ( role == role_transmitter )  {
      radio.read(&message_count,sizeof(message_count));
      printf("Ack: %lu\n\r",message_count);
    }

    if ( role == role_receiver )  {
      radio.read( tx_data, sizeof(tx_data) );
      printf("Got payload %i %i %i %i ",tx_data[0], tx_data[1], tx_data[2], tx_data[3]);
  printf("  Ack send %i \n\r",message_count);
      radio.writeAckPayload( 1, &message_count, sizeof(message_count) );
      ++message_count;
    }
  }
}
//--------------------------- end of check_radio --------------------------------------------------
RCClass RC;
/*--------------------------- end of RCclass ----------------------------------------------------*/


Main Empfänger
Code: [Select]

/*
Receiver modul for Quadrocopter
based on Arduino Mini Pro (328p 5v 16MHz)

read an 9 channel RC

*/

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

#include "RC.h"

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

void read_RC(void);
//-----------------------------------------------------------------------------

void setup(void)  {

  Serial.begin(115200);
  printf_begin();

  RC.init();

  attachInterrupt(1, read_RC, FALLING);
}
//--------------------------- end of setup --------------------------------------------------------

void loop(void) {
  // loop is empty
}
//--------------------------- end of mainloop -----------------------------------------------------

void read_RC() {
RC.check_radio();
}
//--------------------------- end of read_RC -----------------------------------------------------
/*--------------------------- end of Quad_Receiver ----------------------------------------------*/


Ich hoffe, ich habe nicht zu viel Mühe gemacht. Ich habe hier
http://www.daedalus.ei.tum.de/index.php/de/zeppelin/blimp/gamepad-dms2-funkverbindung

folgendes gelesen :
"
Der erste Modus ist der Normale-Modus indem die Stickwerte verschickt werden, in dem Normalen-Modus werden permanent Pakete mit den zugehörigen Stickwerten verschickt. Dazu werden die Stickwerte codiert, sodass pro Stickwert 2Bytes gebraucht werden. Im gesendeten Paket stehen die Stickwerte somit vom 1. bis 8. Byte. Der 9.Byte hat den Wert Null. Im empfänger werden die Stickwerte anschließend wieder decodiert.
"
Ist das richtig, dass ich nur Byte senden kann? Kann ich mir nicht vorstellen.

Gruß Kucky


combie

Quote
aber sind diese Werte nicht optional?

Durchaus...
Aber da deine Verwendung des "Ack Payload" den üblichen (Zeit)Rahmen sprengt, könntest du es damit mal versuchen...

Quote
Ist das richtig, dass ich nur Byte senden kann? Kann ich mir nicht vorstellen.

Du kannst alles senden, Hauptsache es passt in deine PayloadSize!
Also
32 byte
12 int
usw....
Das Funkmodul kennt keine Datentypen.
Gefährlich, was Theorien aus Menschen machen können.
Schlimmer, was Menschen aus Theorien machen.

KUCKY

Jau das war es. Vielen Dank. Auch der Hinweis zu Ack Payload. Ab 999 hing das Programm wieder.

Gruß Willi

combie

Schön!
Dann kann ich ja mit mir und meiner Glaskugel recht zufrieden sein.
Gefährlich, was Theorien aus Menschen machen können.
Schlimmer, was Menschen aus Theorien machen.

KUCKY

Hallo,
nun funktioniert (fast) alles.

Ich habe folgende Struktur auf beiden Seiten:
Code: [Select]

typedef struct __attribute__((__packed__)) {
  uint16_t throttle;
  int16_t yaw;
  int16_t pitch;
  int16_t roll;
  uint8_t switch1;
  uint8_t switch2;
  uint8_t switch3;
//  uint8_t switch4;
//  uint8_t switch5;
  uint16_t checksum;
} rxValues_t;

Paylodsize(13);

Übertragung wie auf Bild "OK" zu sehen.

Wenn ich aber einen Wert (switch4) hinzu nehme und die Payloadsize auf 14 erhöhe, stockt der Empfang (Bild "NichtOK"). Ich vermute, es liegt an der Payloadsize und speziell an der "checksum". Was mache ich falsch?

Code: [Select]

rxValues.checksum = (rxValues.yaw*2) + (rxValues.pitch*3) + (rxValues.roll*4) + (rxValues.throttle*5);


Gruß
Willi

KUCKY

Es liegt tatsälich an der checksum. Ist ein uint16_t mit 2 Byte. Habe ich so berechnet.

Code: [Select]

rxValues.checksum = (rxValues.yaw*2) + (rxValues.pitch*3) + (rxValues.roll*4) + (rxValues.throttle*5);

KUCKY

erledigt, es lag an dem typ. Mit int16_t ist alles in Butter. Hätte ich auch früher drauf kommen können. :smiley-roll-sweat:
Gruß
Willi

KUCKY

Ich habe noch 2 Fragen zu "Ack Payload" und "radio.setRetries(15,15)". Du sagst, das AckPayload zeitintensiv ist. Habe ich das richtig verstanden habe, und dies ist eine einfache Kontrolle über das was gesendet/empfangen wurde, und ich das mit einer Checksumme schneller prüfen kann?
Was macht eigentlich "radio.setRetries(15,15)" außer das mein Programm innerhalb von setup bzw. init einfriert? Gehören die 2 zusammen. Ich habe die Doku gelesen aber nicht verstanden.

Gruß Willi

Go Up