natevw / node-nrf

Pure-JavaScript nRF24L01 driver library
117 stars 31 forks source link

Arduino and node-nrf #53

Open maximov-ru opened 8 years ago

maximov-ru commented 8 years ago

Hello! I try connect your library with arduino. I can connect arduino pinpong(mode ping) and raspberry pinpong on C++(mode pong).

Arduino sketch:

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

// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 

RF24 radio(9,10);
const int role_pin = 5;
//
// Topology
//

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes
// in this system.  Doing so greatly simplifies testing.  The hardware itself specifies
// which node it is.
//
// This is done through the role_pin
//

// The various roles supported by this sketch
typedef enum { role_ping_out = 1, role_pong_back } role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};

// The role of the current running sketch
role_e role;

//
// Payload
//

const int min_payload_size = 4;
const int max_payload_size = 32;
const int payload_size_increments_by = 1;
int next_payload_size = min_payload_size;

char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char

void setup(void)
{
  //
  // Role
  //

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

  // read the address pin, establish our role
  if ( digitalRead(role_pin) )
    role = role_ping_out;
  else
    role = role_pong_back;

  //
  // Print preamble
  //

  Serial.begin(115200);

  Serial.println(F("RF24/examples/pingpair_dyn/"));
  Serial.print(F("ROLE: "));
  Serial.println(role_friendly_name[role]);

  //
  // Setup and configure rf radio
  //

  radio.begin();

  // enable dynamic payloads
  radio.enableDynamicPayloads();

  // optionally, increase the delay between retries & # of retries
  radio.setRetries(5,15);

  //
  // Open pipes to other nodes for communication
  //

  // This simple sketch opens two pipes for these two nodes to communicate
  // back and forth.
  // Open 'our' pipe for writing
  // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)

  if ( role == role_ping_out )
  {
    radio.openWritingPipe(pipes[0]);
    radio.openReadingPipe(1,pipes[1]);
  }
  else
  {
    radio.openWritingPipe(pipes[1]);
    radio.openReadingPipe(1,pipes[0]);
  }

  //
  // Start listening
  //

  radio.startListening();

  //
  // Dump the configuration of the rf unit for debugging
  //

  radio.printDetails();
}

void loop(void)
{
  //
  // Ping out role.  Repeatedly send the current time
  //

  if (role == role_ping_out)
  {
    // The payload will always be the same, what will change is how much of it we send.
    static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";

    // First, stop listening so we can talk.
    radio.stopListening();

    // Take the time, and send it.  This will block until complete
    Serial.print(F("Now sending length "));
    Serial.println(next_payload_size);
    radio.write( send_payload, next_payload_size );

    // Now, continue listening
    radio.startListening();

    // Wait here until we get a response, or timeout
    unsigned long started_waiting_at = millis();
    bool timeout = false;
    while ( ! radio.available() && ! timeout )
      if (millis() - started_waiting_at > 500 )
        timeout = true;

    // Describe the results
    if ( timeout )
    {
      Serial.println(F("Failed, response timed out."));
    }
    else
    {
      // Grab the response, compare, and send to debugging spew
      uint8_t len = radio.getDynamicPayloadSize();

      // If a corrupt dynamic payload is received, it will be flushed
      if(!len){
        return; 
      }

      radio.read( receive_payload, len );

      // Put a zero at the end for easy printing
      receive_payload[len] = 0;

      // Spew it
      Serial.print(F("Got response size="));
      Serial.print(len);
      Serial.print(F(" value="));
      Serial.println(receive_payload);
    }

    // Update size for next time.
    next_payload_size += payload_size_increments_by;
    if ( next_payload_size > max_payload_size )
      next_payload_size = min_payload_size;

    // Try again 1s later
    delay(100);
  }

  //
  // Pong back role.  Receive each packet, dump it out, and send it back
  //

  if ( role == role_pong_back )
  {
    // if there is data ready
    while ( radio.available() )
    {

      // Fetch the payload, and see if this was the last one.
      uint8_t len = radio.getDynamicPayloadSize();

      // If a corrupt dynamic payload is received, it will be flushed
      if(!len){
        continue; 
      }

      radio.read( receive_payload, len );

      // Put a zero at the end for easy printing
      receive_payload[len] = 0;

      // Spew it
      Serial.print(F("Got response size="));
      Serial.print(len);
      Serial.print(F(" value="));
      Serial.println(receive_payload);

      // First, stop listening so we can talk
      radio.stopListening();

      // Send the final one back.
      radio.write( receive_payload, len );
      Serial.println(F("Sent response."));

      // Now, resume listening so we catch the next packets.
      radio.startListening();
    }
  }
}

raspberry worked part:

