commit e439ac81ec2b1e39340399bae1f152ff28969324 Author: jusax23 Date: Sun Aug 21 14:10:45 2022 +0200 initial diff --git a/BUTTONDesc.h b/BUTTONDesc.h new file mode 100644 index 0000000..b45afcc --- /dev/null +++ b/BUTTONDesc.h @@ -0,0 +1,47 @@ +#include "descriptionStruct.h" +#define jType_ANALOG_Desc 50 +#define jType_BUTTON_Desc 51 +#define jCommand_OUT_OF_BOUND 0xff + +typedef struct{ + byte type; //jType_ANALOG_Desc || jType_BUTTON_Desc + byte command; //0-31 button channel || 0-11 + byte use = 0xff; //0-3 || 0-1 + char text[29] = "error"; //Text +}Channel_Desc_Send; + +void initBUTTON_Desc(){ + +} + +void BUTTON_DescLoop(){ + +} + +void BUTTON_DescradioTask(){ + byte num = jRCbuff[1]; + Channel_Desc_Send data; + data.type = jType_BUTTON_Desc; + data.command = num; + if(num>31){ + jSendNRF(&data, sizeof(data)); + return; + } + data.use = buttonDesc[num].use; + strncpy(data.text, buttonDesc[num].text, 29); + jSendNRF(&data, sizeof(data)); +} + +void ANALOG_DescradioTask(){ + byte num = jRCbuff[1]; + Channel_Desc_Send data; + data.type = jType_ANALOG_Desc; + data.command = num; + if(num>11){ + jSendNRF(&data, sizeof(data)); + return; + } + data.use = analogDesc[num].use; + strncpy(data.text, analogDesc[num].text, 29); + jSendNRF(&data, sizeof(data)); +} diff --git a/COMP.h b/COMP.h new file mode 100644 index 0000000..111d2dc --- /dev/null +++ b/COMP.h @@ -0,0 +1,54 @@ +#define jType_S_COMP 2 +#define jCommand_COMP_fail 0xff +//#define jCommand_Compass_Raw 0 + +typedef struct{ + byte type = jType_S_COMP; + byte command = 0; + int X; + int Y; + int Z; + int angle; +}compData; + +#ifdef jCOMP + +#include +QMC5883LCompass compass; + +void initCOMP(){ + compass.init(); +} + +void COMPLoop(){ + compass.read(); +} + +/*float Altitude = mpu6050.getAngleX()/180*PI; +float Roll = mpu6050.getAngleY()/180*PI; +float xh=compass.getX()*cos(Altitude)+compass.getZ()*sin(Altitude); +float yh=compass.getX()*sin(Roll)*sin(Altitude)+compass.getY()*cos(Roll)-compass.getZ()*sin(Roll)*cos(Altitude); +float heading = atan2(yh, xh);*/ + +void COMPradioTask(){ + compData data; + data.X = compass.getX(); + data.Y = compass.getY(); + data.Z = compass.getZ(); + data.angle = compass.getAzimuth(); + jSendNRF(&data, sizeof(data)); +} + +#else + +void initCOMP(){} + +void COMPLoop(){} + +void MPUradioTask(){ + compData data; + data.command = jCommand_COMP_fail; + jSendNRF(&data, sizeof(data)); +} + +#endif diff --git a/DefaultReceiver.ino b/DefaultReceiver.ino new file mode 100644 index 0000000..f4cce67 --- /dev/null +++ b/DefaultReceiver.ino @@ -0,0 +1,44 @@ +#include "descriptionStruct.h" + +#define myId 0x01 +#define myChannel 1 + +#define jMPU +#define jCOMP +#define jGNSS + +#define debug + +//https://dl.espressif.com/dl/package_esp32_index.json +//1.0.6 + +ChannelDesc buttonDesc[32] = { + {3,"Armed"} +}; +ChannelDesc analogDesc[12] = { + +}; + + +void onConnect(){ + +} +void onDisconnect(bool expected){ + +} + +#include "juPadReceiver.h" + +void onData(){ + //RCdata + //RCgetBTN(0-31) + //RCgetAnalog(0-11) +} + +void setup(){ + jSetup(); +} + +void loop(){ + jLoop(); +} diff --git a/GNSS.h b/GNSS.h new file mode 100644 index 0000000..9fc2f27 --- /dev/null +++ b/GNSS.h @@ -0,0 +1,195 @@ +#define jType_S_GNSS 3 +#define jCommand_GNSS_location 0 +#define jCommand_GNSS_date 1 +#define jCommand_GNSS_time 2 +#define jCommand_GNSS_speed 3 +#define jCommand_GNSS_course 4 +#define jCommand_GNSS_altitude 5 +#define jCommand_GNSS_satellites 6 +#define jCommand_GNSS_hdop 7 + +#define jCommand_GNSS_fail 0xff + +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_location; + + byte isValid; + + double lat; + double lng; +}gnssLocData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_date; + + byte isValid; + + uint32_t value; + uint16_t year; + uint8_t month; + uint8_t day; +}gnssDateData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_time; + + byte isValid; + + uint32_t value; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t centisecond; +}gnssTimeData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_speed; + + byte isValid; + + double mps; +}gnssSpeedData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_course; + + byte isValid; + + double deg; +}gnssCourseData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_altitude; + + byte isValid; + + double m; +}gnssAltData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_satellites; + + byte isValid; + + uint32_t n; +}gnssSatData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_hdop; + + byte isValid; + + double hdop; +}gnssHdopData; +typedef struct{ + byte type = jType_S_GNSS; + byte command = jCommand_GNSS_fail; +}gnssFailData; + +#ifdef jGNSS + +#include + +TinyGPSPlus gps; + +void initGNSS(){ + Serial2.begin(9600, SERIAL_8N1, 16, 17); +} + +void GNSSLoop(){ + while (Serial2.available() > 0) { + int readd = Serial2.read(); + gps.encode(readd); + } +} + +void GNSSradioTask(){ + switch (jRCbuff[1]) { + case jCommand_GNSS_location:{ + gnssLocData data; + + data.isValid = gps.location.isValid()|(gps.location.isUpdated()<<1); + data.lat = gps.location.lat(); + data.lng = gps.location.lng(); + + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_GNSS_date:{ + gnssDateData data; + + data.isValid = gps.date.isValid()|(gps.date.isUpdated()<<1); + data.value = gps.date.value(); + data.year = gps.date.year(); + data.month = gps.date.month(); + data.day = gps.date.day(); + + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_GNSS_time:{ + gnssTimeData data; + + data.isValid = gps.time.isValid()|(gps.time.isUpdated()<<1); + data.value = gps.time.value(); + data.hour = gps.time.hour(); + data.minute = gps.time.minute(); + data.second = gps.time.second(); + data.centisecond = gps.time.centisecond(); + + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_GNSS_speed:{ + gnssSpeedData data; + + data.isValid = gps.speed.isValid()|(gps.speed.isUpdated()<<1); + data.mps = gps.speed.mps(); + + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_GNSS_course:{ + gnssCourseData data; + + data.isValid = gps.course.isValid()|(gps.course.isUpdated()<<1); + data.deg = gps.course.deg(); + + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_GNSS_altitude:{ + gnssAltData data; + + data.isValid = gps.altitude.isValid()|(gps.altitude.isUpdated()<<1); + data.m = gps.altitude.meters(); + + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_GNSS_satellites:{ + gnssSatData data; + + data.isValid = gps.satellites.isValid()|(gps.satellites.isUpdated()<<1); + data.n = gps.satellites.value(); + + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_GNSS_hdop:{ + gnssHdopData data; + + data.isValid = gps.hdop.isValid()|(gps.hdop.isUpdated()<<1); + data.hdop = gps.hdop.hdop(); + + jSendNRF(&data, sizeof(data)); + }break; + } +} + +#else + +void initGNSS(){} + +void GNSSLoop(){} + +void GNSSradioTask(){ + gnssFailData data; + jSendNRF(&data, sizeof(data)); +} + +#endif diff --git a/MPU.h b/MPU.h new file mode 100644 index 0000000..37ab0e6 --- /dev/null +++ b/MPU.h @@ -0,0 +1,73 @@ +#define jType_S_MPU 1 +#define jCommand_MPU_Acc 0 +#define jCommand_MPU_Gyro 1 +#define jCommand_MPU_Angle 2 +#define jCommand_MPU_fail 0xff + +typedef struct{ + byte type = jType_S_MPU; + byte command; + float X; + float Y; + float Z; +}mpuSendData; + +#ifdef jMPU + +#include + +MPU6050 mpu6050(Wire, 0.001f, 0.999f); + +void initMPU(){ + mpu6050.begin(); + mpu6050.setGyroOffsets(-7.8,2.32,-0.22); + mpu6050.setAccXoffset(0.03,0.0,0.3); + //mpu6050.calcGyroOffsets(false,50,50); +} + +void MPULoop(){ + mpu6050.update(); +} + +void MPUradioTask(){ + switch (jRCbuff[1]) { + case jCommand_MPU_Acc:{ + mpuSendData data; + data.command = jCommand_MPU_Acc; + data.X = mpu6050.getAccX(); + data.Y = mpu6050.getAccY(); + data.Z = mpu6050.getAccZ(); + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_MPU_Gyro:{ + mpuSendData data; + data.command = jCommand_MPU_Gyro; + data.X = mpu6050.getGyroX(); + data.Y = mpu6050.getGyroY(); + data.Z = mpu6050.getGyroZ(); + jSendNRF(&data, sizeof(data)); + }break; + case jCommand_MPU_Angle:{ + mpuSendData data; + data.command = jCommand_MPU_Angle; + data.X = mpu6050.getAngleX(); + data.Y = mpu6050.getAngleY(); + data.Z = mpu6050.getAngleZ(); + jSendNRF(&data, sizeof(data)); + }break; + } +} + +#else + +void initMPU(){} + +void MPULoop(){} + +void MPUradioTask(){ + mpuSendData data; + data.command = jCommand_MPU_fail; + jSendNRF(&data, sizeof(data)); +} + +#endif diff --git a/RCdata.h b/RCdata.h new file mode 100644 index 0000000..8d697ab --- /dev/null +++ b/RCdata.h @@ -0,0 +1,33 @@ +#define jType_RC 0 +//#define jCommand_GPS_location 0 + +#define NUM_ANALOG_channels 12 + +typedef struct{ + byte type; + byte command; + uint32_t btns; + int16_t analog[NUM_ANALOG_channels]; +}nrfRC; + +nrfRC RCdata; + +void initRCdata(){ + +} + +void RCdataLoop(){ + +} + +void RCdataradioTask(){ + memmove(&RCdata, &jRCbuff, sizeof(RCdata)); + onData(); +} + +bool RCgetBTN(byte i){ + return (RCdata.btns>>min(31,(int)i))&1; +} +int16_t RCgetAnalog(byte i){ + return RCdata.analog[min(NUM_ANALOG_channels-1,(int)i)]; +} diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..f262483 --- /dev/null +++ b/Readme.md @@ -0,0 +1,2 @@ +# DefaultReceiver +This software is designed to run on an esp32. It controls many sensors and communicates with the remote control in the background. \ No newline at end of file diff --git a/descriptionStruct.h b/descriptionStruct.h new file mode 100644 index 0000000..577b0a4 --- /dev/null +++ b/descriptionStruct.h @@ -0,0 +1,9 @@ +#ifndef _descriptionStruct_h_ +#define _descriptionStruct_h_ + +typedef struct { + byte use; //0-3 || 0-1 + char text[29]; //Text +}ChannelDesc; + +#endif diff --git a/juPadReceiver.h b/juPadReceiver.h new file mode 100644 index 0000000..181e332 --- /dev/null +++ b/juPadReceiver.h @@ -0,0 +1,193 @@ +#ifndef _juPadReceiver_h_ +#define _juPadReceiver_h_ + +#define maxLast 2500 + +typedef struct{ + byte type = 0xff; + uint64_t pipe; + byte channel; +}nrfMulticast; + +#ifndef myId + #error "myId is not defined" +#endif +#ifndef myChannel + #error "myChannel is not defined" +#endif + +#define multicastChannel 124 +#define multicastAddress 0xF0F0F0F0FF + +#define jChannel_0 13 +#define jChannel_1 12 +#define jChannel_2 14 +#define jChannel_3 27 +#define jChannel_4 26 +#define jChannel_5 25 +#define jChannel_6 33 +#define jChannel_7 32 +#define jChannel_8 15 + +#define jServo 1 +#define jhBridge 2 +#define jESC 3 +#define jDigital 4 + +#include +#include +#include "nRF24L01.h" +#include "RF24.h" +#include +Preferences preferences; + +void jSendNRF(const void* buf, uint8_t length); + +byte jRCbuff[32]; + +#include "MPU.h" +#include "RCdata.h" +#include "GNSS.h" +#include "COMP.h" +#include "BUTTONDesc.h" + +//3 (CE) 0 //4 (CSN) 4 //5 (SCK) 18 //6 (MOSI) 23 //7 (MISO) 19 +// CE CSN +RF24 radio(0,4); + +const uint64_t myPipe = 0xF0F0F0F000|myId ; + +//0 -> never, 1 -> connected, 2 -> lost/wait +byte jLastStatus = 0; +unsigned long jLast = 0; + +float avgRound = 10; +unsigned long lastRound = 0; +unsigned long delta = 10; + +void jSetup(){ + Serial.begin(115200); + Serial.print("Starting up ... "); + preferences.begin("data", false); + if(!radio.begin()){ + Serial.println("radio hardware is not responding!!"); + while (1) {} + } + radio.enableDynamicPayloads(); + radio.setRetries(5,15); + radio.setChannel(myChannel); + radio.openReadingPipe(0,myPipe); + radio.startListening(); + Wire.begin(); + initMPU(); + initGNSS(); + initCOMP(); + initRCdata(); + Serial.print("wait ... "); + delay(1000); + Serial.println("done"); + #ifdef debug + Serial.println("> debuging"); + #endif + lastRound = millis(); +} + +void jNoConn(){ + if(jLastStatus==1){ + onDisconnect(false); + jLastStatus=3; + } + if(random(25)==1){ +#ifdef debug + Serial.println("Multicast!"); +#endif + radio.stopListening(); + radio.setChannel(multicastChannel); + radio.openWritingPipe(multicastAddress); + nrfMulticast data; + data.pipe = myPipe; + data.channel = myChannel; + radio.write(&data, sizeof(data), true); + radio.setChannel(myChannel); + radio.startListening(); + } +} +void jConn(){ + if(jLastStatus!=1){ + onConnect(); + radio.openWritingPipe(myPipe); + radio.startListening(); + jLastStatus=1; + } +} + + +#ifdef debug +const String b16 = "0123456789abcdef"; + +String SensorDataBuffer=""; +#endif + +void receive(){ + if(radio.available()){ +#ifdef debug + Serial.println("Radio available!"); +#endif + uint8_t payloadSize = radio.getDynamicPayloadSize(); + if(payloadSize>=1){ + jLast = millis(); + radio.read( &jRCbuff, payloadSize ); +#ifdef debug + SensorDataBuffer = "data: "; + for (size_t i = 0; i < payloadSize; i++) { + SensorDataBuffer+=b16[(jRCbuff[i]>>4)&0xf]; + SensorDataBuffer+=b16[jRCbuff[i]&0xf]; + } + Serial.println(SensorDataBuffer); +#endif + switch (jRCbuff[0]) { + case jType_RC:{ + RCdataradioTask(); + }break; + case jType_S_MPU:{ + MPUradioTask(); + }break; + case jType_S_GNSS:{ + GNSSradioTask(); + }break; + case jType_S_COMP:{ + COMPradioTask(); + }break; + case jType_BUTTON_Desc:{ + BUTTON_DescradioTask(); + }break; + case jType_ANALOG_Desc:{ + ANALOG_DescradioTask(); + }break; + } + } + } +} + +void jLoop(){ + unsigned long now = millis(); + delta = now - lastRound; + lastRound = now; + avgRound = avgRound*0.9 + delta*0.1; + + MPULoop(); + GNSSLoop(); + COMPLoop(); + RCdataLoop(); + receive(); + if(millis()-jLast>maxLast)jNoConn(); + else jConn(); +} + +void jSendNRF(const void* buf, uint8_t length){ + radio.stopListening(); + radio.write( buf, length ); + radio.startListening(); +} + +#endif