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;
注意:
1.microBox库需要做修改方能试验本实例,修改如下:
microBox.h:
#define MAX_CMD_NUM 128 //设置合适值以正确接受输入内容
#define MAX_CMD_BUF_SIZE 128 //根据需要设置
2.经过简单性能测试,该例程可最快 50ms发收一次(发送32Byte并且接收32Byte)
3.某些情况下可能会发送失败,经测试发现是 Client端的问题,解决方法:对Client端进行复位,现以提供 “reset”指令以支持软复位
Client 代码(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
#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 代码(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
#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;
}
}
}