richonguzman / LoRa_APRS_iGate

LoRa APRS iGATE for ESP32 Based Board with Rx + Tx capabilities
MIT License
212 stars 65 forks source link

No battery voltage in beacon #70

Closed 7deve closed 5 months ago

7deve commented 6 months ago

Hello,

First of all, thanks for the amazing work. I have a Heltec LoRa v3 board, and the iGate function is working as expected. However I can't get the internal battery voltage shown in the beacon message or in the telemetry. I have checked with tcpdump on the connected router and it seems that the board is not sending it in the beacon messages.

"beacon": { ... "sendViaAPRSIS": true, ...

"other": { "rememberStationTime": 30, "sendBatteryVoltage": true, "externalVoltageMeasurement": false, "externalVoltagePin": 34, "lowPowerMode": false, "lowVoltageCutOff": 0

Is there something I missed? Thanks & 73, Daniel

richonguzman commented 6 months ago

maybe the battery pin was wrongly defined on my side... can you check the data sheet of the board to double confirm it ... if it needs to be changed... I will do it for sure ;)

7deve commented 6 months ago

On the ESP it is PIN6, GPIO1 (ADC1 CH0). But in battery_utils.cpp:

if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_HTCT62)

        sample = analogRead(batteryPin);
        #endif
        #if defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
        sample = 0;
        #endif

Do you actually read the adc?

richonguzman commented 6 months ago

will check the code for this to change it ASAP

7deve commented 6 months ago

Thanks! Let me know, I will test it.

Szetya commented 6 months ago

The heltec V3 has an ADC control pin (GPIO17) which is set high. It is connected to the leg of a FET gate. It must be pulled low before measuring voltage. The role of ADC_CTRL is to prevent the battery from slowly discharging on the voltage divider. HTIT-WB32LAF_V3 image

7deve commented 6 months ago

The heltec V3 has an ADC control pin (GPIO17) which is set high. It is connected to the leg of a FET gate. It must be pulled low before measuring voltage. The role of ADC_CTRL is to prevent the battery from slowly discharging on the voltage divider.

Isn't this GPIO37?

Szetya commented 6 months ago

A heltec V3 ADC vezérlőtűvel (GPIO17) rendelkezik, amely magasra van állítva. Egy FET-kapu lábához csatlakozik. Feszültségmérés előtt alacsonyra kell húzni. Az ADC_CTRL szerepe az, hogy megakadályozza az akkumulátor lassú lemerülését a feszültségosztón.

Ez nem GPIO37?

Sorry. Indeed 37 :)

Szetya commented 6 months ago

ifdef ADC_CTRL

pinMode(ADC_CTRL & 127, OUTPUT); digitalWrite(ADC_CTRL & 127, ADC_CTRL & 128 ? 1 : 0); ////128 + pin num > HIGH, pin num > LOW

endif

//measurement

ifdef ADC_CTRL

digitalWrite(ADC_CTRL & 127, ADC_CTRL & 128 ? 0 : 1); //128 + pin num > LOW, pin num > HIGH

endif

Some boards need to be pulled low and some need to be pulled high. This is a universal code ADC_CTRL 37+128 pull high ADC_CTRL 37 pulls low :)

richonguzman commented 5 months ago

The heltec V3 has an ADC control pin (GPIO17) which is set high. It is connected to the leg of a FET gate. It must be pulled low before measuring voltage. The role of ADC_CTRL is to prevent the battery from slowly discharging on the voltage divider.

Isn't this GPIO37?

hi!

please update to the latest code and test it... it should work now ;)

7deve commented 5 months ago

Hi,

I have now updated to the latest version, but unfortunately the battery voltage monitoring still doesn't work. I have changed the icon to blue circle also, but this did not help either. Anything else I can test?

Thanks!

richonguzman commented 5 months ago

Hi,

I have now updated to the latest version, but unfortunately the battery voltage monitoring still doesn't work. I have changed the icon to blue circle also, but this did not help either. Anything else I can test?

Thanks!

this was added to a latest version than RELEASE v1.0.2

could you please just upload the firmware from Main branch on github page? (this should be added into V1.0.3 soon)

7deve commented 5 months ago

I complied the firmware from source, did not use the release branch. Source was downloaded 21.04, I can see the changes in pins_config, power_utils, battery utils, etc

richonguzman commented 5 months ago

so all works for you now?

IZ1HMT commented 5 months ago

so all works for you now?

