From a8448faccabdcf5ca1fe05760bbbfb78a1c5e917 Mon Sep 17 00:00:00 2001 From: jaseg Date: Mon, 15 Apr 2019 12:28:22 +0900 Subject: driver/fw: current sensor works --- driver/driver.sch | 2 +- driver_fw/Makefile | 5 +++- driver_fw/ina226.c | 27 ++++++++++++++++++ driver_fw/ina226.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ driver_fw/main.c | 20 ++++++++++++- 5 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 driver_fw/ina226.c create mode 100644 driver_fw/ina226.h diff --git a/driver/driver.sch b/driver/driver.sch index 0abe822..4fa34e9 100644 --- a/driver/driver.sch +++ b/driver/driver.sch @@ -2745,6 +2745,6 @@ F 3 "~" H 17400 2950 50 0001 C CNN 1 0 0 -1 $EndComp Text Notes 7600 10050 0 50 ~ 0 -TODO:\n* RS485 drv fp is wide, should be narrow SOIC-8\n* Heatsink holes are plated-through, shouln't be\n* Add thermal reliefs in upper logic ground plane\n* GND/VCC input labels are swapped\n* White label field for MAC\n* Remove optoisolators\n* Add series resistor to RS485 GND\n* Add decoupling cap next to mosfet temp sensor +TODO:\n* RS485 drv fp is wide, should be narrow SOIC-8\n* Heatsink holes are plated-through, shouln't be\n* Add thermal reliefs in upper logic ground plane\n* GND/VCC input labels are swapped\n* White label field for MAC\n* Remove optoisolators\n* Add series resistor to RS485 GND\n* Add decoupling cap next to mosfet temp sensor\n* Add INA226 filter network (see datasheet p.14) NoConn ~ 14600 2800 $EndSCHEMATC diff --git a/driver_fw/Makefile b/driver_fw/Makefile index 1fb1865..482e265 100644 --- a/driver_fw/Makefile +++ b/driver_fw/Makefile @@ -30,6 +30,9 @@ LDFLAGS += -Tstm32_flash.ld CFLAGS += -I$(CMSIS_DEV_PATH)/Include -I$(CMSIS_PATH)/Include -I$(HAL_PATH)/Inc -Iconfig -I../common #LDFLAGS += -L$(CMSIS_PATH)/Lib/GCC -larm_cortexM0l_math +SOURCES = main.c startup_stm32f030x6.s system_stm32f0xx.c base.c $(HAL_PATH)/Src/stm32f0xx_ll_utils.c cmsis_exports.c \ + ../common/8b10b.c serial.c mac.c i2c.c lcd1602.c mcp9801.c ina226.c + ################################################### .PHONY: program clean @@ -50,7 +53,7 @@ cmsis_exports.c: $(CMSIS_DEV_PATH)/Include/stm32f030x6.h $(CMSIS_PATH)/Include/c %.dot: %.elf r2 -a arm -qc 'aa;agC' $< 2>/dev/null >$@ -main.elf: main.o startup_stm32f030x6.o system_stm32f0xx.o $(HAL_PATH)/Src/stm32f0xx_ll_utils.o cmsis_exports.o ../common/8b10b.o serial.o mac.o i2c.o lcd1602.o mcp9801.o base.o +main.elf: $(SOURCES) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(OBJCOPY) -O ihex $@ $(@:.elf=.hex) $(OBJCOPY) -O binary $@ $(@:.elf=.bin) diff --git a/driver_fw/ina226.c b/driver_fw/ina226.c new file mode 100644 index 0000000..d73703b --- /dev/null +++ b/driver_fw/ina226.c @@ -0,0 +1,27 @@ + +#include "global.h" +#include "i2c.h" +#include "ina226.h" + +void ina226_init() { + /* FIXME plug in final values for I meas backchannel */ + uint16_t config = INA226_CONFIG_AVG_128 | INA226_CONFIG_VBUSCT_204u | INA226_CONFIG_VSHCT_1m1 | + INA226_CONFIG_MODE_SHUNT | INA226_CONFIG_MODE_BUS | INA226_CONFIG_MODE_CONT; + ina226_write_reg(INA226_REG_CONFIG, config); + + ina226_write_reg(INA226_REG_CAL, INA226_CAL); +} + +void ina226_write_reg(uint8_t reg, uint16_t val) { + uint8_t buf[3] = { reg, val>>8, val&0xff }; + i2c_transmit(INA226_I2C_PERIPH, buf, sizeof(buf), INA226_I2C_ADDR, I2C_GENSTOP_YES); +} + +uint16_t ina226_read_reg(uint8_t reg) { + uint8_t buf2[1] = { reg }; + i2c_transmit(INA226_I2C_PERIPH, buf2, sizeof(buf2), INA226_I2C_ADDR, I2C_GENSTOP_NO); + uint8_t rx[2]; + i2c_receive(INA226_I2C_PERIPH, rx, sizeof(rx), INA226_I2C_ADDR); + return (rx[0]<<8) | rx[1]; +} + diff --git a/driver_fw/ina226.h b/driver_fw/ina226.h new file mode 100644 index 0000000..405be48 --- /dev/null +++ b/driver_fw/ina226.h @@ -0,0 +1,84 @@ +#ifndef __INA226_H__ +#define __INA226_H__ + +#include + +#define INA226_I2C_PERIPH I2C1 +#define INA226_I2C_ADDR 0x80 + +#define INA226_I_LSB_uA 2000 +#define INA226_RSHUNT_uOhm 2000 +/* FIXME validate this */ +#define INA226_CAL (5120000 / INA226_I_LSB_uA * 1000 / INA226_RSHUNT_uOhm) + +enum ina226_reg { + INA226_REG_CONFIG = 0x00, + INA226_REG_VS = 0x01, + INA226_REG_VB = 0x02, + INA226_REG_P = 0x03, + INA226_REG_I = 0x04, + INA226_REG_CAL = 0x05, + INA226_REG_MASK_EN = 0x06, + INA226_REG_ALERT = 0x07, + INA226_REG_MFGID = 0xfe, + INA226_REG_DIEID = 0xff +}; + +enum ina226_config { + INA226_CONFIG_RST = 1<<15, + + INA226_CONFIG_AVG_Pos = 9, + INA226_CONFIG_AVG_Msk = 3<<9, + INA226_CONFIG_AVG_1 = 0<<9, + INA226_CONFIG_AVG_4 = 1<<9, + INA226_CONFIG_AVG_16 = 2<<9, + INA226_CONFIG_AVG_64 = 3<<9, + INA226_CONFIG_AVG_128 = 4<<9, + INA226_CONFIG_AVG_256 = 5<<9, + INA226_CONFIG_AVG_512 = 6<<9, + INA226_CONFIG_AVG_1024 = 7<<9, + + INA226_CONFIG_VBUSCT_Pos = 6, + INA226_CONFIG_VBUSCT_Msk = 7<<6, + INA226_CONFIG_VBUSCT_140u = 0<<6, + INA226_CONFIG_VBUSCT_204u = 1<<6, + INA226_CONFIG_VBUSCT_332u = 2<<6, + INA226_CONFIG_VBUSCT_588u = 3<<6, + INA226_CONFIG_VBUSCT_1m1 = 4<<6, + INA226_CONFIG_VBUSCT_2m116 = 5<<6, + INA226_CONFIG_VBUSCT_4m156 = 6<<6, + INA226_CONFIG_VBUSCT_8m244 = 7<<6, + + INA226_CONFIG_VSHCT_Pos = 3, + INA226_CONFIG_VSHCT_Msk = 7<<3, + INA226_CONFIG_VSHCT_140u = 0<<3, + INA226_CONFIG_VSHCT_204u = 1<<3, + INA226_CONFIG_VSHCT_332u = 2<<3, + INA226_CONFIG_VSHCT_588u = 3<<3, + INA226_CONFIG_VSHCT_1m1 = 4<<3, + INA226_CONFIG_VSHCT_2m116 = 5<<3, + INA226_CONFIG_VSHCT_4m156 = 6<<3, + INA226_CONFIG_VSHCT_8m244 = 7<<3, + + INA226_CONFIG_MODE_Pos = 0, + INA226_CONFIG_MODE_Msk = 7, + INA226_CONFIG_MODE_POWERDOWN = 0, + + INA226_CONFIG_MODE_SHUNT = 1, + + INA226_CONFIG_MODE_BUS = 2, + + INA226_CONFIG_MODE_TRIG = 0, + INA226_CONFIG_MODE_CONT = 4 +}; + +void ina226_init(void); +void ina226_write_reg(uint8_t reg, uint16_t val); +uint16_t ina226_read_reg(uint8_t reg); + +static inline int16_t ina226_read_i(void) { return (int16_t)ina226_read_reg(INA226_REG_I); } +static inline int16_t ina226_read_v(void) { return (int16_t)ina226_read_reg(INA226_REG_VB); } +static inline uint16_t ina226_read_p(void) { return ina226_read_reg(INA226_REG_P); } +static inline int16_t ina226_read_vs(void) { return (int16_t)ina226_read_reg(INA226_REG_VS); } + +#endif /* __INA226_H__ */ diff --git a/driver_fw/main.c b/driver_fw/main.c index 5960e23..1cad970 100644 --- a/driver_fw/main.c +++ b/driver_fw/main.c @@ -21,6 +21,7 @@ #include "i2c.h" #include "lcd1602.h" #include "mcp9801.h" +#include "ina226.h" #include <8b10b.h> @@ -161,6 +162,7 @@ int main(void) { using a Java(TM) GUI. */ i2c_enable(I2C1); lcd1602_init(); + ina226_init(); /* The MCP9801 temperature sensor is initialized below in the SysTick ISR since it needs a few milliseconds to * powerup. */ @@ -254,6 +256,11 @@ void SVC_Handler(void) { void PendSV_Handler(void) { } +char hexdigit(uint8_t nibble) { + nibble &= 0xf; + return (nibble < 10) ? ('0' + nibble) : ('A' + nibble - 10); +} + void SysTick_Handler(void) { sys_time_tick++; sys_time_ms += TICK_MS; @@ -271,7 +278,18 @@ void SysTick_Handler(void) { buf[9] = (temp%100)/10 + '0'; buf[11] = temp%10 + '0'; lcd_write_str(0, 0, buf); - lcd_write_str(0, 1, " "" "" "" "); + strcpy(buf, "INA:XXXX""/XXX""X "); + uint16_t rx = ina226_read_i(); + buf[4] = hexdigit(rx>>12); + buf[5] = hexdigit(rx>>8); + buf[6] = hexdigit(rx>>4); + buf[7] = hexdigit(rx>>0); + rx = ina226_read_v(); + buf[9] = hexdigit(rx>>12); + buf[10] = hexdigit(rx>>8); + buf[11] = hexdigit(rx>>4); + buf[12] = hexdigit(rx>>0); + lcd_write_str(0, 1, buf); mcp9801_init(); } -- cgit