Skip to content

Commit

Permalink
Implement lights using raspi gpio
Browse files Browse the repository at this point in the history
  • Loading branch information
ConnorWhalen committed Jun 20, 2017
1 parent 17ebd81 commit dd92876
Show file tree
Hide file tree
Showing 20 changed files with 245 additions and 155 deletions.
4 changes: 2 additions & 2 deletions playbooks/files/defaultConfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ rov:
toolingAMotorChannel: 11
toolingBMotorChannel: 5
toolingCMotorChannel: 22
lightAChannel: 23
lightBChannel: 22
lightAPin: 0
lightBPin: 2
altImuSa0High: false
i2cBus: 1
shutdownTimeout: 1000
Expand Down
52 changes: 30 additions & 22 deletions src/main/java/com/easternedgerobotics/rov/Rov.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.easternedgerobotics.rov.event.EventPublisher;
import com.easternedgerobotics.rov.io.Bar30PressureSensor;
import com.easternedgerobotics.rov.io.BluetoothReader;
import com.easternedgerobotics.rov.io.Light;
import com.easternedgerobotics.rov.io.DigitalLight;
import com.easternedgerobotics.rov.io.Motor;
import com.easternedgerobotics.rov.io.Thruster;
import com.easternedgerobotics.rov.io.devices.ADC;
Expand All @@ -17,19 +17,22 @@
import com.easternedgerobotics.rov.io.devices.Bluetooth;
import com.easternedgerobotics.rov.io.devices.Gyroscope;
import com.easternedgerobotics.rov.io.devices.I2C;
import com.easternedgerobotics.rov.io.devices.Light;
import com.easternedgerobotics.rov.io.devices.Magnetometer;
import com.easternedgerobotics.rov.io.devices.PWM;
import com.easternedgerobotics.rov.io.devices.Thermometer;
import com.easternedgerobotics.rov.io.pololu.AltIMU10v3;
import com.easternedgerobotics.rov.io.pololu.Maestro;
import com.easternedgerobotics.rov.io.rpi.RPiGPIOLight;
import com.easternedgerobotics.rov.io.rpi.RaspberryCpuInformation;
import com.easternedgerobotics.rov.io.rpi.RaspberryI2CBus;
import com.easternedgerobotics.rov.math.Range;
import com.easternedgerobotics.rov.value.CameraSpeedValueA;
import com.easternedgerobotics.rov.value.CameraSpeedValueB;
import com.easternedgerobotics.rov.value.HeartbeatValue;
import com.easternedgerobotics.rov.value.LightASpeedValue;
import com.easternedgerobotics.rov.value.LightBSpeedValue;
import com.easternedgerobotics.rov.value.LightAValue;
import com.easternedgerobotics.rov.value.LightBValue;
import com.easternedgerobotics.rov.value.LightValue;
import com.easternedgerobotics.rov.value.PortAftSpeedValue;
import com.easternedgerobotics.rov.value.PortForeSpeedValue;
import com.easternedgerobotics.rov.value.RasprimeCpuValue;
Expand Down Expand Up @@ -80,7 +83,7 @@ final class Rov {

private final List<Motor> motors;

private final List<Light> lights;
private final List<DigitalLight> lights;

private final Accelerometer accelerometer;

Expand Down Expand Up @@ -112,6 +115,7 @@ MaestroChannel extends ADC & PWM> Rov(
final AltIMU imu,
final PressureSensor externalPressure,
final Bluetooth bluetooth,
final List<Light> lightDevices,
final RovConfig rovConfig
) {
this.eventPublisher = eventPublisher;
Expand Down Expand Up @@ -164,6 +168,21 @@ MaestroChannel extends ADC & PWM> Rov(
.setOutputRange(new Range(Motor.MAX_REV, Motor.MAX_FWD)))
));

this.lights = Collections.unmodifiableList(Arrays.asList(
new DigitalLight(
eventPublisher
.valuesOfType(LightAValue.class)
.startWith(new LightAValue())
.cast(LightValue.class),
lightDevices.get(0)),
new DigitalLight(
eventPublisher
.valuesOfType(LightBValue.class)
.startWith(new LightBValue())
.cast(LightValue.class),
lightDevices.get(1))
));

