Skip to content

Conversation

@imliubo
Copy link
Contributor

@imliubo imliubo commented Nov 21, 2025

Signed-off-by: imliubo imliubo@makingfun.xyz

Implement full NessoBattery class with:

  • AW32001 charger control (charge current/voltage, UVLO, watchdog, Hi-Z mode)
  • BQ27220 fuel gauge telemetry (voltage, current, power, temperature, cycle count)
  • Register enums and named constants replacing magic numbers
  • Datasheet references for all ICs

Description of Change

Add comprehensive battery management API for Arduino Nesso N1 board, providing full control and monitoring capabilities for the onboard AW32001 battery charger and BQ27220 fuel gauge.

Test Scenarios

I have tested my Pull Request on Arduino-esp32 core v3.3.4 with Arduino Nesso N1(ESP32C6) board.

@imliubo imliubo requested a review from P-R-O-C-H-Y as a code owner November 21, 2025 07:50
@github-actions
Copy link
Contributor

github-actions bot commented Nov 21, 2025

Messages
📖 🎉 Good Job! All checks are passing!

👋 Hello imliubo, we appreciate your contribution to this project!


📘 Please review the project's Contributions Guide for key guidelines on code, documentation, testing, and more.

🖊️ Please also make sure you have read and signed the Contributor License Agreement for this project.

Click to see more instructions ...


This automated output is generated by the PR linter DangerJS, which checks if your Pull Request meets the project's requirements and helps you fix potential issues.

DangerJS is triggered with each push event to a Pull Request and modify the contents of this comment.

Please consider the following:
- Danger mainly focuses on the PR structure and formatting and can't understand the meaning behind your code or changes.
- Danger is not a substitute for human code reviews; it's still important to request a code review from your colleagues.
- To manually retry these Danger checks, please navigate to the Actions tab and re-run last Danger workflow.

Review and merge process you can expect ...


We do welcome contributions in the form of bug reports, feature requests and pull requests.

1. An internal issue has been created for the PR, we assign it to the relevant engineer.
2. They review the PR and either approve it or ask you for changes or clarifications.
3. Once the GitHub PR is approved we do the final review, collect approvals from core owners and make sure all the automated tests are passing.
- At this point we may do some adjustments to the proposed change, or extend it by adding tests or documentation.
4. If the change is approved and passes the tests it is merged into the default branch.

Generated by 🚫 dangerJS against dca94e1

@me-no-dev
Copy link
Member

@facchinm PTAL

@imliubo imliubo force-pushed the feat(boards-nesso-n1) branch 2 times, most recently from 406813a to f943806 Compare November 21, 2025 08:40
Copy link
Contributor

@facchinm facchinm left a comment

Choose a reason for hiding this comment

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

LGTM!

@imliubo imliubo force-pushed the feat(boards-nesso-n1) branch from f943806 to 366d26a Compare November 21, 2025 08:53
@imliubo
Copy link
Contributor Author

imliubo commented Nov 21, 2025

Sorry, final default parameter adjustments were made :)

Signed-off-by: imliubo <imliubo@makingfun.xyz>

Implement full NessoBattery class with:
- AW32001 charger control (charge current/voltage, UVLO, watchdog, Hi-Z mode)
- BQ27220 fuel gauge telemetry (voltage, current, power, temperature, cycle count)
- Register enums and named constants replacing magic numbers
- Datasheet references for all ICs
@imliubo imliubo force-pushed the feat(boards-nesso-n1) branch from 366d26a to dca94e1 Compare November 21, 2025 09:21
@Jason2866
Copy link
Collaborator

Jason2866 commented Nov 21, 2025

Imho, adding code which conflicts to the driver library from the manufacturer https://github.com/M5Stack/M5Unified is not the best idea.
Arduino just sells this device under its name (without providing any real support)

@lucasssvaz
Copy link
Member

lucasssvaz commented Nov 21, 2025

@Jason2866 AFAIK Li Bo works for M5Stack. I think this is intended. (although I agree it would be best to avoid conflicts if possible)

@P-R-O-C-H-Y P-R-O-C-H-Y added Type: 3rd party Boards Related to third-party/non-Espressif hardware boards. Status: Pending Merge Pull Request is ready to be merged labels Nov 24, 2025
@imliubo
Copy link
Contributor Author

