Skip to content

Commit 5c3e9b9

Browse files
committed
Implement lights using raspi gpio
1 parent 439d12d commit 5c3e9b9

20 files changed

Lines changed: 245 additions & 155 deletions

File tree

playbooks/files/defaultConfig.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ rov:
3939
toolingAMotorChannel: 11
4040
toolingBMotorChannel: 5
4141
toolingCMotorChannel: 22
42-
lightAChannel: 23
43-
lightBChannel: 22
42+
lightAPin: 0
43+
lightBPin: 2
4444
altImuSa0High: false
4545
i2cBus: 1
4646
shutdownTimeout: 1000

src/main/java/com/easternedgerobotics/rov/Rov.java

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import com.easternedgerobotics.rov.event.EventPublisher;
99
import com.easternedgerobotics.rov.io.Bar30PressureSensor;
1010
import com.easternedgerobotics.rov.io.BluetoothReader;
11-
import com.easternedgerobotics.rov.io.Light;
11+
import com.easternedgerobotics.rov.io.DigitalLight;
1212
import com.easternedgerobotics.rov.io.Motor;
1313
import com.easternedgerobotics.rov.io.Thruster;
1414
import com.easternedgerobotics.rov.io.devices.ADC;
@@ -17,19 +17,22 @@
1717
import com.easternedgerobotics.rov.io.devices.Bluetooth;
1818
import com.easternedgerobotics.rov.io.devices.Gyroscope;
1919
import com.easternedgerobotics.rov.io.devices.I2C;
20+
import com.easternedgerobotics.rov.io.devices.Light;
2021
import com.easternedgerobotics.rov.io.devices.Magnetometer;
2122
import com.easternedgerobotics.rov.io.devices.PWM;
2223
import com.easternedgerobotics.rov.io.devices.Thermometer;
2324
import com.easternedgerobotics.rov.io.pololu.AltIMU10v3;
2425
import com.easternedgerobotics.rov.io.pololu.Maestro;
26+
import com.easternedgerobotics.rov.io.rpi.RPiGPIOLight;
2527
import com.easternedgerobotics.rov.io.rpi.RaspberryCpuInformation;
2628
import com.easternedgerobotics.rov.io.rpi.RaspberryI2CBus;
2729
import com.easternedgerobotics.rov.math.Range;
2830
import com.easternedgerobotics.rov.value.CameraSpeedValueA;
2931
import com.easternedgerobotics.rov.value.CameraSpeedValueB;
3032
import com.easternedgerobotics.rov.value.HeartbeatValue;
31-
import com.easternedgerobotics.rov.value.LightASpeedValue;
32-
import com.easternedgerobotics.rov.value.LightBSpeedValue;
33+
import com.easternedgerobotics.rov.value.LightAValue;
34+
import com.easternedgerobotics.rov.value.LightBValue;
35+
import com.easternedgerobotics.rov.value.LightValue;
3336
import com.easternedgerobotics.rov.value.PortAftSpeedValue;
3437
import com.easternedgerobotics.rov.value.PortForeSpeedValue;
3538
import com.easternedgerobotics.rov.value.RasprimeCpuValue;
@@ -80,7 +83,7 @@ final class Rov {
8083

8184
private final List<Motor> motors;
8285

83-
private final List<Light> lights;
86+
private final List<DigitalLight> lights;
8487

8588
private final Accelerometer accelerometer;
8689

@@ -112,6 +115,7 @@ MaestroChannel extends ADC & PWM> Rov(
112115
final AltIMU imu,
113116
final PressureSensor externalPressure,
114117
final Bluetooth bluetooth,
118+
final List<Light> lightDevices,
115119
final RovConfig rovConfig
116120
) {
117121
this.eventPublisher = eventPublisher;
@@ -164,6 +168,21 @@ MaestroChannel extends ADC & PWM> Rov(
164168
.setOutputRange(new Range(Motor.MAX_REV, Motor.MAX_FWD)))
165169
));
166170

