commit 7e64ff3ffa6b0283552d93ad2f2a15aeb29712e1
parent 31b6eb5c43cfae83b2156b5e884d17b942bc73ea
Author: Lukas F. Hartmann <lukas@mntre.com>
Date: Wed, 5 Apr 2023 18:54:08 +0200
lpc-fw: mb2.5 support WIP
Diffstat:
1 file changed, 91 insertions(+), 22 deletions(-)
diff --git a/reform2-lpc-fw/src/boards/reform2/board_reform2.c b/reform2-lpc-fw/src/boards/reform2/board_reform2.c
@@ -35,13 +35,14 @@
#define REFORM_MBREV_R1 11
#define REFORM_MBREV_R2 12 // stock R2
#define REFORM_MBREV_R3 13 // R2 with "NTC instead of RNG/SS" fix
+#define REFORM_MBREV_25_R1 25 // motherboard 2.5
// don't forget to set this to the correct rev for your motherboard!
-#define REFORM_MOTHERBOARD_REV REFORM_MBREV_R3
+#define REFORM_MOTHERBOARD_REV REFORM_MBREV_25_R1
//#define REF2_DEBUG 1
#define FW_STRING1 "MREF2LPC"
-#define FW_STRING2 "R3"
-#define FW_STRING3 "20220621"
+#define FW_STRING2 "R4"
+#define FW_STRING3 "20230208"
#define FW_REV FW_STRING1 FW_STRING2 FW_STRING3
#define POWERSAVE_SLEEP_SECONDS 1
@@ -76,7 +77,7 @@ err_t i2c_write8(uint8_t i2c_addr, uint8_t reg, uint8_t value)
return ERROR_NONE;
}
-int16_t i2c_read16_le(uint8_t i2c_addr, uint8_t reg)
+int16_t i2c_read16_be(uint8_t i2c_addr, uint8_t reg)
{
i2c_write_len = 2;
i2c_read_len = 2;
@@ -89,7 +90,20 @@ int16_t i2c_read16_le(uint8_t i2c_addr, uint8_t reg)
return value;
}
-int16_t i2c_read16_be(uint8_t i2c_addr, uint8_t reg)
+err_t i2c_write16_be(uint8_t i2c_addr, uint8_t reg, uint16_t value)
+{
+ i2c_write_len = 4;
+ i2c_read_len = 0;
+ i2c_write_buf[0] = i2c_addr << 1;
+ i2c_write_buf[1] = reg;
+ i2c_write_buf[2] = value>>8;
+ i2c_write_buf[3] = value&0xff;
+ i2cEngine();
+
+ return ERROR_NONE;
+}
+
+int16_t i2c_read16_le(uint8_t i2c_addr, uint8_t reg)
{
i2c_write_len = 2;
i2c_read_len = 2;
@@ -102,7 +116,7 @@ int16_t i2c_read16_be(uint8_t i2c_addr, uint8_t reg)
return value;
}
-err_t i2c_write16_be(uint8_t i2c_addr, uint8_t reg, uint16_t value)
+err_t i2c_write16_le(uint8_t i2c_addr, uint8_t reg, uint16_t value)
{
i2c_write_len = 4;
i2c_read_len = 0;
@@ -352,8 +366,8 @@ void reset_discharge_bits() {
// using INA260 current monitor, count amp-secs going in and out of battery
// (battery gauge)
void measure_and_accumulate_current() {
- float raw_volts = (float)i2c_read16_le(INA260_ADDRESS, 0x2);
- float raw_current = (float)i2c_read16_le(INA260_ADDRESS, 0x1);
+ float raw_volts = (float)i2c_read16_be(INA260_ADDRESS, 0x2);
+ float raw_current = (float)i2c_read16_be(INA260_ADDRESS, 0x1);
volts = raw_volts * 0.00125;
current = raw_current * 0.001;
@@ -381,6 +395,50 @@ void measure_and_accumulate_current() {
#endif
}
+#define INA233_ADDRESS 0x40
+
+void ina233_calibrate() {
+ /*
+ current_lsb = i_max / (pow(2,15)); // 0.00030517578125 (i_max = 10 amperes)
+ power_lsb = 25 * current_lsb; // 0.00762939453125
+ cal = 0.00512/(r_shunt * current_lsb); // 838.8608 (r_shunt = 0.02 ohms)
+
+ m_c = 1/current_lsb // 3276.8
+ m_b = 1/power_lsb // 131.072
+
+ see also: https://github.com/scottvr/pi-ina233/blob/master/ina233.py
+ */
+
+ uint16_t cal = 838;
+
+ i2c_write16_le(INA233_ADDRESS, 0xd4, cal);
+}
+
+void measure_and_accumulate_current_v25() {
+ float raw_volts = (float)i2c_read16_le(INA233_ADDRESS, 0x88);
+ float raw_current = (float)i2c_read16_le(INA233_ADDRESS, 0x89);
+
+ volts = raw_volts * 0.00125; // TODO adjust for 20mOhms
+ current = raw_current * 0.00030517578125;
+
+ if (current>-0.02 && current<0.02) current = 0; // clamp to zero
+
+ unsigned long thisTime = delayGetSecondsActive();
+ if (lastTime>0 && thisTime>lastTime) {
+ unsigned long secondsPassed = thisTime - lastTime;
+
+ if (secondsPassed >= 1) {
+ lastTime = thisTime;
+
+ // decrease estimated battery capacity
+ //capacity_accu_ampsecs -= current*(secondsPassed);
+ }
+ } else {
+ // timer uninitialized or timer wrap
+ lastTime = thisTime;
+ }
+}
+
void turn_som_power_on(void) {
LPC_GPIO->CLR[1] = (1 << 28); // hold in reset
@@ -389,7 +447,7 @@ void turn_som_power_on(void) {
LPC_GPIO->CLR[1] = (1 << 31); // USB 5v off (R1+)
LPC_GPIO->CLR[0] = (1 << 7); // AUX 3v3 off (R1+)
- if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) {
+ if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1 && REFORM_MOTHERBOARD_REV < REFORM_MBREV_25_R1) {
LPC_GPIO->CLR[1] = (1 << 16); // 3v3 on
LPC_GPIO->CLR[1] = (1 << 15); // 5v on
} else {
@@ -410,7 +468,7 @@ void turn_som_power_on(void) {
void turn_som_power_off(void) {
LPC_GPIO->CLR[1] = (1 << 28); // hold in reset
- if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) {
+ if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1 && REFORM_MOTHERBOARD_REV < REFORM_MBREV_25_R1) {
LPC_GPIO->SET[1] = (1 << 16); // 3v3 off
LPC_GPIO->SET[1] = (1 << 15); // 5v off
} else {
@@ -449,7 +507,7 @@ void turn_aux_power_off(void) {
void brownout_setup(void) {
// Set brownout threshold to 2.63-2.71V (highest level)
- // and enable brownout reset
+ // and enable brownout reset (BODRSTENA)
LPC_SYSCON->BODCTRL = 0x3 | (1<<4);
}
@@ -465,6 +523,8 @@ void watchdog_feed(void) {
void boardInit(void)
{
+ brownout_setup();
+
SystemCoreClockUpdate();
GPIOInit();
delayInit();
@@ -524,6 +584,11 @@ void boardInit(void)
LPC_IOCON->PIO1_13 &= ~0x07;
imx_uart_enabled = false;
+ // motherboard 2.5 introduces INA233 instead of INA260
+ if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_25_R1) {
+ ina233_calibrate();
+ }
+
#ifdef REF2_DEBUG
sprintf(uartBuffer, "\r\nMNT Reform 2.0 MCU initialized.\r\n");
uartSend((uint8_t*)uartBuffer, strlen(uartBuffer));
@@ -664,7 +729,7 @@ void handle_commands() {
// get charger system state
if (state == ST_CHARGE) {
- sprintf(uartBuffer,FW_REV"normal,%d,%d,%d\r",cycles_in_state,min_mah,acc_mah);
+ sprintf(uartBuffer,FW_REV"normal,%f\r",current); //,min_mah,acc_mah);
} else if (state == ST_OVERVOLTED) {
sprintf(uartBuffer,FW_REV"balancing,%d,%d,%d\r",cycles_in_state,min_mah,acc_mah);
} else if (state == ST_COOLDOWN) {
@@ -792,7 +857,7 @@ uint8_t spi_arg1 = 0;
/**
* @brief SPI command from imx poll function
* Attempts to handle spi communication asynchronously and in a non-blocking way.
- *
+ *
*/
void handle_spi_commands() {
STATIC_ASSERT(SSP0_FIFOSIZE >= 8);
@@ -800,7 +865,7 @@ void handle_spi_commands() {
uint8_t len = SSP0_FIFOSIZE;
// non blocking read
- // read until requested buffer full or receive buffer empty
+ // read until requested buffer full or receive buffer empty
for (uint8_t i = 0; i < len; i++ )
{
// No more data in receive buffer
@@ -827,7 +892,7 @@ void handle_spi_commands() {
{
if (spi_cmd_state == ST_EXPECT_MAGIC)
{
- // magic byte found, prevents garbage data
+ // magic byte found, prevents garbage data
// in the bus from triggering a command
if(spiBuf[s] == 0xB5)
{
@@ -845,7 +910,7 @@ void handle_spi_commands() {
spi_cmd_state = ST_EXPECT_RETURN;
}
}
-
+
if (spi_cmd_state != ST_EXPECT_RETURN) {
// waiting for more data
return;
@@ -858,7 +923,7 @@ void handle_spi_commands() {
// clear recieve buffer, reuse as send buffer
memset(spiBuf, 0, 8);
-
+
// execute power state command
if (spi_command == 'p') {
// toggle system power and/or reset imx
@@ -873,10 +938,10 @@ void handle_spi_commands() {
}
if (spi_arg1 == 4) {
turn_aux_power_off();
- }
+ }
if (spi_arg1 == 5) {
turn_aux_power_on();
- }
+ }
spiBuf[0] = som_is_powered;
}
@@ -954,14 +1019,14 @@ void handle_spi_commands() {
}
if (imx_uart_enabled) {
- sprintf(uartBuffer, "spi:res: %X %X %X %X %X %X %X %X\r\n",
+ sprintf(uartBuffer, "spi:res: %X %X %X %X %X %X %X %X\r\n",
spiBuf[0], spiBuf[1], spiBuf[2], spiBuf[3],
spiBuf[4], spiBuf[5], spiBuf[6], spiBuf[7]);
uartSend((uint8_t*)uartBuffer, strlen(uartBuffer));
}
// Host must wait while the LPC prepares response buffer
- // If host does not read 8 bytes the previous response buffer will be stuck in here.
+ // If host does not read 8 bytes the previous response buffer will be stuck in here.
for (uint8_t i = 0; i < SSP0_FIFOSIZE; i++)
LPC_SSP0->DR = spiBuf[i];
@@ -1076,7 +1141,11 @@ int main(void)
// charge current 2: ~0.2A
- measure_and_accumulate_current();
+ if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_25_R1) {
+ measure_and_accumulate_current_v25();
+ } else {
+ measure_and_accumulate_current();
+ }
measure_cell_voltages_and_control_discharge();
calculate_capacity_percentage();