Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frequency correction based on board temperature & receiver bandwidth match to allowable value #263

Open
wants to merge 2 commits into
base: beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 72 additions & 1 deletion tinyGS/src/ConfigManager/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
Expand Down
55 changes: 55 additions & 0 deletions tinyGS/src/ConfigManager/ConfigManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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'");
Expand All @@ -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
47 changes: 46 additions & 1 deletion tinyGS/src/Mqtt/MQTT_Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ void MQTT_Client::manageMQTTData(char *topic, uint8_t *payload, unsigned int len
strcpy(m.satellite, doc["sat"].as<char *>());
m.NORAD = doc["NORAD"];


if (m.modem_mode == "LoRa")
{
m.frequency = doc["freq"];
Expand Down Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions tinyGS/src/Radio/Radio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -360,16 +360,19 @@ 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;
RadioLibCRCInstance.out = status.modeminfo.crc_finalxor;
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
Expand Down
84 changes: 84 additions & 0 deletions tinyGS/tinyGS.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)<frequency_deviation_limit) {
status.modeminfo.freqOffset=-freq_off/1000000.0;
}else{
status.modeminfo.freqOffset=0.0;
Log::console(PSTR("Frequency Deviation calculation exceed %5.1f Hz. Frequency Deviation set to 0 Hz."),frequency_deviation_limit);
}
last_tempe_measurement=temperatura;
//For the new frequency offset is taken, the current satellite config needs to be commanded.
radio.begin();
//Log::console (PSTR("Chip Ta: %2.2f ºC -> 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()
Expand Down