#include <string>
#include <getopt.h>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <RF24/RF24.h>
#include <unistd.h>

using namespace std;
//RF24 radio("/dev/spidev0.0",8000000 , 25);  
//RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);

RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

const int min_payload_size = 4;
const int max_payload_size = 32;
const int payload_size_increments_by = 1;
int next_payload_size = min_payload_size;

char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char

int main(int argc, char** argv){

  bool role_ping_out = 1, role_pong_back = 0;
  bool role = 0;

  // Print preamble:
  cout << "RF24/examples/pingpair_dyn/\n";

  // Setup and configure rf radio
  radio.begin();
  radio.enableDynamicPayloads();
  radio.setRetries(5,15);
  radio.printDetails();

/********* Role chooser ***********/

  printf("\n ************ Role Setup ***********\n");
  string input = "";
  char myChar = {0};
  cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>";
  getline(cin,input);

  if(input.length() == 1) {
    myChar = input[0];
    if(myChar == '0'){
    cout << "Role: Pong Back, awaiting transmission " << endl << endl;
    }else{  cout << "Role: Ping Out, starting transmission " << endl << endl;
    role = role_ping_out;
    }
  }
/***********************************/

    if ( role == role_ping_out )    {
      radio.openWritingPipe(pipes[0]);
      radio.openReadingPipe(1,pipes[1]);
    } else {
      radio.openWritingPipe(pipes[1]);
      radio.openReadingPipe(1,pipes[0]);
      radio.startListening();
    }

// forever loop
    while (1)
    {

if (role == role_ping_out)
  {
    // The payload will always be the same, what will change is how much of it we send.
    static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";

    // First, stop listening so we can talk.
    radio.stopListening();

    // Take the time, and send it.  This will block until complete
    printf("Now sending length %i...",next_payload_size);
    radio.write( send_payload, next_payload_size );

    // Now, continue listening
    radio.startListening();

    // Wait here until we get a response, or timeout
    unsigned long started_waiting_at = millis();
    bool timeout = false;
    while ( ! radio.available() && ! timeout )
      if (millis() - started_waiting_at > 500 )
        timeout = true;

    // Describe the results
    if ( timeout )
    {
      printf("Failed, response timed out.\n\r");
    }
    else
    {
      // Grab the response, compare, and send to debugging spew
      uint8_t len = radio.getDynamicPayloadSize();
      radio.read( receive_payload, len );

      // Put a zero at the end for easy printing
      receive_payload[len] = 0;

      // Spew it
      printf("Got response size=%i value=%s\n\r",len,receive_payload);
    }

    // Update size for next time.
    next_payload_size += payload_size_increments_by;
    if ( next_payload_size > max_payload_size )
      next_payload_size = min_payload_size;

    // Try again 1s later
    delay(100);
  }

  //
  // Pong back role.  Receive each packet, dump it out, and send it back
  //

  if ( role == role_pong_back )
  {
    // if there is data ready
    if ( radio.available() )
    {
      // Dump the payloads until we've gotten everything
      uint8_t len;

      while (radio.available())
      {
        // Fetch the payload, and see if this was the last one.
    len = radio.getDynamicPayloadSize();
    radio.read( receive_payload, len );

    // Put a zero at the end for easy printing
    receive_payload[len] = 0;

    // Spew it
    printf("Got payload size=%i value=%s\n\r",len,receive_payload);
      }

      // First, stop listening so we can talk
      radio.stopListening();

      // Send the final one back.
      radio.write( receive_payload, len );
      printf("Sent response.\n\r");

      // Now, resume listening so we catch the next packets.
      radio.startListening();
    }
  }
}
}

on Raspberry pi and put this:

RF24/examples/pingpair_dyn/
================ SPI Configuration ================
CSN Pin      = CE0 (PI Hardware Driven)
CE Pin       = Custom GPIO25
Clock Speed  = 8 Mhz
================ NRF Configuration ================
STATUS       = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1     = 0xe7e7e7e7e7 0xc2c2c2c2c2
RX_ADDR_P2-5     = 0xc3 0xc4 0xc5 0xc6
TX_ADDR      = 0xe7e7e7e7e7
RX_PW_P0-6   = 0x00 0x00 0x00 0x00 0x00 0x00
EN_AA        = 0x3f
EN_RXADDR    = 0x03
RF_CH        = 0x4c
RF_SETUP     = 0x07
CONFIG       = 0x0e
DYNPD/FEATURE    = 0x3f 0x04
Data Rate    = 1MBPS
Model        = nRF24L01+
CRC Length   = 16 bits
PA Power     = PA_MAX

 ************ Role Setup ***********
Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) 
>0
Role: Pong Back, awaiting transmission 

