Skip to content

Commit

Permalink
Merge #237
Browse files Browse the repository at this point in the history
237: Adding support for Booster v1.6 channels r=jordens a=ryan-summers

This PR fixes #233 by adding an additional ON/OFF toggle during the channel initial power-up.

~~It's not currently known if this is sufficient to clear the interlocks in all cases because of the unknown states of the power detectors during the power-up process. If the power detectors create transient voltage outputs that exceed the interlock thresholds, the channels will power up in a tripped state.~~

~~However, the most likely case is that the power detectors will remain low during the power-on process and the interlock will not trip, so there's relatively high confidence that this should address v1.6 concerns.~~

It was discovered that the power detectors did not stay low during initialization, but this was remedied by resetting the interlocks immediately after the channel powered up.

Co-authored-by: Ryan Summers <[email protected]>
Co-authored-by: Robert Jördens <[email protected]>
  • Loading branch information
3 people authored Apr 5, 2023
2 parents 93576b4 + 7181a51 commit 6a13601
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 16 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Support for static IP + netmask and gateway configuration
* NOTE: Boosters that used firmware from before 0.4.0 will return to old network configurations.
To re-enable DHCP, reconfigure the IP address to 0.0.0.0/0
* v1.6 hardware identification is now supported
* Support added for Booster v1.6 hardware

### Changed
* Removed custom `mutex` implementation in favor of leveraging `shared-bus`
Expand Down
2 changes: 1 addition & 1 deletion hitl/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ async def is_enabled() -> bool:
# Lower the interlock threshold so it trips.
print('Setting output interlock threshold to -5 dB, verifying interlock trips')
await booster.settings_interface.command(f'channel/{channel}/output_interlock_threshold',
-5, retain=False)
-5.7, retain=False)

async def is_tripped() -> bool:
_, tlm = await telemetry.get_next_telemetry()
Expand Down
7 changes: 3 additions & 4 deletions src/hardware/booster_channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use stm32f4xx_hal as hal;
use tca9548::{self, Tca9548};

use super::rf_channel::{ChannelPins as RfChannelPins, RfChannel, RfChannelMachine};
use super::{Channel, I2cBusManager, I2cProxy, SystemTimer};
use hal::hal::blocking::delay::DelayUs;
use super::{delay::AsmDelay, Channel, I2cBusManager, I2cProxy, SystemTimer};