imliubo commented Nov 24, 2025

Hi all,
Let me explain why I made these changes.
First, we find that the Nesso N1 might enter a state where it cannot power on or charge. In this state, shorting the battery is the only way to fix.
Our testing revealed that this is related to the AW32001 configuration, so I added many power-related APIs to prevent the device from entering this state.
The original code only enabled charging, which is insufficient in some cases. I also agree that this might conflict with M5Unified, but considering that some users may not be familiar with M5Unified, or dont want use M5Unified, so I have submitted the relevant code here.

If need more detail or info, please let know :).

BR,
BO

@me-no-dev me-no-dev merged commit 56be13b into espressif:master Nov 24, 2025
19 checks passed
@ubidefeo
Copy link

ubidefeo commented Dec 1, 2025

Hi, @me-no-dev :)

This is Ubi from Arduino Team 👋🏼 (cc @facchinm )

We have some users that with the old core versions (no BMS initialisation on NessoBattery::begin()) have incurred in a bricked state (https://forum.arduino.cc/t/dead-nesso-n1-sorta-sad/1416004) after using enableCharge().
Essentially the battery goes under a certain voltage and the device is no longer visible even connecting it with USB-C.

I have found out that powering it externally via GND and 3V3 on the HAT connector the device comes to life and it can ben seen as a serial port over USB-C.
At this point flashing a sketch compiled with the latest code on master and calling .begin() on the battery sets the BMS parameters correctly and the device comes back to life and is usable again.

In order for users to correctly use the battery we need a new release of the core to be made.
Any chance we can expedite this process?

thank you
u.

@me-no-dev
Copy link
Member

Hi @ubidefeo ! Yes, we are looking into posting a new release within a week or two at most. We are holding for a few small fixes in ESP-IDF to propagate down to v5.5 release. If we see that they will take more time than expected, we will release sooner.

@ubidefeo
Copy link

ubidefeo commented Dec 1, 2025

ok, that's fantastic

just FYI, here's a sketch that allows users on 3.3.3 to avoid the battery issue or also to revive it

how to recover after battery depleted using enableCharge on core version 3.3.3

  • power the Nesso N1 using external 3V3 power. It can be any external source, including another Arduino board (see image)
  • connect the USB cable
  • the board will be visible
  • upload the sketch at the bottom of this comment
NessoN1_external_power
#include <Wire.h>

static void writeRegister(uint8_t address, uint8_t reg, uint8_t value) {
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

static uint8_t readRegister(uint8_t address, uint8_t reg) {
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.endTransmission(false);
  Wire.requestFrom(address, 1);
  return Wire.read();
}

static void writeBitRegister(uint8_t address, uint8_t reg, uint8_t bit, uint8_t value) {
  uint8_t val = readRegister(address, reg);
  if (value) {
    writeRegister(address, reg, val | (1 << bit));
  } else {
    writeRegister(address, reg, val & ~(1 << bit));
  }
}

static bool readBitRegister(uint8_t address, uint8_t reg, uint8_t bit) {
  uint8_t val = readRegister(address, reg);
  return ((val & (1 << bit)) > 0);
}

void resetBMS() {
  writeRegister(0x49, 0x1, 0xac);
}

void fixBMS(){
  writeRegister(0x49, 0x1, 0xa2);
}

void enableCharge(bool enable){
  writeBitRegister(0x49, 0x1, 3, !enable);
}

bool isChargeEnabled() {
  return !readBitRegister(0x49, 0x1, 3);
}

void setup() {
  Serial.begin(115200);
  Serial.println("****** SETUP ******");
  Wire.begin();
  delay(1000);
  Serial.print("Charging enabled: ");
  Serial.println(isChargeEnabled() ? "yes": "no");
  fixBMS();
  delay(3000);
}

void loop() {
  Serial.println("****** LOOP ******");
  Serial.print("Charging enabled: ");
  Serial.println(isChargeEnabled() ? "yes": "no");
  
  delay(1000);
}

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

Labels

Status: Pending Merge Pull Request is ready to be merged Type: 3rd party Boards Related to third-party/non-Espressif hardware boards.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants