MKR WiFi 1010 - Battery circuit operation

Smile6905:
Did you check this... You probably did, just to make sure..

" When the charger is in default mode, REG09[7] is HIGH. When the charger is in host mode, REG09[7] is LOW. After power-on-reset, the device starts in watchdog timer expiration state, or default mode. All the registers are in the default settings.
Any write command to bq24195L, bq24195 transitions the device from default mode to host mode. All the device parameters can be programmed by the host. To keep the device in host mode, the host has to reset the watchdog timer by writing 1 twice to REG01[6] before the watchdog timer expires (REG05[5:4]), or disable watchdog timer by setting REG05[5:4] = 00."

Huh, interesting, I didn't see that. It really looks like after watchdog timer expiry (160sec?) all the registers would be reset.. but the "standard" Arduino core code writes to the bus but doesn't do anything about the watchdog:

I think I have found a bug with the I2C read code - I found it on some forum and it has a requestBytes before an endTransmission. This seems incorrect to me: the address is only written when endTransmission is called. I'm away from the project until later today but will try some more things tonight: reading with the revised code, reading the fault register (just in case).

At this point I wonder if it's worth going a bit over the top, writing a tool which chats with the device on the network, shows all registers at all points with some controls for writing registers, changing pin states, etc. Could display battery ADC too.

I have an intuition there's one more big thing I'm missing though..

kierenj:
At this point I wonder if it's worth going a bit over the top, writing a tool which chats with the device on the network, shows all registers at all points with some controls for writing registers, changing pin states, etc. Could display battery ADC too.

That is what I was interested too, I'm refreshing my programming skills.... You know, I'm a bit old, when I studied engineering we were using assembler only... lol

If you don't mind post your test code, I will fiddle around and see what I discover too.

