November 23, 2025, 07:49:48 PM

Recent posts

#61
New Product Ideas / Re: ZX-Spectrum clone
Last post by RafaG - October 27, 2025, 07:53:29 PM
I wonder if it would be possible to emulate the ZX Spectrum (in any of its variants) on the Agonlight2.
#62
ESP32 / ESP32-P4 micropython port
Last post by kerekesg - October 26, 2025, 01:26:53 AM
Just in case anyone would need to run micropython on the ESP32-P4, you can get a build firmware from here:

https://codeberg.org/kerekesg/micropython-olimex-esp32-p4

AI helped me, but it works well on my Olimex ESP32-P4 board.
#63
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by LubOlimex - October 22, 2025, 10:42:00 AM
Yes, it is good and simple way to calibrate but you have to store to non volatile memory or it won't persist after restart (e.g. you have to calibrate every time). More advanced way would be using the espressif guide here:

https://docs.espressif.com/projects/esp-idf/en/stable/esp32h2/api-reference/peripherals/adc_calibration.html

Here is better Arduino IDE code that can be used to calibrate, store to nvm:

// ==========================================================
// ESP32-H2-DevKit-LiPo Battery and Power Sense Demo
// ----------------------------------------------------------
// External Power Sense: GPIO25
// Battery Measurement:  GPIO2
// User Button (BUT1):   GPIO9
// LED:                  GPIO8
//
// Resistor divider coefficient = (R5 + R1) / R5 = 5.7
// Maximum battery voltage = 4.2V
//
// ➤ Press BUT1 for 2–6 seconds → enter ADC calibration mode
// ➤ Press BUT1 for >6 seconds → reset stored calibration factor
// ➤ Measure the battery with a multimeter *while still connected*
//    (at battery contacts on the bottom of the board)
// ➤ LED blinks fast in calibration mode and flashes 3× on success
// ➤ LED flashes 5× quickly on calibration reset
// ==========================================================

#include <Preferences.h>

#define POWER_SENSE_PIN   25
#define BATTERY_PIN       2
#define BUTTON_PIN        9
#define LED_PIN           8

// Divider ratio (R5+R1)/R5 = 5.7
float resistorCoeff = 5.7;

// ADC calibration coefficient (stored in flash)
Preferences prefs;
float calibrationFactor = 1.0;

// LED control
unsigned long lastBlink = 0;
bool ledState = false;

// Calibration mode flag
bool calibrating = false;

// Button press tracking
unsigned long buttonPressStart = 0;
bool buttonPressed = false;

// ----------------------------------------------------------
// Setup
// ----------------------------------------------------------
void setup() {
  Serial.begin(115200);
  pinMode(POWER_SENSE_PIN, INPUT);
  pinMode(BATTERY_PIN, INPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);

  prefs.begin("adc-calib", false);
  calibrationFactor = prefs.getFloat("factor", 1.0);

  Serial.println("\nESP32-H2-DevKit-LiPo Power & Battery Sense");
  Serial.println("------------------------------------------------");
  Serial.print("Resistor divider coefficient: ");
  Serial.println(resistorCoeff);
  Serial.print("Calibration factor: ");
  Serial.print(calibrationFactor);
  if (prefs.isKey("factor"))
    Serial.println("  (loaded from flash)");
  else
    Serial.println("  (using default)");
  Serial.println("------------------------------------------------\n");
}

// ----------------------------------------------------------
// Main loop
// ----------------------------------------------------------
void loop() {
  unsigned long now = millis();

  // LED blinking pattern
  unsigned long interval = calibrating ? 150 : 800;
  if (now - lastBlink > interval) {
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState);
    lastBlink = now;
  }

  // Button press detection
  if (digitalRead(BUTTON_PIN) == LOW) {
    if (!buttonPressed) {
      buttonPressStart = now;
      buttonPressed = true;
    }
  } else {
    if (buttonPressed) {
      unsigned long pressDuration = now - buttonPressStart;

      if (pressDuration >= 2000 && pressDuration < 6000) {
        // Enter calibration mode
        startCalibration();
      } else if (pressDuration >= 6000) {
        // Reset calibration
        calibrationFactor = 1.0;
        prefs.clear();
        Serial.println("\n*** Calibration data reset! Using default = 1.0 ***");

        // Flash LED 5× to confirm reset
        for (int i = 0; i < 5; i++) {
          digitalWrite(LED_PIN, HIGH);
          delay(150);
          digitalWrite(LED_PIN, LOW);
          delay(150);
        }
      }

      buttonPressed = false;
    }
  }

  // Regular measurement mode
  if (!calibrating) {
    Serial.print("External Power Sense: ");
    Serial.println(digitalRead(POWER_SENSE_PIN));

    int mv = analogReadMilliVolts(BATTERY_PIN);
    float actualMv = mv * resistorCoeff * calibrationFactor;

    Serial.print("Battery Voltage: ");
    Serial.print(actualMv);
    Serial.println(" mV\n");
    delay(500);
  }
}

// ----------------------------------------------------------
// Calibration mode
// ----------------------------------------------------------
void startCalibration() {
  calibrating = true;
  Serial.println("\n=== ADC Calibration Mode ===");
  Serial.println("Measure the battery with a multimeter (while connected).");
  Serial.println("Enter the measured voltage in millivolts (e.g., 4120):");

  while (true) {
    if (Serial.available()) {
      String input = Serial.readStringUntil('\n');
      input.trim();
      float measuredMv = input.toFloat();

      if (measuredMv > 0) {
        int rawMv = analogReadMilliVolts(BATTERY_PIN) * resistorCoeff;
        calibrationFactor = measuredMv / rawMv;

        prefs.putFloat("factor", calibrationFactor);
        Serial.print("Calibration complete! Factor saved: ");
        Serial.println(calibrationFactor);

        // Flash LED 3× to confirm success
        for (int i = 0; i < 3; i++) {
          digitalWrite(LED_PIN, HIGH);
          delay(150);
          digitalWrite(LED_PIN, LOW);
          delay(150);
        }

        calibrating = false;
        Serial.println("Exiting calibration mode.\n");
        break;
      } else {
        Serial.println("Invalid input. Please enter numeric millivolts (e.g., 4120):");
      }
    }
  }
}



