internetofthings 2019-11-10
软件准备:
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 <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 代码(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; } } }
测试图示: