BV: add hardware revision variable and identification

This commit is contained in:
King Kévin 2018-02-13 16:19:45 +01:00
parent 400df7c392
commit d75b42377d
2 changed files with 65 additions and 5 deletions

View File

@ -49,6 +49,12 @@ static volatile bool busvoodoo_global_led_blue = false;
/** red LED status */
static volatile bool busvoodoo_global_led_red = false;
/** existing hardware revisions identifiable with voltages */
static const uint8_t busvoodoo_revision_numbers[] = {27};
/** hardware revision voltages (calculated from divider ratios) */
static const float busvoodoo_revision_voltages[] = {100.0/(10.0+100.0)*3.3};
const char* busvoodoo_global_pinout_io[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
const char* busvoodoo_global_pinout_rscan[5] = {NULL, NULL, NULL, NULL, NULL};
@ -58,6 +64,7 @@ const uint32_t busvoodoo_io_pins[13] = {GPIO12, GPIO2, GPIO13, GPIO11, GPIO11, G
const uint8_t busvoodoo_io_groups[13] = {6, 6, 4, 4, 1, 1, 5, 5, 2, 2, 3, 3, 3};
bool busvoodoo_full = false;
uint8_t busvoodoo_revision = 0;
void busvoodoo_setup(void)
{
@ -80,6 +87,48 @@ void busvoodoo_setup(void)
busvoodoo_full = true;
}
// setup ADC to measure hardware revision voltage
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HW_REV_CHANNEL)); // enable clock for GPIO domain for hardware revision channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_REV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_REV_CHANNEL)); // set hardware revision channel as analogue input for the ADC
rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain
adc_off(ADC1); // switch off ADC while configuring it
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable)
adc_enable_temperature_sensor(ADC1); // enable internal voltage reference
adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion
uint8_t rev_channels[] = {ADC_CHANNEL17, ADC_CHANNEL(BUSVOODOO_HW_REV_CHANNEL)}; // voltages to convert: internal, hardware revision
adc_set_regular_sequence(ADC1, LENGTH(rev_channels), rev_channels); // set channels to convert
adc_enable_discontinuous_mode_regular(ADC1, LENGTH(rev_channels)); // convert all channels
adc_power_on(ADC1); // switch on ADC
sleep_us(1); // wait t_stab for the ADC to stabilize
adc_reset_calibration(ADC1); // remove previous non-calibration
adc_calibration(ADC1); // calibrate ADC for less accuracy errors
adc_start_conversion_regular(ADC1); // start conversion to get first voltage
uint16_t channels[LENGTH(rev_channels)] = {0}; // to store the values measured on the channels
for (uint8_t channel_i=0; channel_i<LENGTH(channels); channel_i++) { // get all conversions
while (!adc_eoc(ADC1)); // wait until conversion finished
channels[channel_i] = adc_read_regular(ADC1); // read voltage value (clears flag)
}
float revision_voltage = channels[1]*1.2/channels[0]; // calculate voltage
// find out revision of the board
gpio_set_mode(GPIO(BUSVOODOO_HW_REV_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_HW_REV_PIN)); // use pull up and down to check if a voltage divider is present on the pin
gpio_set(GPIO(BUSVOODOO_HW_REV_PORT), GPIO(BUSVOODOO_HW_REV_PIN)); // pull up
bool rev_up = (0!=gpio_get(GPIO(BUSVOODOO_HW_REV_PORT), GPIO(BUSVOODOO_HW_REV_PIN))); // check if the signal is still up
gpio_clear(GPIO(BUSVOODOO_HW_REV_PORT), GPIO(BUSVOODOO_HW_REV_PIN)); // pull down
bool rev_down = (0==gpio_get(GPIO(BUSVOODOO_HW_REV_PORT), GPIO(BUSVOODOO_HW_REV_PIN))); // check if the signal is still down
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_REV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_REV_CHANNEL)); // put back to analog input
// get revision
if (rev_up && rev_down) { // no voltage divider on pin
busvoodoo_revision = 18; // the pin is floating only for revision 18
} else { // voltage divider on pin
for (uint8_t i=0; i<LENGTH(busvoodoo_revision_numbers) && i<LENGTH(busvoodoo_revision_voltages); i++) { // go through expected revision voltages
if (revision_voltage>busvoodoo_revision_voltages[i]-0.2 && revision_voltage<busvoodoo_revision_voltages[i]+0.2) { // verify if voltage matches
busvoodoo_revision = busvoodoo_revision_numbers[i]; // remember revision number for matching voltage
break; // stop searching
}
}
}
// setup ADC to measure the 5V, 3.3V, LV, and HV power rails voltages
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_5V_CHANNEL)); // enable clock for GPIO domain for 5V channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_5V_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_5V_CHANNEL)); // set 5V channel as analogue input for the ADC
@ -89,14 +138,16 @@ void busvoodoo_setup(void)
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_LV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_LV_CHANNEL)); // set LV channel as analogue input for the ADC
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HV_CHANNEL)); // enable clock for GPIO domain for HV channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HV_CHANNEL)); // set HV channel as analogue input for the ADC
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HW_REV_CHANNEL)); // enable clock for GPIO domain for hardware revision channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_REV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_REV_CHANNEL)); // set hardware revision channel as analogue input for the ADC
rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain
adc_off(ADC1); // switch off ADC while configuring it
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable)
adc_enable_temperature_sensor(ADC1); // enable internal voltage reference
adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion
uint8_t channels[] = {ADC_CHANNEL17, ADC_CHANNEL(BUSVOODOO_5V_CHANNEL), ADC_CHANNEL(BUSVOODOO_3V3_CHANNEL), ADC_CHANNEL(BUSVOODOO_LV_CHANNEL), ADC_CHANNEL(BUSVOODOO_HV_CHANNEL)}; // voltages to convert: internal, 5V, 3.3V, LV, HV
adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channels to convert
adc_enable_discontinuous_mode_regular(ADC1, LENGTH(channels)); // convert all channels
uint8_t rail_channels[] = {ADC_CHANNEL17, ADC_CHANNEL(BUSVOODOO_5V_CHANNEL), ADC_CHANNEL(BUSVOODOO_3V3_CHANNEL), ADC_CHANNEL(BUSVOODOO_LV_CHANNEL), ADC_CHANNEL(BUSVOODOO_HV_CHANNEL)}; // voltages to convert: internal, 5V, 3.3V, LV, HV
adc_set_regular_sequence(ADC1, LENGTH(rail_channels), rail_channels); // set channels to convert
adc_enable_discontinuous_mode_regular(ADC1, LENGTH(rail_channels)); // convert all channels
adc_power_on(ADC1); // switch on ADC
sleep_us(1); // wait t_stab for the ADC to stabilize
adc_reset_calibration(ADC1); // remove previous non-calibration
@ -201,7 +252,7 @@ float busvoodoo_vreg_get(uint8_t channel)
if (channel!=BUSVOODOO_5V_CHANNEL && channel!=BUSVOODOO_3V3_CHANNEL && channel!=BUSVOODOO_LV_CHANNEL && channel!=BUSVOODOO_HV_CHANNEL) { // check channel
return NAN;
}
uint16_t channels[5] = {0}; // to start converted values: internal reference 1.2V, 5V rail, 3.3V rail, LV rail, HV rail
uint16_t channels[5] = {0}; // to start converted values: internal reference 1.2V, 5V rail, 3.3V rail, LV rail, HV rail, hardware version
adc_start_conversion_regular(ADC1); // start conversion to get first voltage
for (uint8_t channel_i=0; channel_i<LENGTH(channels); channel_i++) { // get all conversions
while (!adc_eoc(ADC1)); // wait until conversion finished
@ -619,7 +670,7 @@ const struct menu_command_t busvoodoo_global_commands[] = {
&busvoodoo_global_power,
},
{
'l',
'L',
"LV",
"set voltage on low voltage power rail (0, 0.3-4.8, 5V)",
MENU_ARGUMENT_FLOAT,

View File

@ -97,6 +97,13 @@
#define BUSVOODOO_CAN_RX_PIN 8 /**< CAN Receive input pin */
/** @} */
/** @defgroup busvoodoo_revision ADC pin used to identify hardware revision based on voltage
*/
#define BUSVOODOO_HW_REV_PORT B /**< pin to identify hardware revision */
#define BUSVOODOO_HW_REV_PIN 0 /**< pin to identify hardware revision */
#define BUSVOODOO_HW_REV_CHANNEL 8 /**< ADC to identify hardware revision */
/** @} */
/** BusVoodoo mode interface */
struct busvoodoo_mode_t {
const char* name;
@ -118,6 +125,8 @@ extern const uint8_t busvoodoo_io_groups[13]; /**< which I/O pin (group) does th
/** is the BusVoodoo board fully populated (with HV voltage regulator, RS-232, RS-485, CAN transceiver on the back side) */
extern bool busvoodoo_full;
/** revision of the hardware board */
extern uint8_t busvoodoo_revision;
/** list of supported commands */
extern const struct menu_command_t busvoodoo_global_commands[4];