diff --git a/sbot/arduino.py b/sbot/arduino.py index faac772..d106940 100644 --- a/sbot/arduino.py +++ b/sbot/arduino.py @@ -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. @@ -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') @@ -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 @@ -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) diff --git a/tests/conftest.py b/tests/conftest.py index fe0aa43..d6850a2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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 diff --git a/tests/test_arduino.py b/tests/test_arduino.py index b348c18..e765958 100644 --- a/tests/test_arduino.py +++ b/tests/test_arduino.py @@ -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 @@ -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)