Got payload size=24 value=ABCDEFGHIJKLMNOPQRSTUVWX
Sent response.
Got payload size=25 value=ABCDEFGHIJKLMNOPQRSTUVWXY
Sent response.
Got payload size=26 value=ABCDEFGHIJKLMNOPQRSTUVWXYZ
Sent response.
Got payload size=27 value=ABCDEFGHIJKLMNOPQRSTUVWXYZ7
Sent response.
Got payload size=28 value=ABCDEFGHIJKLMNOPQRSTUVWXYZ78
Sent response.
Got payload size=29 value=ABCDEFGHIJKLMNOPQRSTUVWXYZ789
Sent response.
Got payload size=30 value=ABCDEFGHIJKLMNOPQRSTUVWXYZ7890
Sent response.
Got payload size=31 value=ABCDEFGHIJKLMNOPQRSTUVWXYZ78901
Sent response.
Got payload size=32 value=ABCDEFGHIJKLMNOPQRSTUVWXYZ789012
Sent response.

And I have example with your library:

var NRF24 = require("nrf"),
    queue = require('queue-async');
var pipes = [0xF0F0F0F0E1, 0xF0F0F0F0D2];
var radiocfg = {spiDev:"/dev/spidev0.0", cePin:25};
var radio = NRF24.connect(radiocfg.spiDev, radiocfg.cePin);
try {
    radio._debug = false;
    radio.dataRate('1Mbps').crcBytes(2);
    radio.transmitPower('PA_MAX').autoRetransmit({count:5, delay:4000});
    //radio.setStates({DYNPD:0x00, FEATURE:0x00,EN_DPL:0});

    radio.begin(function (e) {
        var rx = radio.openPipe('rx', pipes[0],{size: 'auto',autoAck:false}),
            tx = radio.openPipe('tx', pipes[1],{size: 'auto',autoAck:false});
        //radio.setStates({DYNPD:0x00, FEATURE:0x00,EN_DPL:0});
        tx.on('ready', function () {
            radio.printDetails();
            var buf = new Uint32Array(1);
            buf[0] = 81;
            var ret = 'hz';
            try {
                ret = tx.write(new Buffer(buf));
            }catch(e) {
               console.log('=((');
            }
            console.log('myret',ret);
            if(ret === true){
                //tx.
            }
            //tx.write("Hello?");
            //tx.write("blah blah blah");
            //tx.write("the number 4");
            //setInterval(tx.write.bind(tx, "beep"), 2e3);
            //setInterval(tx.write.bind(tx, "boop"), 2e3);
        });
        tx.on('error',function(e){
            console.log('err',e);
        });

        rx.on('data', function (d) {
            console.log("Got data:", d.toString());
        });
        rx.on('error',function(e){
            console.log('err2',e);
        });
    });
}catch(e) {
    console.log('hm....');

that out:

Recommend use with IRQ pin, fallback handling is suboptimal.
SPI device:  /dev/spidev0.0
CE GPIO:     25
IRQ GPIO:    undefined
myret true
STATUS:      0xe RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0–1:  0xf0f0f0f0d2 0xf0f0f0f0e1
RX_ADDR_P2–5:  0xc3 0xc4 0xc5 0xc6
TX_ADDR:     0xf0f0f0f0d2
RX_PW_P0–5:    0x20 0x20 0x0 0x0 0x0 0x0
EN_AA:       0x3f
EN_RXADDR:   0x02
RF_CH:       0x4c
RF_SETUP:    0x07
CONFIG:      0x0e
DYNPD/FEATURE:   0x3f 0x07
Data Rate:   1Mbps
Model:       nRF24L01+
CRC Length:  16 bits
PA Power:    PA_MAX
Got data: UTSRQPONMLKJIHGFEDCBA
Got data: UUUUUUUUUUUUUUUUUUUUU
Got data: VUTSRQPONMLKJIHGFEDCBA
Got data: VVVVVVVVVVVVVVVVVVVVVV
Got data: WVUTSRQPONMLKJIHGFEDCBA
Got data: WWWWWWWWWWWWWWWWWWWWWWW
Got data: XWVUTSRQPONMLKJIHGFEDCBA
Got data: XXXXXXXXXXXXXXXXXXXXXXXX
Got data: YXWVUTSRQPONMLKJIHGFEDCBA
Got data: YYYYYYYYYYYYYYYYYYYYYYYYY
Got data: ZYXWVUTSRQPONMLKJIHGFEDCBA
Got data: ZZZZZZZZZZZZZZZZZZZZZZZZZZ

I see all packets reverted, and next packet have some length but filled by last char. What I to do wrong?

Vuurbaard commented 8 years ago

What I did was to switch the buffer you send and receive on the Raspberry Pi like this:

Array.prototype.reverse.call(buffer);