171+
this.lights = Collections.unmodifiableList(Arrays.asList(
172+
new DigitalLight(
173+
eventPublisher
174+
.valuesOfType(LightAValue.class)
175+
.startWith(new LightAValue())
176+
.cast(LightValue.class),
177+
lightDevices.get(0)),
178+
new DigitalLight(
179+
eventPublisher
180+
.valuesOfType(LightBValue.class)
181+
.startWith(new LightBValue())
182+
.cast(LightValue.class),
183+
lightDevices.get(1))
184+
));
185+
167186
this.thrusters = Collections.unmodifiableList(Arrays.asList(
168187
new Thruster(
169188
eventPublisher
@@ -209,21 +228,6 @@ MaestroChannel extends ADC & PWM> Rov(
209228
.setOutputRange(new Range(Thruster.MAX_REV, Thruster.MAX_FWD)))
210229
));
211230

212-
this.lights = Collections.unmodifiableList(Arrays.asList(
213-
new Light(
214-
eventPublisher
215-
.valuesOfType(LightASpeedValue.class)
216-
.startWith(new LightASpeedValue())
217-
.cast(SpeedValue.class),
218-
channels.get(config.lightAChannel()).setOutputRange(new Range(Light.MAX_REV, Light.MAX_FWD))),
219-
new Light(
220-
eventPublisher
221-
.valuesOfType(LightBSpeedValue.class)
222-
.startWith(new LightBSpeedValue())
223-
.cast(SpeedValue.class),
224-
channels.get(config.lightBChannel()).setOutputRange(new Range(Light.MAX_REV, Light.MAX_FWD)))
225-
));
226-
227231
internalBarometer = () -> imu.pressure();
228232
magnetometer = () -> imu.rotation();
229233
accelerometer = () -> imu.acceleration();
@@ -248,7 +252,7 @@ void shutdown() {
248252
}
249253

250254
motors.forEach(Motor::writeZero);
251-
lights.forEach(Light::writeZero);
255+
lights.forEach(DigitalLight::writeZero);
252256
thrusters.forEach(Thruster::writeZero);
253257
bluetooth.stop();
254258
eventPublisher.emit(new RasprimeHeartbeatValue(false));
@@ -324,12 +328,12 @@ private void doOnSubscribe() {
324328
private void onNext(final HeartbeatValue heartbeat) {
325329
if (heartbeat.getOperational()) {
326330
thrustersUpdate();
327-
lights.forEach(Light::write);
331+
lights.forEach(DigitalLight::write);
328332
motors.forEach(Motor::write);
329333
eventPublisher.emit(new RasprimeHeartbeatValue(true));
330334
} else {
331335
softShutdown();
332-
lights.forEach(Light::flash);
336+
lights.forEach(DigitalLight::flash);
333337
motors.forEach(Motor::writeZero);
334338
eventPublisher.emit(new RasprimeHeartbeatValue(false));
335339
}
@@ -404,6 +408,10 @@ public static void main(final String[] args) throws InterruptedException, IOExce
404408
rovConfig.bluetoothComPort(),
405409
rovConfig.bluetoothConnectionTimeout(),
406410
rovConfig.bluetoothBaudRate()),
411+
Collections.unmodifiableList(Arrays.asList(
412+
new RPiGPIOLight(rovConfig.lightAPin()),
413+
new RPiGPIOLight(rovConfig.lightBPin())
414+
)),
407415
rovConfig);
408416

409417
Runtime.getRuntime().addShutdownHook(new Thread(rov::shutdown));

src/main/java/com/easternedgerobotics/rov/config/RovConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public interface RovConfig {
3333

3434
byte toolingCMotorChannel();
3535

36-
byte lightAChannel();
36+
byte lightAPin();
3737

38-
byte lightBChannel();
38+
byte lightBPin();
3939

4040
boolean altImuSa0High();
4141

src/main/java/com/easternedgerobotics/rov/control/AnalogToPowerLevel.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ private AnalogToPowerLevel() {
2424
*/
2525
private static final float MAXIMUM = 1.00f;
2626

27+
/**
28+
* Centre of result range.
29+
*/
30+
private static final float MIDDLE = 0.5f;
31+
2732
/**
2833
* Transform an analog pin value into an appropriate power slider value
2934
* with dead-bands at the top and bottom of the slider.
@@ -46,6 +51,17 @@ public static float convertNeg(final float analogValue) {
4651
return 1f - convert(analogValue);
4752
}
4853

54+
/**
55+
* Transform an analog pin value into an appropriate power slider value
56+
* with dead-bands at the top and bottom of the slider, and 0v is max power.
57+
*
58+
* @param analogValue the input.
59+
* @return power slider value.
60+
*/
61+
public static boolean convertBool(final float analogValue) {
62+
return analogValue > MIDDLE;
63+
}
64+
4965
/**
5066
* Clamp the value between the maximum and minimum supported power values.
5167
*
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.easternedgerobotics.rov.io;
2+
3+
import com.easternedgerobotics.rov.io.devices.Light;
4+
import com.easternedgerobotics.rov.value.LightValue;
5+
6+
import rx.Observable;
7+
8+
public class DigitalLight {
9+
/**
10+
* The raspi gpio pin being used.
11+
*/
12+
private final Light light;
13+
14+
/**
15+
* The latest value from the speed observable.
16+
*/
17+
private LightValue value;
18+
19+
public DigitalLight(final Observable<LightValue> values, final Light light) {
20+
this.light = light;
21+
values.subscribe(v -> value = v);
22+
}
23+
24+
public final void write() {
25+
light.write(value.getActive());
26+
}
27+
28+
public final void writeZero() {
29+
light.write(false);
30+
}
31+
32+
public final void flash() {
33+
light.flash();
34+
}
35+
}

src/main/java/com/easternedgerobotics/rov/io/Light.java

Lines changed: 0 additions & 74 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.easternedgerobotics.rov.io.devices;
2+
3+
public interface Light {
4+
void write(boolean active);
5+
6+
void flash();
7+
}

src/main/java/com/easternedgerobotics/rov/io/panel/SliderController.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
import com.easternedgerobotics.rov.value.ForePowerValue;
1111
import com.easternedgerobotics.rov.value.GlobalPowerValue;
1212
import com.easternedgerobotics.rov.value.HeavePowerValue;
13-
import com.easternedgerobotics.rov.value.LightASpeedValue;
14-
import com.easternedgerobotics.rov.value.LightBSpeedValue;
13+
import com.easternedgerobotics.rov.value.LightAValue;
14+
import com.easternedgerobotics.rov.value.LightBValue;
1515
import com.easternedgerobotics.rov.value.PitchPowerValue;
1616
import com.easternedgerobotics.rov.value.SurgePowerValue;
1717
import com.easternedgerobotics.rov.value.SwayPowerValue;
@@ -55,11 +55,11 @@ public SliderController(
5555
final Observable<ForePowerValue> fore = io.analogPin(config.forePowerSliderAddress())
5656
.map(AnalogPinValue::getValue).map(AnalogToPowerLevel::convertNeg).map(ForePowerValue::new);
5757

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

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

6464
subscription.addAll(
6565
SourceController.manageMultiViewModel(
@@ -87,10 +87,10 @@ public SliderController(
8787
eventPublisher.valuesOfType(ForePowerValue.class), v -> { }, scheduler,
8888
fore, eventPublisher::emit, Schedulers.io()),
8989
SourceController.manageMultiViewModel(
90-
eventPublisher.valuesOfType(LightASpeedValue.class), v -> { }, scheduler,
90+
eventPublisher.valuesOfType(LightAValue.class), v -> { }, scheduler,
9191
lightA, eventPublisher::emit, Schedulers.io()),
9292
SourceController.manageMultiViewModel(
93-
eventPublisher.valuesOfType(LightBSpeedValue.class), v -> { }, scheduler,
93+
eventPublisher.valuesOfType(LightBValue.class), v -> { }, scheduler,
9494
lightB, eventPublisher::emit, Schedulers.io()));
9595
}
9696

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.easternedgerobotics.rov.io.rpi;
2+
3+
import com.easternedgerobotics.rov.io.devices.Light;
4+
5+
import com.pi4j.io.gpio.GpioController;
6+
import com.pi4j.io.gpio.GpioFactory;
7+
import com.pi4j.io.gpio.GpioPinDigitalOutput;
8+
import com.pi4j.io.gpio.RaspiPin;
9+
10+
public final class RPiGPIOLight implements Light {
11+
/**
12+
* The raspi gpio pin being used.
13+
*/
14+
private final GpioPinDigitalOutput pin;
15+
16+
/**
17+
* Flashing period for the lights.
18+
*/
19+
private static final int PERIOD = 600;
20+
21+
public RPiGPIOLight(final int pinNumber) {
22+
final GpioController gpioController = GpioFactory.getInstance();
23+
pin = gpioController.provisionDigitalOutputPin(RaspiPin.getPinByName("GPIO " + pinNumber));
24+
}
25+
26+
@Override
27+
public void write(final boolean value) {
28+
pin.setState(value);
29+
}
30+
31+
@Override
32+
public void flash() {
33+
pin.blink(PERIOD);
34+
}
35+
36+
}

src/main/kotlin/com/easternedgerobotics/rov/value/LightASpeedValue.kt

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)