@@ -6,7 +6,11 @@ use dac_mcp4922::Mcp4922;
6
6
use dac_mcp4922:: MODE as DAC_MODE ;
7
7
use dual_signal:: HighLowReader ;
8
8
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 ;
10
14
use nucleo_f767zi:: hal:: can:: Can ;
11
15
use nucleo_f767zi:: hal:: iwdg:: { Iwdg , IwdgConfig , WatchdogTimeout } ;
12
16
use nucleo_f767zi:: hal:: prelude:: * ;
@@ -21,31 +25,48 @@ use vehicle::FAULT_HYSTERESIS;
21
25
22
26
pub use types:: * ;
23
27
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.
24
33
pub const CAN_PUBLISH_HZ : u32 = 50 ;
25
34
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
44
58
pub const ADC_PRESCALER : AdcPrescaler = AdcPrescaler :: Prescaler4 ;
45
59
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.
49
70
pub const DAC_SAMPLE_AVERAGE_COUNT : u32 = 20 ;
50
71
51
72
pub struct FullBoard {
@@ -199,6 +220,15 @@ impl FullBoard {
199
220
// configure maximum clock frequency at 200 MHz
200
221
let clocks = rcc. cfgr . freeze_max ( & mut flash. acr ) ;
201
222
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
+
202
232
let mut leds = Leds :: new ( led_r, led_g, led_b) ;
203
233
for led in leds. iter_mut ( ) {
204
234
led. off ( ) ;
@@ -294,13 +324,31 @@ impl FullBoard {
294
324
control_can,
295
325
obd_can,
296
326
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
+ ) ,
298
334
} ,
299
335
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
+ ) ,
301
343
} ,
302
344
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
+ ) ,
304
352
} ,
305
353
brake_dac : Mcp4922 :: new ( brake_spi, brake_nss) ,
306
354
throttle_dac : Mcp4922 :: new ( throttle_spi, throttle_nss) ,
0 commit comments