I have a test app now, can confirm by reading registers that I'm writing them OK.. but can't enable OTG, even when setting PIN_USB_HOST_ENABLE to HIGH / LOW (I'm not sure what it should be). Writing OTG mode to REG01 would only "stick" if the USB power was removed (if it was present, reading back the value got the old one, no OTG mode), which seemed a good sign..

I feel like its the host enable pin then? But it looks clear cut from the schematic. The core code sets it HIGH here - ArduinoCore-samd/samd21_host.c at 020b419fc1dbca49b23b7c0b5e47d50fb2a04485 · arduino/ArduinoCore-samd · GitHub - so why when I write a LOW does nothing change? :frowning:

The test app also allows for reading the battery ADC. It's messy code but I can share if that's helpful @Smile6905?

(Edit: it's here - GitHub - kierenj/bq24195-mkr-wifi-debug )

In a case such as this.. I wonder where I can go for assistance. From time to time this kind of problem seems to crop up and I wish I could put up some cash for someone to help me solve!

I did some more testing with a multimeter.

When the USB_HOST_ENABLE (PA18) pin is high, as it is by default, the OTG pin of the charger IC is low (0V).

When I set the PA18 pin low, and then measure the OTG pin, my multimeter shows 0.16V, slowly falling, as if it's discharging a cap.

I'd expect OTG to go high in this case, am I mistaken?

kierenj:
The test app also allows for reading the battery ADC. It's messy code but I can share if that's helpful @Smile6905?

I will look into I think I can manage :wink:

kierenj:
I'd expect OTG to go high in this case, am I mistaken?

No you're right Q3 will be open and R26 pull up should keep it at 3.3V.

I think the problem might have to do with D+/D- USB lines on the BQ chip (pin 2and 3) being disconnected from the USB port of the MKR board (they go straight into U1)... My understanding is that the BQ chip use the D+/D- lines to set the current limit registry and maybe they're not set correctly... check 8.3.1.3.4 and following, maybe you find something useful there.

Argh this is frustrating!

PA18 is either high @3.3V, which puts the MOSFET output (OTG input) @ 0V..

or PA18 is low @ 0.3V, whereby the MOSFET output (OTG input) sits @ ~0.1V.

Does it make sense that PA18 would go to 0.3V, not 0V, when I write LOW to it?

I've ordered another board, will arrive Monday, in case of some component failure..

kierenj:
Does it make sense that PA18 would go to 0.3V, not 0V, when I write LOW to it?

Yes possible, I don't have this mosfet to test separately but considering, the internal protection diode between D&S and the internal impedance, the pull-up resistors that will generate a small current thought the MS... yes

If you want my advice, get a separate BQ chip and build a small battery dev board, I normally use BQ3055 for more complex battery projects (cell balancing etc..) the chip in MKR board is only good for single cells.

kierenj:
The test app also allows for reading the battery ADC. It's messy code but I can share if that's helpful @Smile6905?

Update: I can read all registry correctly I made a quick sketch for it. See below.
Did you try to set OTG level from your PC or from Arduino code?. I think it matters who's the host, and I still think that not monitoring D+/D- makes the bq chip ignoring OTG alltogether. (which if you think of it for a moment make sense). More interesting reading here FYI: https://www.maximintegrated.com/en/app-notes/index.mvp/id/1822

//
// MKR WiFi 1010 - Battery Voltage monitoring and BQ I2C registry read
//

#include <Wire.h>
#define PMIC_ADDRESS 0x6B

byte reg, val;

void setup() {
Serial.begin(115200);
Wire.begin();

}

void loop() {

// read the input on analog pin 0:
analogReadResolution(12);
int sensorValue = analogRead(ADC_BATTERY);

// Convert the analog reading (which goes from 0 - 4095) to a voltage (0 - 4.208V):
float voltage = sensorValue * (4.208 / 4095.000);

// print out the value you read:
Serial.print(voltage);
Serial.println("V");

reg = 0x08; /// Insert the registry interested

Wire.beginTransmission(PMIC_ADDRESS);
Wire.write((byte)reg);
Wire.endTransmission();

Wire.beginTransmission(PMIC_ADDRESS);
Wire.requestFrom(PMIC_ADDRESS, 1);
Wire.endTransmission();

byte val = Wire.read();
Serial.println(val);

unsigned char byte = val;
unsigned char mask = 1;
unsigned char bits[8];

// Extract the bits
for (int i = 0; i < 8; i++) {
// Mask each bit in the byte and store it
bits = (byte >> i) & mask;

  • Serial.print(i);*
  • Serial.print(" = ");*
    _ Serial.println(bits*);_
    _
    }_
    _
    delay(1000);_
    _
    }*_

It wasn't connected to the PC/USB at all, set using the test app I put together whereby the PC sends a packet via wifi to say set the reg/pin and the Arudino does the job.

I asked on a thread on the TI forums, they responded saying the only criteria for boost mode are those listed. I asked about D+/D- and they said:

"D+/D- is unrelated to the boost operation as it only sets the input current limit during buck operation."

Since I've measured that the OTG pin isn't actually going high, I'm fairly sure that's the cause. I don't understand the purpose of the board having OTG hooked up to an I/O pin if it wasn't intended to be toggled low/high in some circumstances..

I'm wondering how cheeky it would be for me to email Arudino support and ask if the board is faulty - maybe then there's some board design team who has answers? It feels like they really want to provide support via the forum so I'm hesistant.

That sketch looks great btw - should be included in the standard examples for the board!

kierenj:
It wasn't connected to the PC/USB at all, set using the test app I put together whereby the PC sends a packet via wifi to say set the reg/pin and the Arduino does the job.

Send me the registry sequence you use/write (I'm on mac and I don't have a PC, I'll check with my scope on my board and we can see if it works.

kierenj:
That sketch looks great btw - should be included in the standard examples for the board!

Thanks!

It's the following, although the write doesn't "take" unless 5V/USB is not present, i.e. if it's plugged in, the register reverts to the default.

#define PMIC_ADDRESS 0x6B

Wire.beginTransmission(PMIC_ADDRESS);
Wire.write(0x01); // reg 01
Wire.write(0x2B); // 2B = OTG mode (1B = normal)
Wire.endTransmission();

pinMode(PIN_USB_HOST_ENABLE, OUTPUT); // should be the case from standard startup anyway..
digitalWrite(PIN_USB_HOST_ENABLE, LOW); // inverse of startup

kierenj:
It's the following, although the write doesn't "take" unless 5V/USB is not present, i.e. if it's plugged in, the register reverts to the default.

I have a small switch that removes power from the USB bus, so that the serial works on battery :wink:

I have formatted the sketch a bit more:

//*
BQ SET OTG test
Trying 5V power boost on MKR WiFI1010

*/

#include <Wire.h>
#define PMIC_ADDRESS 0x6B

byte val;
byte BQ_REG[10] = { 0x01, 0x2, 0x03, 0x04, 0x05, 0x06,0x07,0x08, 0x09 };
byte OTG = 0x2B;

void setup() {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}

Wire.begin();

// Check battery status
analogReadResolution(12);
int sensorValue = analogRead(ADC_BATTERY);
float voltage = sensorValue * (4.208 / 4095.000);
if (voltage < 3.000) { // BATLOWV REG04[1] = 1 {
Serial.println("Battery voltage below 3.0V - Battery BOOST mode not allowed!");
return;
}
else {
Serial.print("Voltage: ");
Serial.println(voltage);
}

// Check watchdog timer status
Wire.beginTransmission(PMIC_ADDRESS);
Wire.write(BQ_REG[4]); // REG05
Wire.endTransmission();

Wire.beginTransmission(PMIC_ADDRESS);
Wire.requestFrom(PMIC_ADDRESS, 1);
Wire.endTransmission();

val = Wire.read();

Serial.print("Watchdog timer value is: ");
Serial.println(val);

if (val != 154) { // 154 DEC = 9A
Serial.println("Watchdog timer is enabled, we're going to disable it now");
Wire.beginTransmission(PMIC_ADDRESS);
Wire.write(BQ_REG[4]); // REG05
Wire.write(0x9A); // Enable Termination, match ITERM, Set Watchdog timer to 00, Safety timer on, Fast Charge 8hrs
Wire.endTransmission();
}

// Set OTG High and OTG register REG01[4:5] to 10
pinMode(PIN_USB_HOST_ENABLE, OUTPUT);
digitalWrite(PIN_USB_HOST_ENABLE, HIGH); // Set OTG pin High

Wire.beginTransmission(PMIC_ADDRESS);
Wire.write(BQ_REG[0]); // REG 01
Wire.write(OTG); // don't reset, normal watchdog, 10=OTG mode, 1011 = 3.5V min sys voltage
Wire.endTransmission();

}

void loop() { // We dump now all the registries of the BQ chip

for (int r = 0; r < 9; r++) {
Wire.beginTransmission(PMIC_ADDRESS);
Wire.write(BQ_REG[r]);
Wire.endTransmission();

Wire.beginTransmission(PMIC_ADDRESS);
Wire.requestFrom(PMIC_ADDRESS, 1);
Wire.endTransmission();

val = Wire.read();

Serial.print("Register ");
Serial.print(BQ_REG[r]);
Serial.print(" = 0x");
if (val<15)
{
Serial.print("0");
}
Serial.print(val, HEX);
Serial.print(" Bits (0-7) : ");

unsigned char byte = val;
unsigned char mask = 1;
unsigned char bits[8];

// Extract the bits
for (int i = 0; i < 8; i++) {
// Mask each bit in the byte and store it
bits = (byte >> i) & mask;
_ Serial.print(bits*);_
_
Serial.print(" ");_
_
}_
_
Serial.println(" ");_
_
}_
Serial.println(" ");
//pinMode(PIN_USB_HOST_ENABLE, OUTPUT); // should be the case from standard startup anyway..
//digitalWrite(PIN_USB_HOST_ENABLE, LOW); // inverse of startup*

delay(10000);
}
Output with USB power on
Voltage: 4.17
Watchdog timer value is: 138
Watchdog timer is enabled, we're going to disable it now
*Register 1 = 0x1B Bits (0-7) : 1 1 0 1 1 0 0 0 *
*Register 2 = 0x00 Bits (0-7) : 0 0 0 0 0 0 0 0 *
*Register 3 = 0x11 Bits (0-7) : 1 0 0 0 1 0 0 0 *
*Register 4 = 0x9A Bits (0-7) : 0 1 0 1 1 0 0 1 *
*Register 5 = 0x9A Bits (0-7) : 0 1 0 1 1 0 0 1 *
*Register 6 = 0x03 Bits (0-7) : 1 1 0 0 0 0 0 0 *
*Register 7 = 0x0B Bits (0-7) : 1 1 0 1 0 0 0 0 *
*Register 8 = 0x24 Bits (0-7) : 0 0 1 0 0 1 0 0 *
Register 9 = 0x80 Bits (0-7) : 0 0 0 0 0 0 0 1
Output with USB power off
Voltage: 3.99
Watchdog timer value is: 138
Watchdog timer is enabled, we're going to disable it now
*Register 1 = 0x2B Bits (0-7) : 1 1 0 1 0 1 0 0 *
*Register 2 = 0x00 Bits (0-7) : 0 0 0 0 0 0 0 0 *
*Register 3 = 0x11 Bits (0-7) : 1 0 0 0 1 0 0 0 *
*Register 4 = 0x9A Bits (0-7) : 0 1 0 1 1 0 0 1 *
*Register 5 = 0x9A Bits (0-7) : 0 1 0 1 1 0 0 1 *
*Register 6 = 0x03 Bits (0-7) : 1 1 0 0 0 0 0 0 *
*Register 7 = 0x0B Bits (0-7) : 1 1 0 1 0 0 0 0 *
*Register 8 = 0x00 Bits (0-7) : 0 0 0 0 0 0 0 0 *
Register 9 = 0x80 Bits (0-7) : 0 0 0 0 0 0 0 1
I have noticed the following, REG1 not ok stays at 1B despite setting when on USB power, ok on battery to 2B, REG4 ok, REG8[6:7] = 00 As a result not good - Plus I'm getting intermittent watchdog error on REG9
So, still no 5V power out when on battery, last test would be to set OTG pin electrically High... I need to find a USB cable to cut open and see what happens

Oh that's fantastic info, cool! Strange that you see 4.17V ish, not 5V, when plugged in.. was that from the 5V header? (Edit: oh I see, that's the battery ;))

