sysctl: debug charger WIP

This commit is contained in:
Lukas F. Hartmann 2023-12-27 13:07:20 +01:00
parent 5776704735
commit 18286f8b7d
No known key found for this signature in database
GPG Key ID: 376511EB67AD7BAF
1 changed files with 120 additions and 65 deletions

View File

@ -168,6 +168,7 @@ float max_word_to_cap(uint16_t w)
float max_word_to_percentage(uint16_t w) float max_word_to_percentage(uint16_t w)
{ {
// TODO: cap to 100%
float result = ((float)w)*0.00390625; float result = ((float)w)*0.00390625;
return result; return result;
} }
@ -335,7 +336,9 @@ uint8_t fusb_read_message(union pd_msg *msg)
/* If this isn't an SOP message, return error. /* If this isn't an SOP message, return error.
* Because of our configuration, we should be able to assume this means the * Because of our configuration, we should be able to assume this means the
* buffer is empty, and not try to read past a non-SOP message. */ * buffer is empty, and not try to read past a non-SOP message. */
if ((fusb_read_byte(FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS) uint8_t rxb = fusb_read_byte(FUSB_FIFOS);
if (rxb!=0) printf("[rxb] %x\n", rxb);
if ((rxb & FUSB_FIFO_RX_TOKEN_BITS)
!= FUSB_FIFO_RX_SOP) { != FUSB_FIFO_RX_SOP) {
return 1; return 1;
} }
@ -412,13 +415,21 @@ int print_src_fixed_pdo(uint32_t pdo) {
return voltage; return voltage;
} }
int charger_dump() { int charger_configure() {
// TODO: check all MP2650 registers, esp. 4, 7, b
// set input current limit to 2000mA // set input current limit to 2000mA
mps_write_byte(0x00, (1<<5)|(1<<3)); mps_write_byte(0x00, (1<<5)|(1<<3));
// set input voltage limit to 6V (above 5V USB voltage) // set input voltage limit to 6V (above 5V USB voltage)
mps_write_byte(0x01, (1<<6)); mps_write_byte(0x01, (1<<6));
// set charge current limit to 2000mA (1600+400) // set charge current limit to 2000mA (1600+400)
mps_write_byte(0x02, (1<<5)|(1<<3)); mps_write_byte(0x02, (1<<5)|(1<<3));
}
float charger_dump() {
// TODO: if max reports overvoltage (dysbalanced cells),
// can we lower the charging voltage temporarily?
// alternatively, the current
uint8_t status = mps_read_byte(0x13); uint8_t status = mps_read_byte(0x13);
uint8_t fault = mps_read_byte(0x14); uint8_t fault = mps_read_byte(0x14);
@ -439,6 +450,8 @@ int charger_dump() {
uint8_t precharge_c = mps_read_byte(0x03); uint8_t precharge_c = mps_read_byte(0x03);
uint8_t bat_full_v = mps_read_byte(0x04); uint8_t bat_full_v = mps_read_byte(0x04);
int print_charger_info = 1;
if (print_charger_info) {
printf("[charger info]\n"); printf("[charger info]\n");
printf(" status: %x\n", status); printf(" status: %x\n", status);
printf(" fault: %x\n ------------\n", fault); printf(" fault: %x\n ------------\n", fault);
@ -458,25 +471,32 @@ int charger_dump() {
printf(" charge_c: %x\n", charge_c); printf(" charge_c: %x\n", charge_c);
printf(" precharge_c: %x\n", precharge_c); printf(" precharge_c: %x\n", precharge_c);
printf(" bat_full_v: %d\n ============\n", bat_full_v); printf(" bat_full_v: %d\n ============\n", bat_full_v);
if (adc_input_v < 11) {
// renegotiate PD
return 1;
} }
return 0;
return adc_input_v;
} }
void max_dump() { void max_dump() {
// disable write protection (CommStat) // disable write protection (CommStat)
max_write_word(0x61, 0x0000); max_write_word(0x61, 0x0000);
max_write_word(0x61, 0x0000); max_write_word(0x61, 0x0000);
// set pack cfg: 2 cells (0), 1+1 thermistor, 6v charge pump, 11:thtype=10k, btpken on, no aoldo
max_write_word_100(0xb5, (0<<14)|(1<<13)|(0<<11)|(0<<8)|(2<<2)|0);
// fixme set thermistor config // fixme set thermistor config
max_write_word_100(0xca, 0x58ef); //max_write_word_100(0xca, 0x30fb); // for 100k, beta value 4250
// set pack cfg: 2 cells (0), 1 thermistor, 6v charge pump (?), no aoldo, btpken off (??)
max_write_word_100(0xb5, (1<11)|(0<<8)|(0<<2)|0); // TODO: need to enable balancing (zener?)
// nBalCfg
max_write_word(0x61, 0x0000);
max_write_word(0x61, 0x0000);
max_write_word_100(0xd4, (1<<13)|(3<<10)|(3<<5));
uint16_t comm_stat = max_read_word(0x61); uint16_t comm_stat = max_read_word(0x61);
uint16_t status = max_read_word(0x00); uint16_t status = max_read_word(0x00);
uint16_t packcfg = max_read_word_100(0xb5);
uint16_t prot_status = max_read_word(0xd9); uint16_t prot_status = max_read_word(0xd9);
uint16_t prot_alert = max_read_word(0xaf); uint16_t prot_alert = max_read_word(0xaf);
uint16_t prot_cfg2 = max_read_word_100(0xf1); uint16_t prot_cfg2 = max_read_word_100(0xf1);
@ -487,6 +507,7 @@ void max_dump() {
float cell2 = max_word_to_mv(max_read_word(0xd7)); float cell2 = max_word_to_mv(max_read_word(0xd7));
float cell3 = max_word_to_mv(max_read_word(0xd6)); float cell3 = max_word_to_mv(max_read_word(0xd6));
float cell4 = max_word_to_mv(max_read_word(0xd5)); float cell4 = max_word_to_mv(max_read_word(0xd5));
// this value looks good (checked with inducing voltages w/ power supply)
float vpack = max_word_to_pack_mv(max_read_word(0xda)); float vpack = max_word_to_pack_mv(max_read_word(0xda));
float temp = ((float)((int16_t)max_read_word(0x1b)))*(1.0/256.0); float temp = ((float)((int16_t)max_read_word(0x1b)))*(1.0/256.0);
@ -507,6 +528,7 @@ void max_dump() {
printf(" comm_stat: %04x\n", comm_stat); printf(" comm_stat: %04x\n", comm_stat);
printf(" packcfg: %04x\n", packcfg);
printf(" status: %04x\n", status); printf(" status: %04x\n", status);
if (status & 0x8000) { if (status & 0x8000) {
printf(" `-- prot alert\n"); printf(" `-- prot alert\n");
@ -845,7 +867,7 @@ void on_uart_rx() {
} }
int main() { int main() {
set_sys_clock_48mhz(); //set_sys_clock_48mhz();
stdio_init_all(); stdio_init_all();
@ -952,11 +974,11 @@ int main() {
// https://www.reclaimerlabs.com/blog/2017/2/1/usb-c-for-engineers-part-3 // https://www.reclaimerlabs.com/blog/2017/2/1/usb-c-for-engineers-part-3
sleep_ms(5000);
printf("[pocket-sysctl] entering main loop.\n"); printf("[pocket-sysctl] entering main loop.\n");
while (true) { while (true) {
sleep_ms(1);
while (uart_is_readable(UART_ID)) { while (uart_is_readable(UART_ID)) {
handle_commands(uart_getc(UART_ID)); handle_commands(uart_getc(UART_ID));
} }
@ -964,9 +986,10 @@ int main() {
if (state == 0) { if (state == 0) {
gpio_put(PIN_LED_R, 0); gpio_put(PIN_LED_R, 0);
power_objects = 0; power_objects = 0;
request_sent = 0;
// by default, we output 5V on VUSB // by default, we output 5V on VUSB
gpio_put(PIN_USB_SRC_ENABLE, 1); gpio_put(PIN_USB_SRC_ENABLE, 1); // FIXME
//printf("[pocket-sysctl] state 0\n"); //printf("[pocket-sysctl] state 0\n");
// probe FUSB302BMPX // probe FUSB302BMPX
@ -974,41 +997,61 @@ int main() {
// 1. set auto GoodCRC // 1. set auto GoodCRC
// AUTO_CRC in Switches1 // AUTO_CRC in Switches1
// Address: 03h; Reset Value: 0b0010_0000 // Address: 03h; Reset Value: 0b0010_0000
// TODO: figure out CC direction?
printf("[pocket-sysctl] FUSB probed.\n"); printf("[pocket-sysctl] FUSB probed.\n");
fusb_write_byte(FUSB_RESET, FUSB_RESET_SW_RES); fusb_write_byte(FUSB_RESET, FUSB_RESET_SW_RES);
sleep_us(10);
// turn on all power // turn on all power
fusb_write_byte(FUSB_POWER, 0x0F); fusb_write_byte(FUSB_POWER, 0x0F);
fusb_write_byte(FUSB_CONTROL3, 0x07); // automatic retransmission
//fusb_write_byte(FUSB_CONTROL3, 0x07);
// AUTO_HARDRESET | AUTO_SOFTRESET | 3 retries | AUTO_RETRY
fusb_write_byte(FUSB_CONTROL3, (1<<4) | (1<<3) | (3<<1) | 1);
// flush rx buffer
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
// pdwn means pulldown. 0 = no pull down
/* Measure CC1 */ /* Measure CC1 */
fusb_write_byte(FUSB_SWITCHES0, 0x07); fusb_write_byte(FUSB_SWITCHES0, 4|2|1); // MEAS_CC1|PDWN2 |PDWN1
sleep_us(250); sleep_us(250);
uint8_t cc1 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; uint8_t cc1 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
printf("[pocket-sysctl] CC1: %d\n", cc1); printf("[pocket-sysctl] CC1: %d\n", cc1);
/* Measure CC2 */ /* Measure CC2 */
fusb_write_byte(FUSB_SWITCHES0, 0x0B); fusb_write_byte(FUSB_SWITCHES0, 8|2|1); // MEAS_CC2|PDWN2 |PDWN1
sleep_us(250); sleep_us(250);
uint8_t cc2 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; uint8_t cc2 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
printf("[pocket-sysctl] CC2: %d\n", cc2); printf("[pocket-sysctl] CC2: %d\n", cc2);
// cc1: 0, cc2: 3
// detect orientation
if (cc1 > cc2) { if (cc1 > cc2) {
fusb_write_byte(FUSB_SWITCHES1, 0x25); fusb_write_byte(FUSB_SWITCHES1, 4|1); // |AUTO_CRC|TXCC1
fusb_write_byte(FUSB_SWITCHES0, 0x07); fusb_write_byte(FUSB_SWITCHES0, 4|2|1); // MEAS_CC1|PDWN2 |PDWN1
} else { } else {
fusb_write_byte(FUSB_SWITCHES1, 0x26); fusb_write_byte(FUSB_SWITCHES1, 4|2); // |AUTO_CRC|TXCC2
fusb_write_byte(FUSB_SWITCHES0, 0x0B); fusb_write_byte(FUSB_SWITCHES0, 8|2|1); // MEAS_CC2|PDWN2 |PDWN1
} }
printf("[pocket-sysctl] switches set\n"); printf("[pocket-sysctl] switches set\n");
//fusb_write_byte(FUSB_RESET, FUSB_RESET_PD_RESET); fusb_write_byte(FUSB_RESET, FUSB_RESET_PD_RESET);
// automatic soft reset
// FIXME
//fusb_write_byte(FUSB_CONTROL3, (1<<6) | (1<<4) | (1<<3) | (3<<1) | 1);
//sleep_ms(1);
//fusb_write_byte(FUSB_CONTROL3, (1<<4) | (1<<3) | (3<<1) | 1);
printf("[pocket-sysctl] auto hard/soft reset and retries set.\n");
t = 0; t = 0;
state = 1; state = 1;
} else { } else {
@ -1019,37 +1062,40 @@ int main() {
} }
} else if (state == 1) { } else if (state == 1) {
//printf("[pocket-sysctl] state 2\n"); //printf("[pocket-sysctl] state 1\n");
if (t>2000) { if (t>3000) {
printf("[pocket-sysctl] state 2, timeout, sleep\n"); printf("[pocket-sysctl] state 1, timeout\n");
// save power float input_voltage = charger_dump();
sleep_ms(100); max_dump();
t += 100;
// issue hard reset
fusb_write_byte(FUSB_CONTROL3, (1<<6) | 0x07);
sleep_ms(1);
fusb_write_byte(FUSB_CONTROL3, 0x07);
request_sent = 0;
state = 0;
t = 0; t = 0;
// without batteries, the system dies here (brownout?)
// but the charger might have set up the requested voltage anyway
if (input_voltage < 6) {
fusb_write_byte(FUSB_CONTROL3, (1<<6) | (1<<4) | (1<<3) | (3<<1) | 1);
//sleep_ms(1);
fusb_write_byte(FUSB_CONTROL3, (1<<4) | (1<<3) | (3<<1) | 1);
state = 0;
} else {
state = 3;
}
} }
int res = fusb_read_message(&rx_msg); int res = fusb_read_message(&rx_msg);
if (!res) { if (!res) {
//printf("[pocket-sysctl] s1: charger responds, turning off USB_SRC\n");
// if a charger is responding, turn off our 5V output // if a charger is responding, turn off our 5V output
gpio_put(PIN_USB_SRC_ENABLE, 0); gpio_put(PIN_USB_SRC_ENABLE, 0);
uint8_t msgtype = PD_MSGTYPE_GET(&rx_msg); uint8_t msgtype = PD_MSGTYPE_GET(&rx_msg);
uint8_t numobj = PD_NUMOBJ_GET(&rx_msg); uint8_t numobj = PD_NUMOBJ_GET(&rx_msg);
printf(" msg type: %x numobj: %d\n", msgtype, numobj);
if (msgtype == PD_MSGTYPE_SOURCE_CAPABILITIES) { if (msgtype == PD_MSGTYPE_SOURCE_CAPABILITIES) {
int max_voltage = 0; int max_voltage = 0;
for (int i=0; i<numobj; i++) { for (int i=0; i<numobj; i++) {
uint32_t pdo = rx_msg.obj[i]; uint32_t pdo = rx_msg.obj[i];
if ((pdo & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { if ((pdo & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
int voltage = print_src_fixed_pdo(pdo); int voltage = print_src_fixed_pdo(pdo);
if (voltage > max_voltage && voltage <= 20) { if (voltage > max_voltage && voltage <= 20) {
@ -1057,7 +1103,7 @@ int main() {
max_voltage = voltage; max_voltage = voltage;
} }
} else { } else {
printf("not a fixed PDO: %08x\n", pdo); printf("[pocket-sysctl] s1: not a fixed PDO: %08x\n", pdo);
} }
} }
if (!request_sent) { if (!request_sent) {
@ -1066,11 +1112,16 @@ int main() {
} }
} else if (msgtype == PD_MSGTYPE_PS_RDY) { } else if (msgtype == PD_MSGTYPE_PS_RDY) {
// power supply is ready // power supply is ready
printf("[pocket-sysctl] power supply ready!\n"); printf("[pocket-sysctl] s1: power supply ready!\n");
request_sent = 0; request_sent = 0;
t = 0; t = 0;
state = 3; state = 3;
} else {
printf("[pocket-sysctl] s1: msg type: %x numobj: %d\n", msgtype, numobj);
} }
} else {
//sleep_ms(1);
//printf("[pocket-sysctl] s1: no message\n");
} }
} else if (state == 2) { } else if (state == 2) {
printf("[pocket-sysctl] state 2, requesting PO %d\n", power_objects); printf("[pocket-sysctl] state 2, requesting PO %d\n", power_objects);
@ -1088,23 +1139,32 @@ int main() {
fusb_send_message(&tx); fusb_send_message(&tx);
printf("[pocket-sysctl] request sent.\n"); printf("[pocket-sysctl] s2: request sent.\n");
tx_id_count++; tx_id_count++;
t = 0;
request_sent = 1; request_sent = 1;
state = 1; state = 1;
} else if (state == 3) { } else if (state == 3) {
gpio_put(PIN_LED_R, 1); gpio_put(PIN_LED_R, 1);
gpio_put(PIN_USB_SRC_ENABLE, 0);
charger_configure();
// charging
sleep_ms(1);
// running // running
if (t>2000) { if (t>2000) {
printf("[pocket-sysctl] state 3\n"); printf("[pocket-sysctl] state 3\n");
//i2c_scan(); //i2c_scan();
int renegotiate = charger_dump(); float input_voltage = charger_dump();
max_dump();
if (renegotiate) { if (input_voltage < 6) {
printf("[pocket-sysctl] input voltage below 6v, renegotiate\n");
state = 0; state = 0;
} }
@ -1112,11 +1172,6 @@ int main() {
} }
} }
if (t_report>5000) {
max_dump();
t_report = 0;
}
t++; t++;
t_report++; t_report++;
} }