Arduino NRF24L01 应用实例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Arduino NRF24L01 应用实例相关的知识,希望对你有一定的参考价值。

Arduino(NANO) NRF24L01 应用实例

软件准备:
microBox 库(https://github.com/wastel7/microBox):构建一个微型的命令行系统
Mirf 库(https://github.com/E-elektronic/Mirf):提供RF相关的核心功能
以上库请自行下载

硬件准备:
Arduino NANO板 x 2; NRF24L01 x 2; Other;

开发环境:
VS2017 + Arduino IDE(1.8.4)

硬件连接:
技术分享图片
Server、Client 与 NRF24L01模块的连接方式完全相同。接线次序:VCC:3.3V; GND:GND; CSN: 7; CE:8; MOSI:11; SCK:13; IRQ:不接; MISO:12;

Client 代码(client.ino):

#include "microBox.h"

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

#ifndef FIRSWOF_ADD
#define FIRSWOF_ADD
#endif // !FIRSWOF_ADD

#ifdef FIRSWOF_ADD
/*
 * 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"

//LED
#define RED_LED_PIN         2
#define GREEN_LED_PIN       3
#define BLUE_LED_PIN        4
#define LED_TRIGGER         HIGH

//BEEP
#define BEEP_PIN            5
#define BEEP_TRIGGER        LOW

uint8_t code[4] = { 0 };

void RedLedLight()
{
    digitalWrite(RED_LED_PIN, LED_TRIGGER);
    delay(50);
    digitalWrite(RED_LED_PIN, !LED_TRIGGER);
}

void GreenLedLight()
{
    digitalWrite(GREEN_LED_PIN, LED_TRIGGER);
    delay(50);
    digitalWrite(GREEN_LED_PIN, !LED_TRIGGER);
}

bool RfSend_Internal(uint8_t * data)
{
    unsigned long time = millis();

    Serial.print("cmd: ");
    Serial.print(data[0], HEX);
    Serial.print(" ");
    Serial.print(data[1], HEX);
    Serial.print(" ");
    Serial.print(data[2], HEX);
    Serial.print(" ");
    Serial.println(data[3], HEX);
    Mirf.setTADDR((byte *)"serv0");
    Mirf.send(data);
    while (Mirf.isSending()) 
    {
        if ((millis() - time) > 2000)
        {
            RedLedLight();
            Serial.println("timeout on send cmd!");
            return false;
        }
    }
    delay(10);
    while (!Mirf.dataReady())
    {
        if ((millis() - time) > 2000)
        {
            RedLedLight();
            Serial.println("timeout on response from server!");
            return false;
        }
    }
    GreenLedLight();
    Mirf.getData(data);
    Serial.print("ack: ");
    Serial.print(data[0], HEX);
    Serial.print(" ");
    Serial.print(data[1], HEX);
    Serial.print(" ");
    Serial.print(data[2], HEX);
    Serial.print(" ");
    Serial.println(data[3], HEX);
}

void RfSend(char **param, uint8_t parCnt)
{
    if (parCnt == 1)
    {
        unsigned long uli = strtoul(param[0], 0, 16);
        code[3] = (uint8_t)(uli & 0xff);
        code[2] = (uint8_t)((uli & 0xff00)>>8);
        code[1] = (uint8_t)((uli & 0xff0000)>>16);
        code[0] = (uint8_t)((uli & 0xff000000)>>24);
        RfSend_Internal(code);
    }
    else
        Serial.println(F("Usage: rf-send hex-code(4 bytes), eg: rf-send AABBCCDD"));
}

void Test(char **param, uint8_t parCnt)
{
    if (parCnt == 0)
    {
        ;
    }
    else
        Serial.println(F("Usage: test"));
}

void UsrInit()
{
    pinMode(RED_LED_PIN, OUTPUT);
    pinMode(GREEN_LED_PIN, OUTPUT);
    pinMode(BLUE_LED_PIN, OUTPUT);
    digitalWrite(RED_LED_PIN, !LED_TRIGGER);
    digitalWrite(GREEN_LED_PIN, !LED_TRIGGER);
    digitalWrite(BLUE_LED_PIN, !LED_TRIGGER);

    Mirf.spi = &MirfHardwareSpi;
    Mirf.init();
    Mirf.setRADDR((byte *)"sndr0");
    Mirf.payload = sizeof(unsigned long);   //size:4
    //Mirf.channel = 10;
    Mirf.config();
}
#endif // FIRSWOF_ADD
#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 FIRSWOF_ADD
  UsrInit();
  microbox.AddCommand("test", Test);
  microbox.AddCommand("rf-send", RfSend);
#endif // FIRSWOF_ADD
}

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

Server 代码(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 BEEP_PIN        2
#define BEEP_TRIGGER    LOW
#define CHECKSUM        data[0]
#define DATA_SET_INTERNAL(x,y,m,n)  {/*data[0]=(uint8_t)x;*/data[1]=(uint8_t)y;data[2]=(uint8_t)m;data[3]=(uint8_t)n;}
#define SEND_DATA(x,y,m,n) {DATA_SET_INTERNAL(x,y,m,n);Serial.print("ack: ");Serial.print(data[0], HEX);Serial.print("  ");Serial.print(data[1], HEX);Serial.print("  ");Serial.print(data[2], HEX);Serial.print("  ");Serial.println(data[3], HEX);Mirf.send(data); }

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

unsigned long ulCode = 0ul;

void beep()
{
    digitalWrite(BEEP_PIN, BEEP_TRIGGER);
    delay(10);
    digitalWrite(BEEP_PIN, !BEEP_TRIGGER);
}

//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 setup()
{
    pinMode(BEEP_PIN, OUTPUT);
    digitalWrite(BEEP_PIN, !BEEP_TRIGGER);
    Serial.begin(115200);
    Mirf.spi = &MirfHardwareSpi;
    Mirf.init();
    Mirf.setRADDR((byte *)"serv0");
    Mirf.payload = sizeof(unsigned long);
    Mirf.config();
    Serial.println("Listening..."); 
}

void loop()
{
    byte data[Mirf.payload];
    if (!Mirf.isSending() && Mirf.dataReady())
    {
        Mirf.getData(data);
        Serial.print("cmd: ");
        Serial.print(data[0], HEX);
        Serial.print("  ");
        Serial.print(data[1], HEX);
        Serial.print("  ");
        Serial.print(data[2], HEX);
        Serial.print("  ");
        Serial.println(data[3], HEX);
        Mirf.setTADDR((byte *)"sndr0");
        beep();
        ulCode = (unsigned long)((unsigned long)data[0]<<24|(unsigned long)data[1]<<16|(unsigned long)data[2]<<8|data[3]);
        CHECKSUM = CalcCRC8(data, Mirf.payload);
        switch (ulCode)
        {
        case 0x000000:
            SEND_DATA(CHECKSUM, ACK_OK, 0, 0);
            Serial.println("[case 0x000000]");
            break;
        case 0x00112233:
            SEND_DATA(CHECKSUM, ACK_OK, 0, 0);
            Serial.println("[case 0x00112233]");
            break;
        default:
            SEND_DATA(CHECKSUM, ACK_NG, 0, 0);
            Serial.println("[case default]");
            break;
        }
    }
    delay(10);
}

测试图示:
技术分享图片

以上是关于Arduino NRF24L01 应用实例的主要内容,如果未能解决你的问题,请参考以下文章

树莓派与Arduino Leonardo使用NRF24L01无线模块通信之基于RF24库发送自定义数据

树莓派与Arduino Leonardo R3使用NRF24L01无线模块通信

树莓派与Arduino Leonardo使用NRF24L01无线模块通信之基于RF24库全双工通信

树莓派与Arduino Leonardo使用NRF24L01无线模块通信之基于RF24库 树莓派查询子节点温湿度数据

NRF24L01 与 ATtiny 和 Uno 未连接

树莓派与Arduino Leonardo使用NRF24L01无线模块通信之基于RF24库 树莓派单子节点查询