/// Represents a control structure for interfacing to booster RF channels.
pub struct BoosterChannels {
Expand Down Expand Up @@ -50,7 +49,7 @@ impl BoosterChannels {
manager: &'static I2cBusManager,
pins: [RfChannelPins; 8],
clock: SystemTimer,
delay: &mut impl DelayUs<u16>,
delay: AsmDelay,
) -> Self {
let mut channels: [Option<RfChannelMachine>; 8] =
[None, None, None, None, None, None, None, None];
Expand All @@ -60,7 +59,7 @@ impl BoosterChannels {
mux.select_bus(Some(idx.into()))
.expect("Failed to select channel");

if let Some(channel) = RfChannel::new(manager, pins, clock, delay) {
if let Some(channel) = RfChannel::new(manager, pins, clock, delay.clone()) {
let mut machine = RfChannelMachine::new(channel);
machine.handle_startup();
channels[idx as usize].replace(machine);
Expand Down
1 change: 1 addition & 0 deletions src/hardware/delay.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use stm32f4xx_hal::hal::blocking::delay::{DelayMs, DelayUs};

#[derive(Clone)]
pub struct AsmDelay {
frequency_us: u32,
frequency_ms: u32,
Expand Down
31 changes: 22 additions & 9 deletions src/hardware/rf_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use mcp3221::Mcp3221;
use microchip_24aa02e48::Microchip24AA02E48;
use minimq::embedded_time::{duration::Extensions, Clock, Instant};

use super::{platform, I2cBusManager, I2cProxy, SystemTimer};
use super::{delay::AsmDelay, platform, I2cBusManager, I2cProxy, SystemTimer};
use crate::{
settings::{
channel_settings::ChannelSettings, channel_settings::ChannelState, BoosterChannelSettings,
Expand All @@ -19,7 +19,7 @@ use stm32f4xx_hal::{
self as hal,
adc::config::SampleTime,
gpio::{Analog, Input, Output},
hal::blocking::delay::DelayUs,
hal::blocking::delay::DelayMs,
};

/// A structure representing power supply measurements of a channel.
Expand Down Expand Up @@ -152,7 +152,7 @@ impl Devices {
/// properly enumerate, the option will be empty. The returend tuple will be (devices, eeprom).
fn new(
manager: &'static I2cBusManager,
delay: &mut impl DelayUs<u16>,
delay: &mut AsmDelay,
) -> Option<(Self, Microchip24AA02E48<I2cProxy>)> {
// The ADS7924 and DAC7571 are present on the booster mainboard, so instantiation
// and communication should never fail.
Expand Down Expand Up @@ -276,6 +276,7 @@ pub struct RfChannel {
pins: ChannelPins,
settings: BoosterChannelSettings,
clock: SystemTimer,
delay: AsmDelay,
}

impl RfChannel {
Expand All @@ -295,15 +296,16 @@ impl RfChannel {
manager: &'static I2cBusManager,
pins: ChannelPins,
clock: SystemTimer,
delay: &mut impl DelayUs<u16>,
mut delay: AsmDelay,
) -> Option<Self> {
// Attempt to instantiate the I2C devices on the channel.
Devices::new(manager, delay).map(|(devices, eeprom)| {
Devices::new(manager, &mut delay).map(|(devices, eeprom)| {
let mut channel = Self {
devices,
pins,
settings: BoosterChannelSettings::new(eeprom),
clock,
delay,
};

channel.apply_output_interlock_threshold().unwrap();
Expand Down Expand Up @@ -621,7 +623,7 @@ mod sm {
Off + Disable = Off,
Off + Fault(ChannelFault) / handle_fault = Blocked(ChannelFault),

Powerup(Instant<SystemTimer>) + Update [check_timeout] = Powered,
Powerup(Instant<SystemTimer>) + Update [check_timeout] / reset_interlocks = Powered,
Powerup(Instant<SystemTimer>) + Disable / start_disable_instant = Powerdown(Instant<SystemTimer>),
Powerup(Instant<SystemTimer>) + Fault(ChannelFault) / handle_fault_instant = Blocked(ChannelFault),

Expand Down Expand Up @@ -671,9 +673,6 @@ impl sm::StateMachineContext for RfChannel {
.set_voltage(3.2)
.expect("Failed to disable RF bias voltage");

// Ensure that the RF output is disabled during the power-up process.
self.disable_rf_switch();

// Start the LM3880 power supply sequencer.
self.pins.enable_power.set_high();

Expand All @@ -682,6 +681,20 @@ impl sm::StateMachineContext for RfChannel {
self.clock.try_now().unwrap() + 200_u32.milliseconds()
}

fn reset_interlocks(&mut self, _: &Instant<SystemTimer>) {
// Next, handle resetting interlocks for v1.6 hardware. The interlocks are reset by a
// falling edge on ON/OFF. Because the bias dac is currently in pinch-off (and the RF
// channel is unpowered), toggling ON/OFF introduces no output transients on the RF
// connectors.
self.pins.signal_on.set_high();

// Note: The delay here are purely to accomodate potential capacitance on the ON/OFF
// rail.
self.delay.delay_ms(1u32);

self.pins.signal_on.set_low();
}

/// Guard against powering up the channel.
///
/// # Returns
Expand Down
2 changes: 1 addition & 1 deletion src/hardware/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ pub fn setup(

let adc = hal::adc::Adc::adc3(device.ADC3, true, config);

BoosterChannels::new(mux, adc, i2c_bus_manager, pins, clock, &mut delay)
BoosterChannels::new(mux, adc, i2c_bus_manager, pins, clock, delay.clone())
};

let buttons = {
Expand Down

0 comments on commit 6a13601

Please sign in to comment.