⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Fixed RefCountedDigitalPin.h to release claim correctly to save back 26mA#1569

Open
IoTThinks wants to merge 4 commits intomeshcore-dev:devfrom
IoTThinks:MCdev-Fixed-Incorrect-Release-of-RefCountedDigitalPin
Open

Fixed RefCountedDigitalPin.h to release claim correctly to save back 26mA#1569
IoTThinks wants to merge 4 commits intomeshcore-dev:devfrom
IoTThinks:MCdev-Fixed-Incorrect-Release-of-RefCountedDigitalPin

Conversation

@IoTThinks
Copy link
Contributor

Hi friends,
This is to fix RefCountedDigitalPin.h to release claim correctly and to ensure no negative "claims" number.

Without this, Heltec v4 comsumes extra 26mA in normal mode and in power saving mode when the power to OLED does not cut off in turnOff correctly.
Tested working fine on Heltec v3 and v4.

It should be fine for other boards too.

@Quency-D
Copy link
Contributor

Quency-D commented Feb 2, 2026

Hi @IoTThinks ,Thank you for your hard work, but we believe that #1570 is the correct reason.

@IoTThinks
Copy link
Contributor Author

IoTThinks commented Feb 2, 2026

Ok, let me try yours.

If your PR works then I will close this PR as you have clearer picture than I.

@JDat
Copy link

JDat commented Feb 2, 2026

Ho this is working? Will this code stay on on Heltec v3 +v4 platforms or this code also will impact my PicoW variant? I don't have OLED display and possibly use this GPIO pin for things...

@IoTThinks
Copy link
Contributor Author

IoTThinks commented Feb 3, 2026

Ho this is working? Will this code stay on on Heltec v3 +v4 platforms or this code also will impact my PicoW variant? I don't have OLED display and possibly use this GPIO pin for things...

@JDat If you don't have OLED, this issue will not happen to you.
RefCountedDigitalPin is intended to control the shared vEXT (external power to OLED and sensors).
It should ensure that vExt will be on if there is at least one OLED/sensor is using vext.
And vExt will be off if no OLED/sensor uses vext.

However, the OLED and sensors need to use claim() and release().
So far, only OLEDs are using it.

So no impact for you.
I would like to fix this so the OLED can off correctly and sensors in future can on/off correctly.

@IoTThinks
Copy link
Contributor Author

IoTThinks commented Feb 3, 2026

I will keep this PR for review.
I believe this fix is good for not only OLEDs but also for sensors to activate/deactivate vExt correctly.

The release() function should work correctly on its own.
Thanks a lot.

@Socalix
Copy link

Socalix commented Feb 3, 2026

LGTM. Nice and clean and a generic fix for other use cases as well.

Comment on lines 23 to 28

void release() {
_claims--;
if (_claims == 0) {
digitalWrite(_pin, !_active);
} else {
_claims--;
Copy link
Contributor

@oltaco oltaco Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this mean that if claims == 1 and you call release(), claims is will end up as 0 but you the pin won't be deactivated until you call release an extra time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, true.
Let me adjust.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oltaco We can change to this.
This is fix for future vExt usage.
However, it won't fix the OLED. We may need to fix or revert the SSD1306Display as it does not use vExt at all.

See my comment below. #1569 (comment)

  void release() {
    if (_claims == 0) return; // avoid negative _claims

    _claims--;
    if (_claims == 0) {
      digitalWrite(_pin, !_active);
    }
  }

@IoTThinks
Copy link
Contributor Author

IoTThinks commented Feb 5, 2026

@oltaco : When I fixed it properly, it does not work anymore.
So I explore more and found something more.

This is in powersaving off. So there is no sleep yet.
Expected to have 5x mA after the screen is off. It should not stay at 8x mA.

Don't off the vExt at all and ...save power

 void release() {
    // Do nothing and it uses normal consumption at 5x mA
  }

So we aggressive "off" the vExt, the power is increased at 8x mA

  void release() {
    // This one will have 5x mA at first, then 8x mA
    digitalWrite(_pin, HIGH); // LOW is on, HIGH is off according to the latest platformio.ini
  }

So I can guess LOW = vExt off. HIGH = vExt ON, this is correct based on my previously found docs and same to other Heltec boards.
Now Heltec updated from HIGH to LOW (vExt on = LOW)
https://resource.heltec.cn/download/WiFi_LoRa_32_V4/datasheet/WiFi_LoRa_32_V4.2.0.pdf
image

  void release() {
    // This one will have 5x mA at first, then 5x mA
    digitalWrite(_pin, LOW);
  }

To test further, I guess OLED SSD1306 has nothing related to the vExt at all.
Well, I removed all digitalWrite(_pin,...) and all stuffs inside claim() and release(),
The screen is still on to see "Loading..." and "Heltec v4 repeater..."
And the power is at 5x mA as expected.

class RefCountedDigitalPin {
  uint8_t _pin;
  int8_t _claims = 0;
  uint8_t _active = 0;
public:
  RefCountedDigitalPin(uint8_t pin,uint8_t active=HIGH): _pin(pin), _active(active) { }

  void begin() {
    pinMode(_pin, OUTPUT);
    // digitalWrite(_pin, !_active);  // initial state
  }

  void claim() {
  }

  void release() {
  }

I can conclude SSD1306Display is not powered by vExt at all.
And vExt=LOW means Off instead.

That also explains why MeshCore 1.11.0 worked fine.
As MC 1.11.0 does not need to turn on vExt to use SSD1306Display.
SSD1306Display does not need vExt.

In MC 1.12.0, we turn on vExt unneccessarily.
And incorrectly turn on (instead of off) vExt at release() actually increases the power.

Please correct me if I'm incorrect somewhere.

@IoTThinks
Copy link
Contributor Author

So the fix this is one for future usage.

void release() {
    if (_claims == 0) return; // avoid negative _claims

    _claims--;
    if (_claims == 0) {
      digitalWrite(_pin, !_active);
    }
  }

Then revert the SSD1306Display.h as it does not use vExt at all.
Revert -D PIN_VEXT_EN_ACTIVE=LOW to HIGH again.
And update the Heltec docs to the original vExt on = HIGH.

@IoTThinks
Copy link
Contributor Author

IoTThinks commented Feb 5, 2026

It works perfect now.

  1. The fix for negative claims is for future usage. It should stop at 0.

  2. I keep the vExt for SSD1306Display just in case other boards need vExt for SSD1306Display.
    For Heltec v4, I passed a NULL periph_power to disable all claim() and release().
    Heltec v4 does not use vExt to power on/off SSD1306Display.

Tested on Heltec v4 with screen.

  • Able to show "Please wait..."
  • Able to show "Heltec v4 repeater...."
  • Able to use 5x mA in normal mode
  • Able to auto off the screen after a short while.
  • Able to achieve 13mA in PowerSaving on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants