Skip to content

Commit f2c3201

Browse files
committed
Migrate to an OSCC compatable ADC configuration
Prior to this commit, the ADCs were configured to run with full 12 bit conversions. However this can be an inconvenience for users who wish to use their existing vehicle configuration data without re-calibrating. This commit migrates the 12 bit ADC values back to the original 10 bit domain (vehicle constants) and uses the new HAL ADC conversion resolution parameter for configurations.
1 parent 170a1a9 commit f2c3201

File tree

8 files changed

+92
-44
lines changed

8 files changed

+92
-44
lines changed

Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ version = "0.6.3"
3333
features = ["device"]
3434

3535
[dependencies.oxcc-nucleo-f767zi]
36-
version = "0.1.0"
36+
version = "0.1.1"
3737
features = ["rt"]
3838

3939
[dependencies.num]

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ A port of [Open Source Car Control](https://github.com/jonlamb-gh/oscc) written
88

99
It is built around the traits and patterns provided by the [embedded-hal](https://github.com/rust-embedded/embedded-hal)
1010
project and community:
11-
see the [BSP crate](https://github.com/jonlamb-gh/nucleo-f767zi),
12-
the [HAL crate](https://github.com/jonlamb-gh/stm32f767-hal),
13-
and the [device crate](https://github.com/adamgreig/stm32-rs/tree/master/stm32f7).
11+
see the [BSP crate](https://github.com/jonlamb-gh/oxcc-nucleo-f767zi),
12+
the [HAL crate](https://github.com/jonlamb-gh/oxcc-stm32f767-hal),
13+
and the [device crate](https://github.com/jonlamb-gh/oxcc-stm32f767).
1414

1515
### OSCC Divergence
1616

src/board.rs

Lines changed: 73 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ use dac_mcp4922::Mcp4922;
66
use dac_mcp4922::MODE as DAC_MODE;
77
use dual_signal::HighLowReader;
88
use nucleo_f767zi::debug_console::DebugConsole;
9-
use nucleo_f767zi::hal::adc::{Adc, AdcChannel, AdcPrescaler, AdcSampleTime};
9+
use nucleo_f767zi::hal::adc::Adc;
10+
use nucleo_f767zi::hal::adc::Channel as AdcChannel;
11+
use nucleo_f767zi::hal::adc::Prescaler as AdcPrescaler;
12+
use nucleo_f767zi::hal::adc::Resolution as AdcResolution;
13+
use nucleo_f767zi::hal::adc::SampleTime as AdcSampleTime;
1014
use nucleo_f767zi::hal::can::Can;
1115
use nucleo_f767zi::hal::iwdg::{Iwdg, IwdgConfig, WatchdogTimeout};
1216
use nucleo_f767zi::hal::prelude::*;
@@ -21,31 +25,48 @@ use vehicle::FAULT_HYSTERESIS;
2125

2226
pub use types::*;
2327

28+
/// Control module CAN report frame publish rate
29+
///
30+
/// Brake, throttle and steering modules will publish
31+
/// their report frames to the control CAN bus at
32+
/// this rate.
2433
pub const CAN_PUBLISH_HZ: u32 = 50;
2534

26-
// TODO
27-
// We need to decide on a desired ADC sample time.
28-
//
29-
// The OSCC Arduino modules were likely using the
30-
// default configuration which is about 104 microseconds
31-
// per `analogRead()`.
32-
//
33-
// total conversion time = sampling time + 12 cycles
34-
// ADC clock = APB2 clock / prescaler
35-
// e.g our current config, 216 MHz, APB2 108 MHz
36-
// ADCCLK = 108 / Prescaler4 = 27 MHz
37-
// time = Cycles480 + 12 = 492 cycles == 18.22 us
38-
//
39-
// ADCCLK = 108 / Prescaler6 = 18 MHz
40-
// time = Cycles480 + 12 = 492 cycles == 27.33 us
41-
//
42-
// NOTE: prescaler must be chosen such that the ADC clock
43-
// does not exceed 30 MHz
35+
/// ADC configuration
36+
///
37+
/// The ADC(s) are configured to match the original OSCC
38+
/// Arduino resolution of 10 bits instead of the full 12 bit
39+
/// resolution.
40+
/// This allows existing vehicle configurations to be used without
41+
/// re-calibrating.
42+
///
43+
/// The OSCC Arduino builds were likely using the default ADC
44+
/// configuration which would give about 104 microseconds per
45+
/// `analogRead()`.
46+
///
47+
/// OxCC configures the ADC(s) such that the conversion time
48+
/// is about 18.26 microseconds.
49+
///
50+
/// Total conversion time = sampling time + 13 cycles for 10-bit resolution
51+
/// - APB2 clock = 216 MHz / 2
52+
/// - ADC clock = APB2 clock / prescaler = 108 / Prescaler4 = 27 MHz
53+
/// - conversion time = Cycles480 + 13 = 493 cycles == 18.26 us
54+
///
55+
/// **NOTE**
56+
/// Prescalers must be chosen such that the ADC clock
57+
/// does not exceed 30 MHz
4458
pub const ADC_PRESCALER: AdcPrescaler = AdcPrescaler::Prescaler4;
4559
pub const ADC_SAMPLE_TIME: AdcSampleTime = AdcSampleTime::Cycles480;
46-
47-
// not sure if the averaging is needed, we might be able to just use a
48-
// single read with large Cycles480 sample time?
60+
pub const ADC_RESOLUTION: AdcResolution = AdcResolution::Bits10;
61+
62+
/// Number of analog conversion samples read
63+
/// by the DAC signal discontinuity mechanism.
64+
///
65+
/// **NOTE**
66+
/// This is likely the result of poor ADC hardware on the original
67+
/// OSCC Arduino hardware. I suspect we can get rid of it now that
68+
/// we're using the full conversion time of Cycles480 which is
69+
/// pretty stable.
4970
pub const DAC_SAMPLE_AVERAGE_COUNT: u32 = 20;
5071

5172
pub struct FullBoard {
@@ -199,6 +220,15 @@ impl FullBoard {
199220
// configure maximum clock frequency at 200 MHz
200221
let clocks = rcc.cfgr.freeze_max(&mut flash.acr);
201222

223+
// TODO - this can be moved into the HAL once it's aware of the clocks
224+
let adc_clock = match ADC_PRESCALER {
225+
AdcPrescaler::Prescaler2 => clocks.pclk2().0 / 2,
226+
AdcPrescaler::Prescaler4 => clocks.pclk2().0 / 4,
227+
AdcPrescaler::Prescaler6 => clocks.pclk2().0 / 6,
228+
AdcPrescaler::Prescaler8 => clocks.pclk2().0 / 8,
229+
};
230+
assert!(adc_clock <= 30_000_000);
231+
202232
let mut leds = Leds::new(led_r, led_g, led_b);
203233
for led in leds.iter_mut() {
204234
led.off();
@@ -294,13 +324,31 @@ impl FullBoard {
294324
control_can,
295325
obd_can,
296326
brake_pedal_position_sensor: BrakePedalPositionSensor {
297-
adc1: Adc::adc1(peripherals.ADC1, &mut c_adc, &mut rcc.apb2, ADC_PRESCALER),
327+
adc1: Adc::adc1(
328+
peripherals.ADC1,
329+
&mut c_adc,
330+
&mut rcc.apb2,
331+
ADC_PRESCALER,
332+
ADC_RESOLUTION,
333+
),
298334
},
299335
accelerator_position_sensor: AcceleratorPositionSensor {
300-
adc2: Adc::adc2(peripherals.ADC2, &mut c_adc, &mut rcc.apb2, ADC_PRESCALER),
336+
adc2: Adc::adc2(
337+
peripherals.ADC2,
338+
&mut c_adc,
339+
&mut rcc.apb2,
340+
ADC_PRESCALER,
341+
ADC_RESOLUTION,
342+
),
301343
},
302344
torque_sensor: TorqueSensor {
303-
adc3: Adc::adc3(peripherals.ADC3, &mut c_adc, &mut rcc.apb2, ADC_PRESCALER),
345+
adc3: Adc::adc3(
346+
peripherals.ADC3,
347+
&mut c_adc,
348+
&mut rcc.apb2,
349+
ADC_PRESCALER,
350+
ADC_RESOLUTION,
351+
),
304352
},
305353
brake_dac: Mcp4922::new(brake_spi, brake_nss),
306354
throttle_dac: Mcp4922::new(throttle_spi, throttle_nss),

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ extern crate cortex_m_rt as rt;
1111
#[cfg(feature = "panic-over-semihosting")]
1212
extern crate cortex_m_semihosting;
1313
extern crate embedded_hal;
14-
extern crate oxcc_nucleo_f767zi as nucleo_f767zi;
1514
extern crate num;
15+
extern crate oxcc_nucleo_f767zi as nucleo_f767zi;
1616
#[cfg(feature = "panic-over-abort")]
1717
extern crate panic_abort;
1818
#[cfg(feature = "panic-over-semihosting")]

src/vehicles/kial_niro.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ pub const fn brake_position_to_volts_high(position: f32) -> f32 {
101101
+ BRAKE_SPOOF_HIGH_SIGNAL_VOLTAGE_MIN
102102
}
103103

104-
/// Value of the accelerator position that indicates operator
104+
/// Value of the brake position that indicates operator
105105
/// override. \[steps\]
106-
pub const BRAKE_PEDAL_OVERRIDE_THRESHOLD: u16 = 200 << 2;
106+
pub const BRAKE_PEDAL_OVERRIDE_THRESHOLD: u16 = 200;
107107

108108
/// Minimum value of the high spoof signal that activates the brake
109109
/// lights. \[steps\]
@@ -243,4 +243,4 @@ pub const fn throttle_position_to_volts_high(position: f32) -> f32 {
243243

244244
/// Value of the accelerator position that indicates operator
245245
/// override. \[steps\]
246-
pub const ACCELERATOR_OVERRIDE_THRESHOLD: u32 = 185 << 2;
246+
pub const ACCELERATOR_OVERRIDE_THRESHOLD: u32 = 185;

src/vehicles/kial_soul_ev.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ pub const fn brake_position_to_volts_high(position: f32) -> f32 {
105105
+ BRAKE_SPOOF_HIGH_SIGNAL_VOLTAGE_MIN
106106
}
107107

108-
/// Value of the accelerator position that indicates operator
108+
/// Value of the brake position that indicates operator
109109
/// override. \[steps\]
110-
pub const BRAKE_PEDAL_OVERRIDE_THRESHOLD: u16 = 130 << 2;
110+
pub const BRAKE_PEDAL_OVERRIDE_THRESHOLD: u16 = 130;
111111

112112
/// Minimum value of the low spoof signal that activates the brake
113113
/// lights. \[steps\]
@@ -246,4 +246,4 @@ pub const fn throttle_position_to_volts_high(position: f32) -> f32 {
246246

247247
/// Value of the accelerator position that indicates operator
248248
/// override. \[steps\]
249-
pub const ACCELERATOR_OVERRIDE_THRESHOLD: u32 = 185 << 2;
249+
pub const ACCELERATOR_OVERRIDE_THRESHOLD: u32 = 185;

src/vehicles/kial_soul_petrol.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,6 @@ pub const fn throttle_position_to_volts_high(position: f32) -> f32 {
269269
+ THROTTLE_SPOOF_HIGH_SIGNAL_VOLTAGE_MIN
270270
}
271271

272-
/// Value of the accelerator position that indicates operator
272+
/// Value of the brake position that indicates operator
273273
/// override. \[steps\]
274-
pub const ACCELERATOR_OVERRIDE_THRESHOLD: u32 = 185 << 2;
274+
pub const ACCELERATOR_OVERRIDE_THRESHOLD: u32 = 185;

0 commit comments

Comments
 (0)