I can see that for USB OTG devices, the USB ID pin (connected to PA18_OTG) is simply grounded. It would be interesting to see either OTG pulled high by force as you say, or also PA18_OTG simply grounded, although it does surprise me since the built-in firmware sets it HIGH by default.. wouldn't that draw too much current and do bad things?

Also - did you try it with digitalWrite(USB_HOST_ENABLE, LOW)? I see that's commented out and you're writing HIGH?

I'm starting to think that PA18 (from the schematic) is intended to be configured as an input. Pulled up by R21, and possibly then to ground via the USB ID pin (grounded for USB OTG cables), then the board could determine if USB OTG is intended.

But then, why would the SAMD21 firmware set the pin as an output and write it HIGH?

I have a replacement board now but don't want to try it for fear of shorting the IO I might be able to use further down the line..

Update: if I write LOW to USB_HOST_ENABLE, then literally attach OTG to 3.3V (wire from 3.3v header to mosfet output), I get a 5v rail! (If I write or keep it at HIGH first, I get 5v too, but also a funky smell. :))

Update 2: the plot thickens. On both my original, and the replacement board, resistor R26 is absent, simply not connected. The board does not match the schematic. I'm not sure what this means..

kierenj:
I'm starting to think that PA18 (from the schematic) is intended to be configured as an input. Pulled up by R21, and possibly then to ground via the USB ID pin (grounded for USB OTG cables), then the board could determine if USB OTG is intended.

