From 64a19c72adea49d3ec42a0be33246201bd58b686 Mon Sep 17 00:00:00 2001 From: esthban Date: Fri, 15 Nov 2024 23:11:25 +0000 Subject: [PATCH 1/2] Frequency correction based on board temperature --- tinyGS/src/ConfigManager/ConfigManager.cpp | 73 ++++++++++++++++++- tinyGS/src/ConfigManager/ConfigManager.h | 55 ++++++++++++++ tinyGS/src/Radio/Radio.cpp | 7 +- tinyGS/tinyGS.ino | 84 ++++++++++++++++++++++ 4 files changed, 216 insertions(+), 3 deletions(-) diff --git a/tinyGS/src/ConfigManager/ConfigManager.cpp b/tinyGS/src/ConfigManager/ConfigManager.cpp index 9df3432f..813d4ab2 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.cpp +++ b/tinyGS/src/ConfigManager/ConfigManager.cpp @@ -126,6 +126,14 @@ ConfigManager::ConfigManager() groupAdvanced.addItem(&modemParam); groupAdvanced.addItem(&advancedConfigParam); addParameterGroup(&groupAdvanced); + + //////////////////////////////////////////// + temperatureCurve.addItem(&allowFreqComparam); + temperatureCurve.addItem(&temperature1param); + temperatureCurve.addItem(&frequencyDev1param); + temperatureCurve.addItem(&temperature2param); + temperatureCurve.addItem(&frequencyDev2param); + addParameterGroup(&temperatureCurve); } void ConfigManager::handleRoot() @@ -520,6 +528,12 @@ void ConfigManager::resetAllConfig() boardTemplate[0] = '\0'; modemStartup[0] = '\0'; advancedConfig[0] = '\0'; + ///////////////////////////// + allowFreqComp[0]='\0'; + temp_1[0]='\0'; + freq_dev_1[0]='\0'; + temp_2[0]='\0'; + freq_dev_2[0]='\0'; saveConfig(); } @@ -769,7 +783,64 @@ void ConfigManager::parseModemStartup() m.crc_finalxor= doc["cF"]; m.crc_refIn= doc["cRI"]; m.crc_refOut= doc["cRO"]; - } + /* + RADIO_SX1278 = 1, + RADIO_SX1276 = 2, + RADIO_SX1268 = 5, + RADIO_SX1262 = 6, + RADIO_SX1280 = 8 + */ + String placa_de_radio=""; + int placa=boards[getBoard()].L_radio; + /* + switch(placa){ + case 1:placa_de_radio ="SX1278";break; + case 2:placa_de_radio="SX1276";break; + case 5:placa_de_radio="SX1268";break; + case 6:placa_de_radio="SX1262";break; + case 8:placa_de_radio="SX1280";break; + default:placa_de_radio="UNKNOWN";break; + } + */ + //Log::console(PSTR("Board: %s Radio: %i"),boards[getBoard()].BOARD.c_str(),placa); + switch (placa) + { + case 1:{ + /* code */ + // Receiver bandwidth in kHz (FSK/OOK) Allowed values for SX1278 are: + // 2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6, 20.8, 25, 31.3, 41.7, 50, 62.5, 83.3, 100, 125, 166.7, 200, 250 kHz + float abw[21]={2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6, 20.8, 25, 31.3, 41.7, 50, 62.5, 83.3, 100, 125, 166.7, 200, 250}; + float arxBw = m.bw; + int i=0; + while (m.bw>abw[i] && i<21){i++;} + if (i<21){arxBw=abw[i];}else{arxBw=abw[i-1];} + if (arxBw!=m.bw){ + Log::console(PSTR("The initial BW of %.2f has been matched to board SX1278 BW of %.2f"),m.bw,arxBw); + m.bw=arxBw; + } + } + break; + + case 5:{ + /* code */ + // Receiver bandwidth in kHz (FSK/OOK) Allowed values for SX1268 are: + // 4.8, 5.8, 7.3, 9.7, 11.7, 14.6, 19.5, 23.4, 29.3, 39.0, 46.9, 58.6, 78.2, 93.8, 117.3, 156.2, 187.2, 234.3, 312.0, 373.6, 467.0 + float abw[21]={4.8, 5.8, 7.3, 9.7, 11.7, 14.6, 19.5, 23.4, 29.3, 39.0, 46.9, 58.6, 78.2, 93.8, 117.3, 156.2, 187.2, 234.3, 312.0, 373.6, 467.0}; + float arxBw = m.bw; + int i=0; + while (m.bw>abw[i] && i<21){i++;} + if (i<21){arxBw=abw[i];}else{arxBw=abw[i-1];} + if (arxBw!=m.bw){ + Log::console(PSTR("The initial BW of %.2f has been matched to board SX1268 BW of %.2f"),m.bw,arxBw); + m.bw=arxBw; + } + } + break; + + default: + break; + } + } // packets Filter uint8_t filterSize = doc["filter"].size(); diff --git a/tinyGS/src/ConfigManager/ConfigManager.h b/tinyGS/src/ConfigManager/ConfigManager.h index 70d7073d..c74a36ff 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.h +++ b/tinyGS/src/ConfigManager/ConfigManager.h @@ -208,6 +208,48 @@ class ConfigManager : public IotWebConf2 IotWebConf2::saveConfig(); currentBoardDirty = true; }; + //////////////////////////////////////// + + bool getAllowFreqComp() { + return (strcmp(allowFreqComp, CB_SELECTED_STR)==0); + } + + float get_temp_1(){ + float temp=-90.0; + if (temp_1[0]!='\0'){ + std::string ts(temp_1); + temp=std::stof(ts); + } + return temp; + } + + float get_temp_2(){ + float temp=-90.0; + if (temp_2[0]!='\0'){ + std::string ts(temp_2); + temp=std::stof(ts); + } + return temp; + } + + float get_freq_dev_1(){ + float freq=-20000.0; + if (freq_dev_1[0]!='\0'){ + std::string freqstr(freq_dev_1); + freq=std::stof(freqstr); + } + return freq; + } + + float get_freq_dev_2(){ + float freq=-20000.0; + if (freq_dev_2[0]!='\0'){ + std::string freqstr(freq_dev_2); + freq=std::stof(freqstr); + } + return freq; + } + //////////////////////////////////////// private: class GSConfigHtmlFormatProvider : public iotwebconf2::HtmlFormatProvider @@ -284,6 +326,12 @@ class ConfigManager : public IotWebConf2 char boardTemplate[TEMPLATE_LEN] = ""; char modemStartup[MODEM_LEN] = ""; char advancedConfig[ADVANCED_LEN] = ""; + //Temperature Curve Definition Parameters + char allowFreqComp[CHECKBOX_LENGTH] = ""; + char temp_1[TEMPLATE_LEN] = ""; + char freq_dev_1[TEMPLATE_LEN] = ""; + char temp_2[TEMPLATE_LEN] = ""; + char freq_dev_2[TEMPLATE_LEN] = ""; iotwebconf2::NumberParameter latitudeParam = iotwebconf2::NumberParameter("Latitude (3 decimals, will be public)", "lat", latitude, COORDINATE_LENGTH, NULL, "0.000", "required min='-180' max='180' step='0.001'"); iotwebconf2::NumberParameter longitudeParam = iotwebconf2::NumberParameter("Longitude (3 decimals, will be public)", "lng", longitude, COORDINATE_LENGTH, NULL, "-0.000", "required min='-180' max='180' step='0.001'"); @@ -308,6 +356,13 @@ class ConfigManager : public IotWebConf2 iotwebconf2::TextParameter boardTemplateParam = iotwebconf2::TextParameter("Board Template (requires manual restart)", "board_template", boardTemplate, TEMPLATE_LEN, NULL, NULL, "type=\"text\" maxlength=255"); iotwebconf2::TextParameter modemParam = iotwebconf2::TextParameter("Modem startup", "modem_startup", modemStartup, MODEM_LEN, "", "", "type=\"text\" maxlength=255"); iotwebconf2::TextParameter advancedConfigParam = iotwebconf2::TextParameter("Advanced parameters", "advanced_config", advancedConfig, ADVANCED_LEN, NULL, NULL, "type=\"text\" maxlength=255"); + + iotwebconf2::ParameterGroup temperatureCurve = iotwebconf2::ParameterGroup("Temperature Curve", "Temperature Curve (Allows to compensate frequency drift due to setup temperature)"); + iotwebconf2::CheckboxParameter allowFreqComparam = iotwebconf2::CheckboxParameter("Allow Frequency Compensation based on chip temperature", "allowFreqComp", allowFreqComp, CHECKBOX_LENGTH, true); + iotwebconf2::NumberParameter temperature1param = iotwebconf2::NumberParameter("Temperature #1", "temp_1", temp_1, NUMBER_LEN, "50.0", "min='-180' max='180' step='0.1'"); + iotwebconf2::NumberParameter frequencyDev1param = iotwebconf2::NumberParameter("Frequency Error #1", "freq_dev_1", freq_dev_1, NUMBER_LEN, "0.000", "min='-10000' max='10000' step='1'"); + iotwebconf2::NumberParameter temperature2param = iotwebconf2::NumberParameter("Temperature #2", "temp_2", temp_2, NUMBER_LEN, "50.0", "min='-180' max='180' step='0.1'"); + iotwebconf2::NumberParameter frequencyDev2param = iotwebconf2::NumberParameter("Frequency Error #2", "freq_dev_2", freq_dev_2, NUMBER_LEN, "0.000", "min='-10000' max='10000' step='1'"); }; #endif diff --git a/tinyGS/src/Radio/Radio.cpp b/tinyGS/src/Radio/Radio.cpp index a26d2513..b7fb9b8e 100644 --- a/tinyGS/src/Radio/Radio.cpp +++ b/tinyGS/src/Radio/Radio.cpp @@ -153,7 +153,7 @@ int16_t Radio::begin() radioHal->setDio0Action(setFlag); // start listening for LoRa packets //Log::console(PSTR("[%s] Starting to listen to %s"), moduleNameString, m.satellite); - Log::console(PSTR("[%s] Starting to listen to %s @ %s mode @ %.4f MHz"), moduleNameString, m.satellite,m.modem_mode,m.frequency); + Log::console(PSTR("[%s] Starting to listen to %s @ %s mode @ %.4f MHz"), moduleNameString, m.satellite,m.modem_mode,m.frequency+m.freqOffset); CHECK_ERROR(radioHal->startReceive()); status.modeminfo.currentRssi = radioHal->getRSSI(false,true); @@ -360,9 +360,11 @@ uint8_t Radio::listen() respFrame=ax25bin; respLen=sizeAx25bin; } - if (frame_error==0 && status.modeminfo.crc_by_sw){ size_t newsize=respLen-status.modeminfo.crc_nbytes; + ////////////////////////////////////////////////////////////////////////////// + // https://github.com/jgromes/RadioLib/blob/master/src/protocols/AX25/AX25.cpp + ////////////////////////////////////////////////////////////////////////////// RadioLibCRCInstance.size = status.modeminfo.crc_nbytes*8; RadioLibCRCInstance.poly = status.modeminfo.crc_poly; RadioLibCRCInstance.init = status.modeminfo.crc_init; @@ -370,6 +372,7 @@ uint8_t Radio::listen() RadioLibCRCInstance.refIn = status.modeminfo.crc_refIn; RadioLibCRCInstance.refOut = status.modeminfo.crc_refOut; uint16_t fcs=RadioLibCRCInstance.checksum(respFrame,newsize); + ////////////////////////////////////////////////////////////////////////////// //If the input is reflected (refIn=true) for the CRC calculation, the CRC value //is computed from last two bytes of respFrame reflecting in first place the bytes. //If the input is not reflected (refIn=false) then the CRC calculation is computed diff --git a/tinyGS/tinyGS.ino b/tinyGS/tinyGS.ino index 1df9d8a4..965bc2c5 100644 --- a/tinyGS/tinyGS.ino +++ b/tinyGS/tinyGS.ino @@ -96,6 +96,23 @@ Radio& radio = Radio::getInstance(); const char* ntpServer = "time.cloudflare.com"; +////////////////////////////////////////////// +//Measure of Chip Temperature and Compensation +////////////////////////////////////////////// +bool allow_logging_verbose_freq_comp=false; +bool allow_logging_freq_comp=true; +unsigned long now=0; +unsigned long last_measu_temp=0; +unsigned long last_log_temp=0; +unsigned long last_write_temp=0; +float tempe_measurement=0.0; +float last_tempe_measurement=0.0; +float temperatura=-90.0; +float freq_off=0.0; +float t1,t2,f1,f2; +float frequency_deviation_limit=10000;//In absolute value +////////////////////////////////////////////// + // Global status Status status; @@ -214,6 +231,73 @@ void loop() { mqtt.loop(); OTA::loop(); if (configManager.getOledBright() != 0) displayUpdate(); + + if (configManager.getAllowFreqComp()){ + ////////////////////////////////////////////// + //Measure of Chip Temperature and Compensation + ////////////////////////////////////////////// + now = millis(); + if ((now - last_measu_temp > 60000) || last_measu_temp==0) + { + last_measu_temp = now; + tempe_measurement=temperatureRead(); + //22/09/2022 + //For some reason, the value 53.33 is a recurrent value provided + //by the board which seems to do not correspond to a real measurement. + //For this reason, when this value is provided that value + //it is not considered for frequency correction. + if (abs(tempe_measurement-53.333)>0.001){ + temperatura=tempe_measurement; + }else{ + //Log::console(PSTR("Temperature %2.2f ºC not considered"),tempe_measurement); + last_measu_temp=now-30000;//Acelerate the measure to do it in 30" + } + if ((now-last_write_temp>60000) + && temperatura!=-90.0 + && last_tempe_measurement!=temperatura){ + + //This determine the offset of the station + t1=configManager.get_temp_1(); f1=configManager.get_freq_dev_1(); + t2=configManager.get_temp_2(); f2=configManager.get_freq_dev_2(); + //Log::console(PSTR("Temp 1: %.2f Freq 1: %.2f Temp 2: %.2f Freq 1: %.2f Temperature: %.2f"),t1,f1,t2,f2,temperatura); + if (t1!=-90.0 && t2!=-90.0 && f1!=-20000.0 && f2!=-20000.0){ + freq_off=f1+(((f2-f1)/(t2-t1))*(temperatura-t1)); + //The negative value (-freq_off) compensates the deviation calculated in the line above + if (abs(freq_off) Set Rx Freq to: %.6f Hz") + if (allow_logging_verbose_freq_comp + || (allow_logging_freq_comp && (now-last_log_temp)>60000) + || last_log_temp==0 ) {last_log_temp=now; + Log::console (PSTR("Chip Ta: %2.2f ºC -> FreqOffset: %.6f MHz") + ,temperatura + // ,status.modeminfo.frequency + // ,-freq_off + ,status.modeminfo.freqOffset); + } + + last_write_temp=now; + temperatura=-90.0; + }else{ + Log::console(PSTR("Check Curve Temperature parameters. Frequency Correction not performed.")); + } + } + } + }else{ + if (status.modeminfo.freqOffset!=0.0){ + status.modeminfo.freqOffset=0.0; + last_measu_temp==0; + radio.begin(); + } + } + ///////////////////////////////////////////////// } void setupNTP() From bca0d3ad1a570bb535880d77e933e4fefb0a083b Mon Sep 17 00:00:00 2001 From: esthban Date: Fri, 15 Nov 2024 23:12:22 +0000 Subject: [PATCH 2/2] Bandwidth adjustment based on RF Modem board --- tinyGS/src/Mqtt/MQTT_Client.cpp | 47 ++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tinyGS/src/Mqtt/MQTT_Client.cpp b/tinyGS/src/Mqtt/MQTT_Client.cpp index 0cadaf9b..37c613f4 100644 --- a/tinyGS/src/Mqtt/MQTT_Client.cpp +++ b/tinyGS/src/Mqtt/MQTT_Client.cpp @@ -482,7 +482,7 @@ void MQTT_Client::manageMQTTData(char *topic, uint8_t *payload, unsigned int len strcpy(m.satellite, doc["sat"].as()); m.NORAD = doc["NORAD"]; - + if (m.modem_mode == "LoRa") { m.frequency = doc["freq"]; @@ -525,6 +525,51 @@ void MQTT_Client::manageMQTTData(char *topic, uint8_t *payload, unsigned int len m.crc_finalxor= doc["cF"]; m.crc_refIn= doc["cRI"]; m.crc_refOut= doc["cRO"]; + /* + RADIO_SX1278 = 1, + RADIO_SX1276 = 2, + RADIO_SX1268 = 5, + RADIO_SX1262 = 6, + RADIO_SX1280 = 8 + */ + Log::console(PSTR("Board: %i Required Bandwidth (BW): %f"),board.L_radio,m.bw); + switch (board.L_radio) + { + case RADIO_SX1278:{ + /* code */ + // Receiver bandwidth in kHz (FSK/OOK) Allowed values are: + // 2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6, 20.8, 25, 31.3, 41.7, 50, 62.5, 83.3, 100, 125, 166.7, 200, 250 kHz + float abw[21]={2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6, 20.8, 25, 31.3, 41.7, 50, 62.5, 83.3, 100, 125, 166.7, 200, 250}; + float arxBw = m.bw; + int i=0; + while (m.bw>abw[i] && i<21){i++;} + if (i<21){arxBw=abw[i];}else{arxBw=abw[i-1];} + if (arxBw!=m.bw){ + Log::console(PSTR("The initial BW of %.2f has been matched to board BW of %.2f"),m.bw,arxBw); + m.bw=arxBw; + } + } + break; + + case RADIO_SX1268:{ + /* code */ + // Receiver bandwidth in kHz (FSK/OOK) Allowed values are: + // 4.8, 5.8, 7.3, 9.7, 11.7, 14.6, 19.5, 23.4, 29.3, 39.0, 46.9, 58.6, 78.2, 93.8, 117.3, 156.2, 187.2, 234.3, 312.0, 373.6, 467.0 + float abw[21]={4.8, 5.8, 7.3, 9.7, 11.7, 14.6, 19.5, 23.4, 29.3, 39.0, 46.9, 58.6, 78.2, 93.8, 117.3, 156.2, 187.2, 234.3, 312.0, 373.6, 467.0}; + float arxBw = m.bw; + int i=0; + while (m.bw>abw[i] && i<21){i++;} + if (i<21){arxBw=abw[i];}else{arxBw=abw[i-1];} + if (arxBw!=m.bw){ + Log::console(PSTR("The initial BW of %.2f has been matched to board BW of %.2f"),m.bw,arxBw); + m.bw=arxBw; + } + } + break; + + default: + break; + } } // packets Filter