Arduino NRF24L01 application instance (32Bytes)

Application example of Arduino(NANO) NRF24L01

Software preparation:
microBox Library( https://github.com/wastel7/microBox ): build a mini command line system
Mirf Library ( https://github.com/E-elektronic/Mirf ): provide RF related core functions
Please download the above library by yourself

Hardware preparation:
Arduino NANO plate x 2; NRF24L01 x 2; Other;

Development environment:
VS2017 + Arduino IDE(1.8.4)

Hardware connection:

The connection mode of Server, Client and NRF24L01 module is the same. Wiring sequence: VCC:3.3V; GND:GND; CSN: 7; CE:8; MOSI:11; SCK:13; IRQ: not connected; MISO:12;

Be careful:
1. The Microbox library needs to be modified to test this example. The modifications are as follows:
microBox.h:
#Define max? CMD? Num 128 / / set the appropriate value to accept the input correctly
#Define max? CMD? Buf? Size 128 / / set as needed
2. After a simple performance test, the routine can send and receive at most 50ms (send 32Byte and receive 32Byte)
3. In some cases, it may fail to send. After testing, it is found that it is the problem of the Client side. Solution: reset the Client side, and now provide the "reset" instruction to support soft reset

Client code (client.ino):

#include "microBox.h"

#pragma region UserDefined
//#define DEBUG
#undef  DEBUG

#ifndef ADD_RF
#define ADD_RF
#endif // !ADD_RF

#ifdef ADD_RF
/*
 * Hardware SPI:
 * MISO -> 12
 * MOSI -> 11
 * SCK -> 13
 *
 * Configurable:
 * CE -> 8
 * CSN -> 7
*/
#include <SPI.h>
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"

#define ulong   unsigned long 
#define dword   ulong 
uint8_t code[32] = { 0 };

void(*ResetInternal) (void) = 0;

//CRC-8, Widh:8, Poly:0x07, Init: 0x00
//RefIn:False, RefOut:False, XorOut:0x00
byte CalcCRC8(byte * pdata, unsigned int len)
{
    byte crc = 0x00;

    for (int i = 0; i < len; i++)
    {
        crc ^= ((*pdata++) & 0xFF);
        for (byte j = 0; j < 8; j++)
        {
            if (crc & 0x80)
            {
                crc <<= 1;
                crc ^= 0x07;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    return crc;
}

bool RfSend_Internal(uint8_t * data)
{
    int i = 0;
    unsigned long time = millis();
    byte crc = CalcCRC8(data, 32);

    Serial.print("cmd: ");
    for (i=0;i<32;i++)
    {
        (data[i] < 0x10) ? Serial.print(0) : i;
        Serial.print(data[i], HEX);
        (i==31)? Serial.println(""):Serial.print("  ");
    }
    Mirf.send(data);
    while (Mirf.isSending()) 
    {
        if ((millis() - time) > 2000)
        {
            Serial.println("timeout on send cmd!");
            return false;
        }
    }
    while (!Mirf.dataReady())
    {
        if ((millis() - time) > 2000)
        {
            Serial.println("timeout on response from server!");
            return false;
        }
    }
    Mirf.getData(data);
    Serial.print("ack: ");
    for (i = 0; i < 32; i++)
    {
        (data[i] < 0x10) ? Serial.print(0) : i;
        Serial.print(data[i], HEX);
        (i==31)? Serial.println(""):Serial.print("  ");
    }

    Serial.print("result: ");
    if (crc == data[0])
        Serial.println("succ");
    else
        Serial.println("fail");
}

void RfSend(char **param, uint8_t parCnt)
{
    if (parCnt == 8)
    {
        ulong uli[8];
        for (int i=0; i < 8; i++)
        {
            uli[i] = strtoul(param[i], 0, 16);
            code[3 + i * 4] = (uint8_t)(uli[i] & 0xff);
            code[2 + i * 4] = (uint8_t)((uli[i] & 0xff00) >> 8);
            code[1 + i * 4] = (uint8_t)((uli[i] & 0xff0000) >> 16);
            code[0 + i * 4] = (uint8_t)((uli[i] & 0xff000000) >> 24);
        }
        RfSend_Internal(code);
    }
    else
        Serial.println(F("Usage: rf-send hex-code(8 dwords), eg: rf-send 01020304 05060708 090A0B0C 0D0E0F10 11121314 15161718 191A1B1C 1D1E1F20"));
}

void Reset(char **param, uint8_t parCnt)
{
    ResetInternal();
}

void UsrInit()
{
    Mirf.spi = &MirfHardwareSpi;
    Mirf.init();
    Mirf.setRADDR((byte *)"sndr0");
    Mirf.setTADDR((byte *)"serv0");
    Mirf.payload = 32;
    //Mirf.channel = 10;
    Mirf.config();
}
#endif // ADD_RF
#pragma endregion

#pragma region InternalFunc
char historyBuf[100];
char hostname[] = "tdxk";

PARAM_ENTRY Params[] =
{
  {"hostname", hostname, PARTYPE_STRING | PARTYPE_RW, sizeof(hostname), NULL, NULL, 0},
  {NULL, NULL}
};

void getMillis(char **param, uint8_t parCnt)
{
    Serial.println(millis());
}

void freeRam(char **param, uint8_t parCnt)
{
    extern int __heap_start, *__brkval;
    int v;
    Serial.println((int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval));
}

void writePin(char **param, uint8_t parCnt)
{
    uint8_t pin, pinval;
    if (parCnt == 2)
    {
        pin = atoi(param[0]);
        pinval = atoi(param[1]);
        digitalWrite(pin, pinval);
    }
    else
        Serial.println(F("Usage: writepin pinNum pinvalue"));
}

void readPin(char **param, uint8_t parCnt)
{
    uint8_t pin;
    if (parCnt == 1)
    {
        pin = atoi(param[0]);
        Serial.println(digitalRead(pin));
    }
    else
        Serial.println(F("Usage: readpin pinNum"));
}

void setPinDirection(char **param, uint8_t parCnt)
{
    uint8_t pin, pindir;
    if (parCnt == 2)
    {
        pin = atoi(param[0]);
        if (strcmp(param[1], "out") == 0)
            pindir = OUTPUT;
        else
            pindir = INPUT;

        pinMode(pin, pindir);
    }
    else
        Serial.println(F("Usage: setpindir pinNum in|out"));
}

void readAnalogPin(char **param, uint8_t parCnt)
{
    uint8_t pin;
    if (parCnt == 1)
    {
        pin = atoi(param[0]);
        Serial.println(analogRead(pin));
    }
    else
        Serial.println(F("Usage: readanalog pinNum"));
}

void writeAnalogPin(char **param, uint8_t parCnt)
{
    uint8_t pin, pinval;
    if (parCnt == 2)
    {
        pin = atoi(param[0]);
        pinval = atoi(param[1]);
        analogWrite(pin, pinval);
    }
    else
        Serial.println(F("Usage: writeanalog pinNum pinvalue"));
}
#pragma endregion

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

  microbox.begin(&Params[0], hostname, true, historyBuf, 100);
  microbox.AddCommand("free", freeRam);
  microbox.AddCommand("millis", getMillis);
  microbox.AddCommand("readanalog", readAnalogPin);
  microbox.AddCommand("readpin", readPin);
  microbox.AddCommand("setpindir", setPinDirection);
  microbox.AddCommand("writeanalog", writeAnalogPin);
  microbox.AddCommand("writepin", writePin);

#ifdef ADD_RF
  UsrInit();
  microbox.AddCommand("rf-send", RfSend);
  microbox.AddCommand("reset", Reset);
#endif // ADD_RF
}

void loop()
{ 
  microbox.cmdParser();
}

Server code (Server.ino):

/**
 * An Mirf example which copies back the data it recives.
 *
 * Pins:
 * Hardware SPI:
 * MISO -> 12
 * MOSI -> 11
 * SCK -> 13
 *
 * Configurable:
 * CE -> 8
 * CSN -> 7
 *
 */

#include <SPI.h>
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"

#define DEBUG
//#undef    DEBUG

#define ulong       unsigned long
#define dword       ulong
#define SEND_DATA(dw1,dw2,dw3,dw4,dw5, dw6, dw7, dw8)   {SendData((dword)(dw1),(dword)(dw2),(dword)(dw3),(dword)(dw4),(dword)(dw5),(dword)(dw6),(dword)(dw7),(dword)(dw8));Mirf.send(data); }

//FLAG
#define ACK_OK      0xE0
#define ACK_NG      0xE1
#define ACK_ERROR   0xE2

byte data[32];
byte checksum;
ulong ulCode[8] = {0};

//CRC-8, Widh:8, Poly:0x07, Init: 0x00
//RefIn:False, RefOut:False, XorOut:0x00
byte CalcCRC8(byte * pdata, unsigned int len)
{
    byte crc = 0x00;

    for (int i = 0; i < len; i++)
    {
        crc ^= ((*pdata++) & 0xFF);
        for (byte j = 0; j < 8; j++)
        {
            if (crc & 0x80)
            {
                crc <<= 1;
                crc ^= 0x07;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    return crc;
}

void SendData(dword dw1, dword dw2, dword dw3, dword dw4, dword dw5, dword dw6, dword dw7, dword dw8)
{
    int i = 0;
    dword dwData[8] = { dw1, dw2, dw3, dw4, dw5, dw6, dw7, dw8};
    for (i = 0; i < 8; i++)
    {
        data[3 + i * 4] = (uint8_t)(dwData[i] & 0xff);
        data[2 + i * 4] = (uint8_t)((dwData[i] & 0xff00) >> 8);
        data[1 + i * 4] = (uint8_t)((dwData[i] & 0xff0000) >> 16);
        data[0 + i * 4] = (uint8_t)((dwData[i] & 0xff000000) >> 24);
    }

    Serial.print("ack: ");
    for (i = 0; i < 32; i++)
    {
        (data[i] < 0x10) ? Serial.print(0) : i;
        Serial.print(data[i], HEX);
        (i == 31) ? Serial.println("") : Serial.print("  ");
    }

}

void setup()
{
    Serial.begin(115200);
    Mirf.spi = &MirfHardwareSpi;
    Mirf.init();
    Mirf.setRADDR((byte *)"serv0"); //serv0
    Mirf.payload = 32;
    Mirf.config();
    Serial.println("Listening..."); 
}

void loop()
{
    int i = 0;

    if (!Mirf.isSending() && Mirf.dataReady())
    {
        Mirf.getData(data);
        Serial.print("cmd: ");
        for (i=0;i<32;i++)
        {
            (data[i] < 0x10) ? Serial.print(0) : i;
            Serial.print(data[i], HEX);
            (i==31)? Serial.println(""):Serial.print("  ");
        }
        Mirf.setTADDR((byte *)"sndr0"); //sndr0
        for (i=0;i<8;i++)
        {
            ulCode[i] = (unsigned long)((unsigned long)data[0 + i * 4] << 24 | (unsigned long)data[1 + i * 4] << 16 | (unsigned long)data[2 + i * 4] << 8 | data[3 + i * 4]);
        }
        checksum = CalcCRC8(data, 32);
        switch (ulCode[0])
        {
        case 0x00000000:
            SEND_DATA(((dword)checksum << 24) + ACK_OK, 0, 0, 0, 0, 0, 0, 0);
            break;
        case 0x00000001:
            SEND_DATA(((dword)checksum << 24) + ACK_OK, 0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10, 0x11121314, 0x15161718, 0x191A1B1C);
            break;
        case 0x00000002:
            SEND_DATA(((dword)checksum << 24) + ACK_OK, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678);
            break;
        default:
            SEND_DATA(((dword)checksum << 24) + ACK_ERROR, 0, 0, 0, 0, 0, 0, 0);
            break;
        }
    }
}

Test diagram:


Keywords: C++ github

Added by mwl707 on Sun, 10 Nov 2019 22:38:02 +0200