Skip to content

Implement lights using raspi gpio #328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
49 changes: 27 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.RPiGPIOLightProvider;
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(rovConfig.lightAPin())),
new DigitalLight(
eventPublisher
.valuesOfType(LightBValue.class)
.startWith(new LightBValue())
.cast(LightValue.class),
lightDevices.get(rovConfig.lightBPin()))
));

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,7 @@ public static void main(final String[] args) throws InterruptedException, IOExce
rovConfig.bluetoothComPort(),
rovConfig.bluetoothConnectionTimeout(),
rovConfig.bluetoothBaudRate()),
new RPiGPIOLightProvider(),
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);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.easternedgerobotics.rov.io.rpi;

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

import java.util.AbstractList;
import java.util.RandomAccess;

public final class RPiGPIOLightProvider extends AbstractList<Light> implements RandomAccess {
private static final int PIN_COUNT = 32;

@Override
public Light get(final int index) {
if (index > PIN_COUNT) {
throw new IndexOutOfBoundsException(String.format("This device has only %d gpio pins", PIN_COUNT));
}
return new RPiGPIOLight(index);
}

@Override
public int size() {
return PIN_COUNT;
}
}
Loading