The voltage is detected and sent but the value (I think the multiplier) is completely wrong. When the battery is charged the voltage is correct (up to approximately 4 volts) then during discharge it indicates very low values. Now the value indicated and transmitted is 0.3 volts on the display for example, but measured with an instrument it is 3.69 volts.

Szetya commented 5 months ago

so all works for you now?

The voltage is detected and sent but the value (I think the multiplier) is completely wrong. When the battery is charged the voltage is correct (up to approximately 4 volts) then during discharge it indicates very low values. Now the value indicated and transmitted is 0.3 volts on the display for example, but measured with an instrument it is 3.69 volts.

That's because the ADC_CTRL PIN should be at LOW level during the voltage measurement. I have already mentioned it above.

IZ1HMT commented 5 months ago

Sorry, I'm not very good at coding. What should I enter and where? In the "power_utils.cpp" part?

Szetya commented 5 months ago

Sorry, I'm not very good at coding. What should I enter and where? In the "power_utils.cpp" part?

//row 340-341
pinMode(ADC_CTRL & 127, OUTPUT);          //Complete line 340
//digitalWrite(ADC_CTRL, HIGH);           //Add a comment to line 341

//row 44-62
double getBatteryVoltage() {
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
return (PMU.getBattVoltage() / 1000.0);
#else
    #ifdef BATTERY_PIN
        #ifdef ADC_CTRL                                         //If ADC_CTRL PIN has value
        //The ADC_CTRL PIN is set high or low for the duration of the measurement. 
        digitalWrite(ADC_CTRL & 127, ADC_CTRL & 128 ? 0 : 1);   //128 + PIN num for LOW, just PIN num for HIGH 
        #endif
        int adc_value = analogRead(BATTERY_PIN);                //This is where the measurement takes place.
        #ifdef ADC_CTRL                                         //If ADC_CTRL PIN has value
        //Reset the ADC_CTRL PIN level.
        digitalWrite(ADC_CTRL & 127, ADC_CTRL & 128 ? 1 : 0);   //128 + PIN num for HIGH, just PIN num for LOW 
        #endif
        double voltage = (adc_value * 3.3 ) / 4095.0;
        #if defined(TTGO_T_Beam_V0_7) || defined(ESP32_DIY_LoRa_GPS) || defined(TTGO_T_LORA32_V2_1_GPS) || defined(TTGO_T_LORA32_V2_1_TNC) || defined(ESP32_DIY_1W_LoRa_GPS) || defined(OE5HWN_MeshCom)
        return (2 * (voltage + 0.1)) * (1 + (lora32BatReadingCorr/100)); // (2 x 100k voltage divider) 2 x voltage divider/+0.1 because ESP32 nonlinearity ~100mV ADC offset/extra correction
        #endif
        #if defined(HELTEC_V3_GPS) || defined(HELTEC_WIRELESS_TRACKER) || defined(ESP32_C3_DIY_LoRa_GPS)
        double inputDivider = (1.0 / (390.0 + 100.0)) * 100.0;  // The voltage divider is a 390k + 100k resistor in series, 100k on the low side. 
        return (voltage / inputDivider) + 0.285; // Yes, this offset is excessive, but the ADC on the ESP32s3 is quite inaccurate and noisy. Adjust to own measurements.
        #endif
    #else
    return 0.0;
    #endif
#endif    
}

The state of ADC_CTRL can be easily changed. If you add 128 to the PIN value it will negate it. The & sign is a bitwise operator. The digitalWrite parameter is pin_num & 127, pin_num & 128 ? 1:0, which means that if pin_num has bit 128, the second argument is 1, otherwise 0. So if pin_num is 128 or greater, the second argument is 1, otherwise 0. This means that it will be usable (with the correct PIN configuration both when the PIN is set to HIGH and when the PIN is set to LOW. Some boards require this and some require that)

Szetya commented 5 months ago

Oops. That was the tracker code. 😉 But the point is the same. The three lines before and after analogRead and the pinmode addition 😇

IZ1HMT commented 5 months ago

Thanks for the help, I'll try to make the changes later and let you know. I hope @richonguzman puts the correct code in the firmware soon.

Szetya commented 5 months ago

In the afternoon, if I have time, I'll write again which lines are affected by the change. Hopefully in good files. 😉 Yesterday I was careless and looked at the tracker code. I wasn't paying attention to which topic. 😉

IZ1HMT commented 5 months ago

It would be fantastic, if I succeeded it would be one less job (and one bug) for Ricardo who in the meantime is also trying to solve the always on display bug when the module is disconnected from the wi-fi.

Szetya commented 5 months ago

pins_config.h row 144 :

