diff options
-rw-r--r-- | sw/Makefile | 2 | ||||
-rw-r--r-- | sw/ltc2400.cpp | 42 | ||||
-rw-r--r-- | sw/ltc2400.h | 2 | ||||
-rw-r--r-- | sw/main.cpp | 22 |
4 files changed, 46 insertions, 22 deletions
diff --git a/sw/Makefile b/sw/Makefile index 259583d..931455a 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -119,7 +119,7 @@ clean: # Send to device program: $(APP_HEX) $(SIZE) -C $(BUILD_DIR)/$(APP_ELF) - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(PROG) -P $(AVRDUDE_DEV) -p $(AVRDUDE_PART) -U flash:w:$(BUILD_DIR)/$(APP_HEX) -v + $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(PROG) -P $(AVRDUDE_DEV) -p $(AVRDUDE_PART) -U flash:w:$(BUILD_DIR)/$(APP_HEX) -v -B 8 fuse: $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(PROG) -P $(AVRDUDE_DEV) -p $(AVRDUDE_PART) -U lfuse:w:0x7e:m -U hfuse:w:0xd9:m -U efuse:w:0xfc:m -v diff --git a/sw/ltc2400.cpp b/sw/ltc2400.cpp index a221029..f0cfa13 100644 --- a/sw/ltc2400.cpp +++ b/sw/ltc2400.cpp @@ -66,6 +66,7 @@ #include <avr/io.h> #include <avr/interrupt.h> +#include <util/delay.h> #include "ltc2400.h" static void cs_low() @@ -82,10 +83,9 @@ static void cs_high() sei(); } -void ltc2400_init() +static void spi_en() { cli(); - // Set SPI Enable and Master mode, // bit order=MSB first (DORD=0), // SPI mode=0 (CPOL=0, CPHA=0) @@ -103,31 +103,46 @@ void ltc2400_init() // 1 0 1 fosc/64 // 1 1 1 fosc/128 // - // Set SPR1 for /32 - SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1); + // Set SPR0 for /8 + SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0); SPSR = 0; // clear SPI2X + sei(); +} +static void spi_dis() +{ + cli(); + PORTB &= ~PINB_SPI_SCK; + SPCR = _BV(MSTR) | _BV(SPR1); sei(); } -bool ltc2400_conversion_ready() +void ltc2400_init() { - return true; -#warning "Clarify usage of SS" + cli(); + PORTB |= PINB_SPI_LTC_CSn; + // Ensure CLK is low so that the device doesn't enter internal SCK mode + PORTB &= ~PINB_SPI_SCK; + sei(); +} +bool ltc2400_conversion_ready() +{ cs_low(); - // EOC == 0 means conversion is complete and device in sleep mode - const int eoc = (PORTB & PINB_SPI_MISO) ? 0 : 1; - cs_high(); + _delay_us(100); - return eoc; + // EOC == 0 means conversion is complete and device in sleep mode + return not (PINB & PINB_SPI_MISO); } -float ltc2400_get_conversion_result(bool& dmy_fault, bool& exr_fault, uint32_t& raw_value) +double ltc2400_get_conversion_result(bool& dmy_fault, bool& exr_fault, uint32_t& raw_value) { + spi_en(); cs_low(); + _delay_us(100); + uint8_t data[4] = {}; for (int i = 0; i < 4; i++) { @@ -137,6 +152,7 @@ float ltc2400_get_conversion_result(bool& dmy_fault, bool& exr_fault, uint32_t& data[i] = SPDR; } + spi_dis(); cs_high(); raw_value = @@ -152,6 +168,6 @@ float ltc2400_get_conversion_result(bool& dmy_fault, bool& exr_fault, uint32_t& const uint32_t adc_value = (raw_value >> 4) & 0x00FFFFFF; // Convert ADC value to voltage - return ((float)adc_value) / ((float)0x00FFFFFF) / 5.0f; + return (double)adc_value / ((double)0x00FFFFFF / 5.0f); } diff --git a/sw/ltc2400.h b/sw/ltc2400.h index d46a24f..05204dd 100644 --- a/sw/ltc2400.h +++ b/sw/ltc2400.h @@ -33,4 +33,4 @@ void ltc2400_init(); bool ltc2400_conversion_ready(); -float ltc2400_get_conversion_result(bool& dmy_fault, bool& exr_fault, uint32_t& raw_value); +double ltc2400_get_conversion_result(bool& dmy_fault, bool& exr_fault, uint32_t& raw_value); diff --git a/sw/main.cpp b/sw/main.cpp index f929c84..94a444a 100644 --- a/sw/main.cpp +++ b/sw/main.cpp @@ -46,7 +46,7 @@ extern "C" { // UART endline is usually CR LF #define ENDL "\r\n" -constexpr double R_SHUNT = 5e-3; // Ohm +constexpr double R_SHUNT = 1e-3; // Ohm /* Capacity counters and thresholds, in As (= Coulombs) * @@ -145,6 +145,7 @@ enum class error_type_t { EEPROM_READ_WARNING, EEPROM_READ_ERROR, EEPROM_WRITE_ERROR, + LTC2400_NOT_READY, LTC2400_DMY_BIT_FAULT, LTC2400_EXTENDED_RANGE_ERROR, RELAY_NOT_SET, @@ -250,7 +251,7 @@ static void handle_thresholds(const timer_t& time_now) previous_capacity = current_capacity; } -static char timestamp_buf[24]; +static char timestamp_buf[32]; static void send_message(const char *message) { snprintf(timestamp_buf, sizeof(timestamp_buf), "TEXT,%ld,", system_timer.get_seconds_atomic()); @@ -289,6 +290,9 @@ static void flag_error(const error_type_t e) case error_type_t::EEPROM_WRITE_ERROR: uart_puts_P("EEPRON write error" ENDL); break; + case error_type_t::LTC2400_NOT_READY: + uart_puts_P("LTC2400 not ready" ENDL); + break; case error_type_t::LTC2400_DMY_BIT_FAULT: uart_puts_P("LTC2400 DMY bit error" ENDL); break; @@ -405,8 +409,7 @@ int main() store_capacity_to_eeprom(); } #endif - - const auto ltc2400_measure_interval = timer_t{0, 100000uL}; + const auto ltc2400_measure_interval = timer_t{0, 200000uL}; if (last_ltc2400_measure + ltc2400_measure_interval < time_now) { last_ltc2400_measure += ltc2400_measure_interval; @@ -414,7 +417,7 @@ int main() bool dmy_fault = false; bool exr_fault = false; uint32_t adc_value = 0; - const float adc_voltage = ltc2400_get_conversion_result(dmy_fault, exr_fault, adc_value); + const double adc_voltage = ltc2400_get_conversion_result(dmy_fault, exr_fault, adc_value); if (dmy_fault) { flag_error(error_type_t::LTC2400_DMY_BIT_FAULT); @@ -426,9 +429,11 @@ int main() /* Vout - 2.5V = Ishunt * Rshunt * 20 */ const double i_shunt = (adc_voltage - 2.5) / (20.0 * R_SHUNT); - capacity_accum += i_shunt * TIMER_TICK_INTERVAL; + capacity_accum += i_shunt * ltc2400_measure_interval.microsecs_ * 1e-6; - snprintf(timestamp_buf, sizeof(timestamp_buf), "DBG,%ld mA" ENDL, lrint(i_shunt * 1000.0)); + snprintf(timestamp_buf, sizeof(timestamp_buf), "DBG,%ldmV,%ldmA" ENDL, + lrint(adc_voltage * 1e3), + lrint(i_shunt * 1e3)); uart_puts(timestamp_buf); if (capacity_accum < 0) { capacity_accum = 0; } @@ -436,6 +441,9 @@ int main() current_capacity = lrint(capacity_accum); } + else { + flag_error(error_type_t::LTC2400_NOT_READY); + } } constexpr auto threshold_calculation_interval_s = 4; |