this.thrusters = Collections.unmodifiableList(Arrays.asList(
new Thruster(
eventPublisher
Expand Down Expand Up @@ -209,21 +228,6 @@ MaestroChannel extends ADC & PWM> Rov(
.setOutputRange(new Range(Thruster.MAX_REV, Thruster.MAX_FWD)))
));

this.lights = Collections.unmodifiableList(Arrays.asList(
new Light(
eventPublisher
.valuesOfType(LightASpeedValue.class)
.startWith(new LightASpeedValue())
.cast(SpeedValue.class),
channels.get(config.lightAChannel()).setOutputRange(new Range(Light.MAX_REV, Light.MAX_FWD))),
new Light(
eventPublisher
.valuesOfType(LightBSpeedValue.class)
.startWith(new LightBSpeedValue())
.cast(SpeedValue.class),
channels.get(config.lightBChannel()).setOutputRange(new Range(Light.MAX_REV, Light.MAX_FWD)))
));

internalBarometer = () -> imu.pressure();
magnetometer = () -> imu.rotation();
accelerometer = () -> imu.acceleration();
Expand All @@ -248,7 +252,7 @@ void shutdown() {
}

motors.forEach(Motor::writeZero);
lights.forEach(Light::writeZero);
lights.forEach(DigitalLight::writeZero);
thrusters.forEach(Thruster::writeZero);
bluetooth.stop();
eventPublisher.emit(new RasprimeHeartbeatValue(false));
Expand Down Expand Up @@ -324,12 +328,12 @@ private void doOnSubscribe() {
private void onNext(final HeartbeatValue heartbeat) {
if (heartbeat.getOperational()) {
thrustersUpdate();
lights.forEach(Light::write);
lights.forEach(DigitalLight::write);
motors.forEach(Motor::write);
eventPublisher.emit(new RasprimeHeartbeatValue(true));
} else {
softShutdown();
lights.forEach(Light::flash);
lights.forEach(DigitalLight::flash);
motors.forEach(Motor::writeZero);
eventPublisher.emit(new RasprimeHeartbeatValue(false));
}
Expand Down Expand Up @@ -404,6 +408,10 @@ public static void main(final String[] args) throws InterruptedException, IOExce
rovConfig.bluetoothComPort(),
rovConfig.bluetoothConnectionTimeout(),
rovConfig.bluetoothBaudRate()),
Collections.unmodifiableList(Arrays.asList(
new RPiGPIOLight(rovConfig.lightAPin()),
new RPiGPIOLight(rovConfig.lightBPin())
)),
rovConfig);

Runtime.getRuntime().addShutdownHook(new Thread(rov::shutdown));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ public interface RovConfig {

byte toolingCMotorChannel();

byte lightAChannel();
byte lightAPin();

byte lightBChannel();
byte lightBPin();

boolean altImuSa0High();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ private AnalogToPowerLevel() {
*/
private static final float MAXIMUM = 1.00f;

/**
* Centre of result range.
*/
private static final float MIDDLE = 0.5f;

/**
* Transform an analog pin value into an appropriate power slider value
* with dead-bands at the top and bottom of the slider.
Expand All @@ -46,6 +51,17 @@ public static float convertNeg(final float analogValue) {
return 1f - convert(analogValue);
}

/**
* Transform an analog pin value into an appropriate power slider value
* with dead-bands at the top and bottom of the slider, and 0v is max power.
*
* @param analogValue the input.
* @return power slider value.
*/
public static boolean convertBool(final float analogValue) {
return analogValue > MIDDLE;
}

/**
* Clamp the value between the maximum and minimum supported power values.
*
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/com/easternedgerobotics/rov/io/DigitalLight.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.easternedgerobotics.rov.io;

import com.easternedgerobotics.rov.io.devices.Light;
import com.easternedgerobotics.rov.value.LightValue;

import rx.Observable;

public class DigitalLight {
/**
* The raspi gpio pin being used.
*/
private final Light light;

/**
* The latest value from the speed observable.
*/
private LightValue value;

public DigitalLight(final Observable<LightValue> values, final Light light) {
this.light = light;
values.subscribe(v -> value = v);
}

public final void write() {
light.write(value.getActive());
}

public final void writeZero() {
light.write(false);
}

public final void flash() {
light.flash();
}
}
74 changes: 0 additions & 74 deletions src/main/java/com/easternedgerobotics/rov/io/Light.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.easternedgerobotics.rov.io.devices;

public interface Light {
void write(boolean active);

void flash();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import com.easternedgerobotics.rov.value.ForePowerValue;
import com.easternedgerobotics.rov.value.GlobalPowerValue;
import com.easternedgerobotics.rov.value.HeavePowerValue;
import com.easternedgerobotics.rov.value.LightASpeedValue;
import com.easternedgerobotics.rov.value.LightBSpeedValue;
import com.easternedgerobotics.rov.value.LightAValue;
import com.easternedgerobotics.rov.value.LightBValue;
import com.easternedgerobotics.rov.value.PitchPowerValue;
import com.easternedgerobotics.rov.value.SurgePowerValue;
import com.easternedgerobotics.rov.value.SwayPowerValue;
Expand Down Expand Up @@ -55,11 +55,11 @@ public SliderController(
final Observable<ForePowerValue> fore = io.analogPin(config.forePowerSliderAddress())
.map(AnalogPinValue::getValue).map(AnalogToPowerLevel::convertNeg).map(ForePowerValue::new);

final Observable<LightASpeedValue> lightA = io.analogPin(config.lightAPowerSliderAddress())
.map(AnalogPinValue::getValue).map(AnalogToPowerLevel::convertNeg).map(LightASpeedValue::new);
final Observable<LightAValue> lightA = io.analogPin(config.lightAPowerSliderAddress())
.map(AnalogPinValue::getValue).map(AnalogToPowerLevel::convertBool).map(LightAValue::new);

final Observable<LightBSpeedValue> lightB = io.analogPin(config.lightBPowerSliderAddress())
.map(AnalogPinValue::getValue).map(AnalogToPowerLevel::convertNeg).map(LightBSpeedValue::new);
final Observable<LightBValue> lightB = io.analogPin(config.lightBPowerSliderAddress())
.map(AnalogPinValue::getValue).map(AnalogToPowerLevel::convertBool).map(LightBValue::new);

subscription.addAll(
SourceController.manageMultiViewModel(
Expand Down Expand Up @@ -87,10 +87,10 @@ public SliderController(
eventPublisher.valuesOfType(ForePowerValue.class), v -> { }, scheduler,
fore, eventPublisher::emit, Schedulers.io()),
SourceController.manageMultiViewModel(
eventPublisher.valuesOfType(LightASpeedValue.class), v -> { }, scheduler,
eventPublisher.valuesOfType(LightAValue.class), v -> { }, scheduler,
lightA, eventPublisher::emit, Schedulers.io()),
SourceController.manageMultiViewModel(
eventPublisher.valuesOfType(LightBSpeedValue.class), v -> { }, scheduler,
eventPublisher.valuesOfType(LightBValue.class), v -> { }, scheduler,
lightB, eventPublisher::emit, Schedulers.io()));
}

Expand Down
36 changes: 36 additions & 0 deletions src/main/java/com/easternedgerobotics/rov/io/rpi/RPiGPIOLight.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.easternedgerobotics.rov.io.rpi;

import com.easternedgerobotics.rov.io.devices.Light;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.RaspiPin;

public final class RPiGPIOLight implements Light {
/**
* The raspi gpio pin being used.
*/
private final GpioPinDigitalOutput pin;

/**
* Flashing period for the lights.
*/
private static final int PERIOD = 600;

public RPiGPIOLight(final int pinNumber) {
final GpioController gpioController = GpioFactory.getInstance();
pin = gpioController.provisionDigitalOutputPin(RaspiPin.getPinByName("GPIO " + pinNumber));
}

@Override
public void write(final boolean value) {
pin.setState(value);
}

@Override
public void flash() {
pin.blink(PERIOD);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.easternedgerobotics.rov.value

data class LightAValue(override val active: Boolean = false) : LightValue {
constructor() : this(false)
}

This file was deleted.

Loading

0 comments on commit dd92876

Please sign in to comment.