Skip to content

Commit

Permalink
Merge pull request #354 from sourcebots/control-loop-optimisation
Browse files Browse the repository at this point in the history
Remove mode check on analog read
  • Loading branch information
WillB97 authored Aug 6, 2024
2 parents 062f944 + 11f0784 commit 2c4836a
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 36 deletions.
30 changes: 14 additions & 16 deletions sbot/arduino.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ class AnalogPins(IntEnum):
A5 = 19


DIGITAL_READ_MODES = {GPIOPinMode.INPUT, GPIOPinMode.INPUT_PULLUP, GPIOPinMode.OUTPUT}
DIGITAL_WRITE_MODES = {GPIOPinMode.OUTPUT}
ANALOG_READ_MODES = {GPIOPinMode.INPUT}


class Arduino(Board):
"""
The Arduino board interface.
Expand Down Expand Up @@ -319,8 +314,6 @@ def digital_value(self) -> bool:
:return: The digital value of the pin.
"""
self._check_if_disabled()
if self.mode not in DIGITAL_READ_MODES:
raise IOError(f'Digital read is not supported in {self.mode}')
response = self._serial.query(f'PIN:{self._index}:DIGITAL:GET?')
return (response == '1')

Expand All @@ -335,12 +328,14 @@ def digital_value(self, value: bool) -> None:
:raises IOError: If this pin cannot be controlled.
"""
self._check_if_disabled()
if self.mode not in DIGITAL_WRITE_MODES:
raise IOError(f'Digital write is not supported in {self.mode}')
if value:
self._serial.write(f'PIN:{self._index}:DIGITAL:SET:1')
else:
self._serial.write(f'PIN:{self._index}:DIGITAL:SET:0')
try:
if value:
self._serial.write(f'PIN:{self._index}:DIGITAL:SET:1')
else:
self._serial.write(f'PIN:{self._index}:DIGITAL:SET:0')
except RuntimeError as e:
if 'is not supported in' in str(e):
raise IOError(str(e))

@property
@log_to_debug
Expand All @@ -358,11 +353,14 @@ def analog_value(self) -> float:
ADC_MIN = 0

self._check_if_disabled()
if self.mode not in ANALOG_READ_MODES:
raise IOError(f'Analog read is not supported in {self.mode}')
if not self._supports_analog:
raise IOError('Pin does not support analog read')
response = self._serial.query(f'PIN:{self._index}:ANALOG:GET?')
try:
response = self._serial.query(f'PIN:{self._index}:ANALOG:GET?')
except RuntimeError as e:
# The firmware returns a NACK if the pin is not in INPUT mode
if 'is not supported in' in str(e):
raise IOError(str(e))
# map the response from the ADC range to the voltage range
return map_to_float(int(response), ADC_MIN, ADC_MAX, 0.0, 5.0)

Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def query(self, request: str) -> str:
"""
# Assert that we have not run out of responses
# and that the request is the next one we expect
assert self.request_index < len(self.responses)
assert self.request_index < len(self.responses), f"Unexpected request: {request}"
assert request == self.responses[self.request_index][0]

# Fetch the response and increment the request index
Expand Down
19 changes: 0 additions & 19 deletions tests/test_arduino.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,8 @@ def test_arduino_pins(arduino_serial: MockArduino) -> None:

# Test that we can get the digital value of a pin
arduino_serial.serial_wrapper._add_responses([
("PIN:2:MODE:GET?", "OUTPUT"), # mode is read before digital value
("PIN:2:DIGITAL:GET?", "1"),
("PIN:10:MODE:GET?", "INPUT_PULLUP"),
("PIN:10:DIGITAL:GET?", "0"),
("PIN:14:MODE:GET?", "INPUT"),
("PIN:14:DIGITAL:GET?", "1"),
])
assert arduino.pins[2].digital_value is True
Expand All @@ -129,32 +126,16 @@ def test_arduino_pins(arduino_serial: MockArduino) -> None:

# Test that we can set the digital value of a pin
arduino_serial.serial_wrapper._add_responses([
("PIN:2:MODE:GET?", "OUTPUT"), # mode is read before digital value
("PIN:2:DIGITAL:SET:1", "ACK"),
("PIN:2:MODE:GET?", "OUTPUT"),
("PIN:2:DIGITAL:SET:0", "ACK"),
("PIN:10:MODE:GET?", "INPUT_PULLUP"),
("PIN:10:MODE:GET?", "INPUT_PULLUP"),
("PIN:14:MODE:GET?", "INPUT"),
("PIN:14:MODE:GET?", "INPUT"),
])
arduino.pins[2].digital_value = True
arduino.pins[2].digital_value = False
with pytest.raises(IOError, match=r"Digital write is not supported.*"):
arduino.pins[10].digital_value = False
with pytest.raises(IOError, match=r"Digital write is not supported.*"):
arduino.pins[AnalogPins.A0].digital_value = True

# Test that we can get the analog value of a pin
arduino_serial.serial_wrapper._add_responses([
("PIN:2:MODE:GET?", "OUTPUT"), # mode is read before analog value
("PIN:2:MODE:GET?", "OUTPUT"),
("PIN:10:MODE:GET?", "INPUT"),
("PIN:14:MODE:GET?", "INPUT"),
("PIN:14:ANALOG:GET?", "1000"),
])
with pytest.raises(IOError, match=r"Analog read is not supported.*"):
arduino.pins[2].analog_value
with pytest.raises(IOError, match=r"Pin does not support analog read"):
arduino.pins[10].analog_value
# 4.888 = round((5 / 1023) * 1000, 3)
Expand Down

0 comments on commit 2c4836a

Please sign in to comment.