I got the components... will test and come back to you shortly

It's fine, it all works. I can get 5V on a battery with:

writeReg(PMIC_REG01, OTG_MODE); // 0x2B
pinMode(PIN_USB_HOST_ENABLE, OUTPUT);
digitalWrite(PIN_USB_HOST_ENABLE, LOW);

My problem all along was that my boards did not have a resistor - R26 - present.

I can detect when USB power is added or removed, and toggle this on/off. There's a little more work to have it start charging when re-attached but pretty soon it'll be working as desired, I think.

kierenj:
My problem all along was that my boards did not have a resistor - R26 - present.

I have the same on 2 boards...

Hi Guys, I came across your discussion of the bq24195. A very nice read.

I have observed something I wanted to reach out and ask if others may have noticed. I am using a MKR WAN 1310 which has the same BQ24195 circuitry as the MKR WIFI 1010. I have been monitoring power consumption and noticed an anomaly when reading the system status register (REG08). It appears that when I read this register, there is a spike in current that lasts for about 1 second. At the moment, when sleeping my current is about 250uA. I noticed that when I read the system status register, the current spikes to 1200uA and stays there for about 1 second. The I2C transaction has long since ended (it lasts about 400us) and I have gone back to sleep. But, for some reason, the bq24195 seems to be doing something and draws about 1mA, which frankly is an unbelievably high current consumption.

This behaviour would suggest it is not a good idea to poll the status of the bq24195 very often or even use it in host mode at all.

Has anyone else noticed this?

sslupsky:
Hi Guys, I came across your discussion of the bq24195. A very nice read.

Sorry for not responding earlier... Thanks we spent quite some time debugging 3 boards with a missing resistor.. quite annoying but useful.

sslupsky:
I have observed something I wanted to reach out and ask if others may have noticed.....

The only thing that I can think of is that it didn't really go to sleep...

You can try to add to your code something like this, to measure if there something executing keeping the MKR awake longer than you expected..

unsigned long start = micros();

// Here you start to measure your function
myFunction();

// At the end you see how long it really took
unsigned long end = micros();
unsigned long elapsed = end - start;
Serial.println(elapsed);

Not familiar with the 1310 specifically so I wouldn't know. Hope that helps
Cheers