920MHz帯無線機モジュール ES920LR用ライブラリ いわゆるLoRaWAN
Dependents: HYBRYD2018_IZU_GROUND_STATION HYBRYD2018_IZU_ROCKET Hybrid_IZU201811_GNDv1 Hybrid_IZU2019 ... more
ES920LR.hpp
- Committer:
- Gaku0606
- Date:
- 2018-02-20
- Revision:
- 0:3dede5174e85
- Child:
- 1:febb32df437c
File content as of revision 0:3dede5174e85:
#pragma once /* * ES920LR ライブラリ ver0.2.1 * RSSI値、アドレス付与はまだ未対応です。 * データ形式はbinaryです。asciiには未対応です。 * 設定の変更はあらかじめ行うという形式です。 */ #include "mbed.h" const int ES920LR_BUFF_SIZE = 70; const int ES920LR_FUNC_NUMBER = 256; const int ES920LR_DATA_INTERVAL = 10000;//[us] /** @brief 920MHz帯無線機ES920LRを簡単に使えるクラス */ class ES920LR { public: typedef enum END_COMMAND { endl = 1, asciiEnd = 2 }end_command; //ノード種別設定 typedef enum NODE { Coordinator = 1, EndDevice = 2 }nodeNumber; //帯域幅 typedef enum BAND_WIDTH { _62_5kHz = 3, _125kHz = 4, _250kHz = 5, _500kHz = 6 }band_width; //転送モード選択 typedef enum TRANSMODE { Payload = 1, Frame = 2 }transmode; typedef enum ON_OFF { OFF = 2, ON = 1 }on_off; typedef enum Operation { Configuration = 1, Operation = 2 }operation; typedef enum es920lr_buff_classify { BUFF_A = 0, BUFF_B = 1 }ES920LR_Buff_Classify; //解析方法に関する変数 const int WAIT_TIME_US = 1000; typedef enum { DATA_STRING = 0, //データの文字列 RESPONSE_STRING = 1, //OKかNGのレスポンスの文字列 NORMAL_STRING = 2, OTHER_STRING = 3, RECEIVE_ID = 4, INTERACTIVE_STRING = 5 }ES920LR_Analyze_Selector; public: ES920LR(Serial &serial, const int baud = 115200){ AB = BUFF_A; ser = &serial; _baud = baud; ser->baud(_baud); init(); ser->attach(this, &ES920LR::es920lrHandler, Serial::RxIrq);//受信割り込み設定 _es920lr_timer.start();//タイマースタート printf("hello world\r\n"); } private: Serial * ser; Timer _es920lr_timer; int _baud; //バッファ関連の変数 char buff_A[ES920LR_BUFF_SIZE]; char buff_B[ES920LR_BUFF_SIZE]; char* readBuffAddr; char* writeBuffAddr; ES920LR_Buff_Classify AB; int es920lr_dataLength; union ES920LR_CAST { double d; float f; long l; int i; short s; char c; char u[8]; }; union ES920LR_CAST es920lr_cast; char data[51]; int sendDataSize; void(*p_callFunc[256])(void); char sendBuff[52]; nodeNumber _nodeNumber;//ノード種別 band_width _band_width;//帯域幅 int _diffusivity;//拡散率 int _ch;//チャンネル ON_OFF _ack;//ack受信設定 ON_OFF _rcvid;//レシーブID表示設定 transmode _transmode;//転送モード operation _operation;//起動モード int _baudrate;//UART速度 int _power;//出力 int _sendtime;//自動送信時間 char _senddata[51];//自動送信データ uint16_t _panid;//PANネットワークアドレス uint16_t _ownid;//自ノードのネットワークアドレス uint16_t _dstid;//送信先ノードのネットワークアドレス ON_OFF _rssiAdd;//RSSI値を付加するかどうか int sendIndex;//送信バッファの現在のインデックス,1以上51以下 int responseFlag = 0;//送信後のレスポンスを受け取るかどうか public: char rssi[5];//最新の電波強度 char rcvPANID[5]; char rcvADDR[5]; char header;//最新のデータのヘッダー void init(){ _nodeNumber = Coordinator; _band_width = _125kHz; _diffusivity = 7;//拡散率 _ch = 1;//チャンネル _ack = OFF;//ack受信設定 _rcvid = OFF;//レシーブID表示設定 _transmode = Payload;//転送モード _operation = Operation;//起動モード _baudrate = 115200;//UART速度 _rssiAdd = OFF; _power = 13; _sendtime = 0; memset(sendBuff, '\0', 51);//送信バッファの初期化 _panid = 0x0001; _ownid = 0x0001; _dstid = 0x0000; memset(buff_A, '\0', ES920LR_BUFF_SIZE);//受信バッファの初期化 memset(buff_B, '\0', ES920LR_BUFF_SIZE); readBuffAddr = buff_B; writeBuffAddr = buff_A; sendDataSize = 0; memset(data, '\0', 50);//受信データ配列の初期化 for (int i = 0; i < 256; ++i) {//関数ポインタにダミー関数を設定 p_callFunc[i] = NULL;//&this->dummyFunc; } es920lr_dataLength = 0; sendIndex = 1; memset(rssi, '\0', 5); memset(rcvPANID, '\0', 5); memset(rcvADDR, '\0', 5); header = 0; ser->printf("start\r\n"); wait(0.5f); } //送信バッファを送信する void send() { printf("index:%d\r\n", sendIndex); sendBuff[0] = (uint8_t)(sendIndex - 1);//sendIndexは一つ大きいので sendBuff[sendIndex + 1] = '\0';//printf用に最後にnullを追加 responseFlag = 1; for (int i = 0; i <= sendIndex; ++i) { ser->putc(sendBuff[i]); } //ser->printf("%s", sendBuff);//putcにすべきだった printf("send: "); for (int i = 0; i < sendIndex; ++i) { printf("%02X ", sendBuff[i]); } printf("\r\n"); //初期化 sendIndex = 1; memset(sendBuff, '\0', 52); } //送信バッファに追加 void Write(char arg) { if (sendIndex < 51) {//気持ち悪いが、index==51が最大 es920lr_cast.c = arg; sendBuff[sendIndex] = es920lr_cast.u[0];//sendIndexは初期値1なので、+1は必要ない sendIndex += 1; } } void Write(unsigned char arg) { if (sendIndex < 51) {//気持ち悪いが、index==51が最大 es920lr_cast.c = arg; sendBuff[sendIndex] = es920lr_cast.u[0];//sendIndexは初期値1なので、+1は必要ない sendIndex += 1; } } void Write(short arg) { if (sendIndex < 50) { es920lr_cast.s = arg; for (int i = 0; i < 2; ++i) { sendBuff[sendIndex] = es920lr_cast.u[i]; ++sendIndex; } } } void Write(unsigned short arg) { if (sendIndex < 50) { es920lr_cast.s = arg; for (int i = 0; i < 2; ++i) { sendBuff[sendIndex] = es920lr_cast.u[i]; ++sendIndex; } } } void Write(int arg) { if (sendIndex < 48) { es920lr_cast.i = arg; for (int i = 0; i < 4; ++i) { sendBuff[sendIndex] = es920lr_cast.u[i]; ++sendIndex; } } } void Write(unsigned int arg) { if (sendIndex < 48) { es920lr_cast.i = arg; for (int i = 0; i < 4; ++i) { sendBuff[sendIndex] = es920lr_cast.u[i]; ++sendIndex; } } } void Write(float arg) { if (sendIndex < 48) { es920lr_cast.f = arg; for (int i = 0; i < 4; ++i) { sendBuff[sendIndex] = es920lr_cast.u[i]; ++sendIndex; } } } void Write(double arg) { if (sendIndex < 44) { es920lr_cast.d = arg; for (int i = 0; i < 8; ++i) { sendBuff[sendIndex] = es920lr_cast.u[i]; ++sendIndex; } } } void Write(long arg) { if (sendIndex < 44) { es920lr_cast.l = arg; for (int i = 0; i < 8; ++i) { sendBuff[sendIndex] = es920lr_cast.u[i]; ++sendIndex; } } } /** @bref データ処理関数を設定 @param *funcAddr 関数ポインタ、void型引数無し関数のみ設定可 @param header 関数を選択する0~255のヘッダー */ void attach(void(*funcAddr)(void), unsigned char myHeader) { p_callFunc[myHeader] = funcAddr; return; } //1文字受信するたびに呼ばれ、データを受信バッファに入れる void es920lrHandler() { static int index = -1;//バッファのイテレータとなる static char c = 0;//受信したデータを一旦入れる static int firstFlag = 1;//最初の1byteなら1 static int dataSize = 0; static int callTime[2] = {0, 0}; c = ser->getc();//1byte受信 //printf("%02X ", c); callTime[1] = _es920lr_timer.read_us();//現在の時刻を取得 if (abs(callTime[1] - callTime[0]) > ES920LR_DATA_INTERVAL) {//前の呼び出しとのΔtから新しいデータか判断 firstFlag = 1; } callTime[0] = callTime[1];//時刻の更新 //バイナリモードを想定 if (firstFlag) { dataSize = (unsigned char)c; firstFlag = 0; index = 0; return; } else { writeBuffAddr[index] = c; if (index == (dataSize - 1)) {//1パケット終わり firstFlag = 1; writeBuffAddr[index + 1] = '\0';//終端文字追加 //printf("%s\r\n", writeBuffAddr); printf("wbuf: "); for (int i = 0; i < 49; ++i) { printf("%02X ", writeBuffAddr[i]); } printf("\r\n"); if (AB == BUFF_A) {//現在バッファAに書き込み中 readBuffAddr = buff_A; writeBuffAddr = buff_B; AB = BUFF_B; } else {//現在バッファBに書き込み中 readBuffAddr = buff_B; writeBuffAddr = buff_A; AB = BUFF_A; } if (!responseFlag) {//レスポンスではない //es920lr_debug(); data_analyze(dataSize);//data配列をつくって、rssi値などを更新 //デバッグ //printf("%s ", rssi); for (int i = 0; i < 49; ++i) { printf("%02X ", data[i]); } printf("\r\n"); printf("header: %02X\r\n", header); printf("size: %d\r\n", dataSize); //ユーザー関数呼び出し if (p_callFunc[(uint8_t)header] != NULL) { (*p_callFunc[(uint8_t)header])(); } } else {//レスポンス responseFlag = 0; //デバッグ printf("res %s\r\n", readBuffAddr); } } ++index;//カウントをインクリメント return; } } //デバッグ用 void es920lr_debug() { printf("%s\r\n", readBuffAddr); } //シリアル通信の通信速度変更 ※設定を変更するわけではない void baud(int baudrate) { ser->baud(baudrate); } int asciiToNumber(char c) { //printf("%c ", c); int temp = (int)c; if (temp >= 65) {//A ~ F return (temp - 55); } else {//0 ~ 9 return (temp - 48); } } /** @bref データを取得します */ void data_analyze(int length) { static char tempStr[70] = {}; for (int i = 0; i < length; ++i) tempStr[i] = readBuffAddr[i]; memset(data, 0, 50); if (_rcvid == ON) {//相手ノードネットワークアドレス付与設定 if (_rssiAdd == OFF) { //AAAABBBB!!!!...!\0 // | | | +- <CR><LF>文字列終了 // | | +------- データ // | +------------ 送信元アドレス // +---------------- 送信元PAN ID for (int i = 0; i < 4; ++i) { rcvPANID[i] = tempStr[i]; rcvADDR[4 + i] = tempStr[4 + i]; } header = tempStr[8]; //strncpy(data, &tempStr[9], length - 9); for (int i = 0; i < length - 9; ++i) { data[i] = tempStr[9 + i]; } return; } else { //1111AAAABBBB!!!!...!\0 // | | | | +-- <CR><LF>文字列終了 // | | | +------- データ // | | +------------ 送信元アドレス // | +---------------- 送信元PAN ID // +--------------------- RSSI値 for (int i = 0; i < 4; ++i) { rssi[i] = tempStr[i]; rcvPANID[4 + i] = tempStr[4 + i]; rcvADDR[8 + i] = tempStr[8 + i]; } header = tempStr[12]; //strncpy(data, &tempStr[13], length - 13); for (int i = 0; i < length - 13; ++i) { data[i] = tempStr[13 + i]; } } } else {//相手ノードネットワークアドレスなし if (_rssiAdd == OFF) { //!!!!...!\0 header = tempStr[0]; //strncpy(data, &tempStr[1], length-1); for (int i = 0; i < length - 1; ++i) { data[i] = tempStr[1 + i]; } return; } else {//RSSI値付与 //1111!!!!...!\0 // | | +-- <CR><LF>文字列終了 // | +-------- データ // +------------- RSSI値 for (int i = 0; i < 4; ++i) { rssi[i] = tempStr[i]; } //strncpy(data, &tempStr[5], length- 5); for (int i = 0; i < length - 5; ++i) { data[i] = tempStr[5 + i]; } } } } //RSSI値を数値に変換する int calcRSSI() { return asciiToNumber(rssi[0]) * 4096 + asciiToNumber(rssi[1]) * 256 + asciiToNumber(rssi[2]) * 16 + asciiToNumber(rssi[3]); } void dummyFunc() { printf("ATTACH NO FUNCTION\r\n"); } short toShort(char *array) { //es920lr_cast.s = ((uint16_t)array[0] << 8) | (uint16_t)array[1]; es920lr_cast.u[0] = array[0]; es920lr_cast.u[1] = array[1]; return es920lr_cast.s; } short toShort(int i) { return toShort(&data[i]); } int toInt(char *array) { //es920lr_cast.i = ((uint32_t)array[0] << 24) | ((uint32_t)array[1] << 16) | ((uint32_t)array[2] << 8) | (uint32_t)array[3]; es920lr_cast.u[0] = array[0]; es920lr_cast.u[1] = array[1]; es920lr_cast.u[2] = array[2]; es920lr_cast.u[3] = array[3]; return es920lr_cast.i; } int toInt(int i) { return toInt(&data[i]); } float toFloat(char *array) { es920lr_cast.u[0] = array[0]; es920lr_cast.u[1] = array[1]; es920lr_cast.u[2] = array[2]; es920lr_cast.u[3] = array[3]; return es920lr_cast.f; } float toFloat(int i) { return toFloat(&data[i]); } double toDouble(char *array) { for (int i = 0; i< 8; ++i) { es920lr_cast.u[i] = array[i]; } return es920lr_cast.d; } double toDouble(int i) { return toDouble(&data[i]); } long toLong(char *array) { for (int i = 0; i < 8; ++i) { es920lr_cast.u[i] = array[i]; } return es920lr_cast.l; } long toLong(int i) { return toLong(&data[i]); } }; //<<演算子オーバーロード ES920LR& operator<<(ES920LR& es, const char& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const unsigned char& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const short& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const unsigned short& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const int& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const unsigned int& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const long& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const float& arg) { es.Write(arg); return es; } ES920LR& operator<<(ES920LR& es, const double& arg) { es.Write(arg); return es; } void operator<<(ES920LR& es, const ES920LR::END_COMMAND cmd) { switch (cmd) { case ES920LR::endl: es.send(); break; case ES920LR::asciiEnd: es.Write('\r'); es.Write('\n'); es.send(); break; } }