Open the serial console, then press and hold button BUT1 for 3 seconds and release to enter calibration mode. If you hold it for 6 seconds or more and release default calibration value of 1.0 will be loaded. Important!!! Measure battery while still connected to the board (at the contacts at the bottom). If you measure the battery while it is disconnected from the board there would be huge discrepancy!!!
#64
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by lmerckx - October 21, 2025, 08:12:34 PM
Indeed, I think the problem is due to the ADC reliability.
I persisted in charging the battery and finally it was full after several hours.

What I didn't understand is that the voltage returned by the ADC is not linear.
It grows fast until a plateau. Then, the ADC returns the same value for a very long period, then it grows again fast until another plateau, etc.
For my battery, these plateau's are around 667 (+/- 3800 mV), 683 (+/- 3890 mV) and 699 (+/- 3990 mV).
When my battery was finally charged and the LED turned off, the value returned by the ADC was 716 (4081.20 mV). But when I checked with the multimeter, the real value was indeed 4,19 V.

So, perhaps I was simply not patient enough and the ADC behavior perturbed me.

Just a last question: to correct the value returned by the ADC and approximately match the real voltage of the battery, can I multiply by 5.87 instead of 5.7. Or is there a better solution for that ?

Thanks again.
#65
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by LubOlimex - October 20, 2025, 03:36:32 PM
It is not perfect here either. The battery seems to be fully charged, the yellow LED turned off (this is indication it is no longer charging) and I get 4143.90 mV ~ 4.14V from the software.

If I measure just the battery it is 4.21V. So the ADC is definitely not perfect.
#66
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by lmerckx - October 20, 2025, 01:43:56 PM
Hello LubOlimex,

Thank you again for your help.

My code is exactly the same for getting the voltage of the battery. Except that now, I also compute an average of 100 values to get a stable value.
Here is a sample of trace:
Voltage: avg = 3804.69 mV - min = 3801.90 mV - max = 3807.60 mV
Voltage: avg = 3804.81 mV - min = 3801.90 mV - max = 3807.60 mV
Voltage: avg = 3804.75 mV - min = 3801.90 mV - max = 3807.60 mV
Voltage: avg = 3805.03 mV - min = 3801.90 mV - max = 3807.60 mV
Voltage: avg = 3804.64 mV - min = 3801.90 mV - max = 3807.60 mV
We can see that minimum and maximum measures are very closed.

The interesting point of your proposal is the results I got with my multimeter.
Measure from the Olimex card: 3804 mV (with or without the USB cable); measure from my multimeter: 3,95 V
I tried to charge the battery for one hour more and made a new measure after:
Measure from the Olimex card: 3804 mV (with or without the USB cable); measure from my multimeter: 3,97 V

It makes me think of a peak reached in the measure that cannot be exceeded.
Can it be a problem with the card ? Or a calibration to do ?
#67
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by LubOlimex - October 20, 2025, 09:47:09 AM
Yes, just set in voltage measurement mode and measure between + and - of battery to see what is the real voltage of the battery and if there is huge difference between the software report.

Meanwhile I also got one board to test here. This is my Arduino code:

#define POWER_SENSE 25
#define BATTERY 2

void setup()
{
  Serial.begin (115200);
  pinMode (POWER_SENSE, INPUT);
  pinMode (BATTERY, INPUT);
}

void loop()
{
  Serial.print ("External power sense: ");
  Serial.println (digitalRead (POWER_SENSE));

  Serial.print ("Battery measurement: ");
  Serial.print (analogReadMilliVolts (BATTERY)*5.7);
  Serial.println (" mV");

  Serial.println ();

  delay (2000);
}

So far the software shows that my battery is 4058.40 mV and the measurement via voltage meter is pretty close at 4060. The charge current is around 75mA, this is expected since after 3.7V DC the charger charges with lower current than the maximum allowed (which is 100mA).
#68
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by lmerckx - October 20, 2025, 09:22:16 AM
No. I suppose I can test it with a simple multimeter between the red and black wires ?
I will try.

Thanks.
#69
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by LubOlimex - October 20, 2025, 09:00:31 AM
Did you measure the voltage of the battery with external tool to compare with the software readings?
#70
ESP32 / Re: ESP32-H2-DevKit-Lipo - Bat...
Last post by lmerckx - October 19, 2025, 11:34:18 AM
Hello,

I tested further like this:
- longer charge of the battery
- use 100 measures of the battery voltage (each 10 ms) and use the average as final value

And indeed, the battery voltage increased slowly as expected until a peak.
But now that this peak is reached, analogReadMilliVolts always returns 667 or 668. So, 3801.90 or 3807.60 mV (after multiplying by 5.7). I expected (like you above) to reach +/- 4200 mV for my battery.
My code for one measurement is simply: analogReadMilliVolts(BATTERY_VOLTAGE_PIN) * 5.7f
as explained in the documentation.
Have you an idea ?

About your last comment, is it possible that the influence of the charger on battery measurement only happens when battery is low ?
Because I noticed it at the beginning but no more now.
Now, I measure the same voltage if the battery and USB are both connected or if it is only the battery.

Sorry for all these questions. And thanks for your support.