define ADC_CTRL 165 //PIN 37+128

power_utils.cpp row 129-134:

if defined(HELTEC_V3)

pinMode(VExt_CTRL,OUTPUT); // this is for GPS and TFT screen on Wireless_Tracker and only for Oled in Heltec V3 digitalWrite(VExt_CTRL, HIGH); pinMode(ADC_CTRL & 127, OUTPUT); //165 & 127 = 37 but 37 & 127 = 37 wow, magic! :) //digitalWrite(ADC_CTRL, HIGH);

endif

battery_utils row 24-36:

 float checkBattery() { 
    int sample;
    int sampleSum = 0;
    #ifdef ADC_CTRL  //If ADC_CTRL is present, it is set to the appropriate level for the duration of the measurement.
    digitalWrite(ADC_CTRL & 127, ADC_CTRL & 128 ? 0 : 1);  //If PIN num greater than 128 then LOW, otherwise HIGH.
    #endif
    for (int i = 0; i < 100; i++) {
        #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_HTCT62) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa_A7670) || defined(TTGO_T_LORA32_V2_1_915)
        sample = analogRead(BATTERY_PIN);
        #endif
        #if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
        sample = 0;
        #endif
        sampleSum += sample;
        delayMicroseconds(50); 
    }
    #ifdef ADC_CTRL  //If ADC_CTRL is present, it is reset to the appropriate level at the end of the measurement.
    digitalWrite(ADC_CTRL & 127, ADC_CTRL & 128 ? 1 : 0);  //If PIN num greater than 128 then HIGH, otherwise LOW.
    #endif

I don't have a V3 so I can't test it but the principle is this. I hope it will work. :)

IZ1HMT commented 5 months ago

Sincerely thanks for the help but the tension is always incorrect. Battery at 3.5 volts measured by voltmeter and the card always reads unreal values like 0.3 volts.

richonguzman commented 5 months ago

Please upload firmware (code) .... not the webInstaller

it should run now for you (please let me know how it goes

IZ1HMT commented 5 months ago

I loaded the latest code from vsc, unfortunately nothing has changed.

richonguzman commented 5 months ago

did you download It just now from github and uploaded "heltec_wifi_lora_32_V3" environment?

IZ1HMT commented 5 months ago

Yes, I did all this. Code from GitHub new and uploaded with VSC selecting heltec V3

IZ1HMT commented 5 months ago

After the last fix yesterday, the bug on the Heltec V3 Wi-fi card has been resolved. Optimal @richonguzman

Szetya commented 5 months ago

All those #defined directives... 🙁 I missed it too. 😠

Szetya commented 5 months ago

I don't even understand why you need a directive before POWER_Utils::setup();. @ricardo Wouldn't it be enough to specify in the setup of power_utils what is needed and what is not needed?!

richonguzman commented 5 months ago

I don't even understand why you need a directive before POWER_Utils::setup();. @ricardo Wouldn't it be enough to specify in the setup of power_utils what is needed and what is not needed?!

you need to be more clear about what you recommend.

please post some code example

Szetya commented 5 months ago

@richonguzman main 79-81:

if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_2_SX1262) || defined(HELTEC_V3)

POWER_Utils::setup();

endif

Instead: POWER_Utils::setup();

power_utils.cpp void setup section:

if defined(HELTEC_V3)

pinMode(VExt_CTRL,OUTPUT); // this is for GPS and TFT screen on Wireless_Tracker and only for Oled in Heltec V3 digitalWrite(VExt_CTRL, HIGH); pinMode(ADC_CTRL, OUTPUT);

endif

Instead:

ifdef VExt_CTRL //It would be nicer to use VEXT_CTRL instead

//We are preparing so that in the future, if you wish to change your PIN number from HIGH to LOW, you will only need to change the PIN number. pinMode(VExt_CTRL & 127, OUTPUT); // It is worth using bitwise. This is for GPS and TFT screen on Wireless_Tracker and only for Oled in Heltec V3 digitalWrite(VExt_CTRL & 127, VExt_CTRL & 128 ? 0 : 1); //HIGH for normal PIN, LOW for PIN+128. ex: 36 = HIGH for heltecWT Ver05, (36+128)=164 = LOW for heltec WT Ver03

endif

ifdef ADC_CTRL

pinMode(ADC_CTRL & 127, OUTPUT); // It is worth using bitwise.

endif

Also, I would put the HAS_AXPxxx directives before the voids (also in the .h file). Because if there is no AXP then empty voids are compiled in the code.

richonguzman commented 5 months ago

great, added