diff --git a/docs/img/T4.1-mux.jpg b/docs/img/T4.1-mux.jpg new file mode 100644 index 0000000..534aae6 Binary files /dev/null and b/docs/img/T4.1-mux.jpg differ diff --git a/docs/img/card11a_rev4_web.pdf b/docs/img/card11a_rev4_web.pdf new file mode 100644 index 0000000..079e507 Binary files /dev/null and b/docs/img/card11a_rev4_web.pdf differ diff --git a/docs/img/card11b_rev4_web.pdf b/docs/img/card11b_rev4_web.pdf new file mode 100644 index 0000000..6e2ccef Binary files /dev/null and b/docs/img/card11b_rev4_web.pdf differ diff --git a/firmware/upy_clank/ble.py b/firmware/upy_clank/ble.py new file mode 100644 index 0000000..ee4b92a --- /dev/null +++ b/firmware/upy_clank/ble.py @@ -0,0 +1,67 @@ +""" +This modul implements a simple serial connection to the ZS-040 and will echo out to the console +any messages it receives. This board is a Bluetooth SPP (Serial Port Protocol) module. + +When powered on the device will broadcast as BT-05 by default. Default passwords are usually 1234 or 0000. +""" +from select import select +from machine import Pin, UART + + +class ZS040: + def __init__( + self, + uart_id, + tx_pin, + rx_pin, + state_pin, + baudrate=38400, + bits=8, + stop=1, + parity=None, + ): + self.uart = UART( + uart_id, + baudrate=baudrate, + bits=bits, + stop=stop, + parity=parity, + ) + self.state_pin = Pin(state_pin, Pin.IN) + + def read(self, nbytes=None): + return self.uart.read(nbytes) + + def readline(self): + return self.uart.readline() + + def write(self, buf): + self.uart.write(buf) + + def any(self): + return self.uart.any() + + @property + def state(self): + return self.state_pin.value() + + @classmethod + def from_config(cls, pin_config): + return cls( + uart_id=pin_config["bluetooth"]["uart_id"], + tx_pin=pin_config["bluetooth"]["tx_pin"], + rx_pin=pin_config["bluetooth"]["rx_pin"], + state_pin=pin_config["bluetooth"]["state_pin"], + ) + + +# while True: +# if BT_STATE_PIN.value(): +# if uart.any(): +# data = uart.read(1) +# print(data.decode("utf8")) +# else: +# print("No data. Sleeping") +# else: +# print("No Bluetooth device paired.") +# sleep_ms(500) diff --git a/firmware/upy_clank/boot.py b/firmware/upy_clank/boot.py index e69de29..46cb794 100644 --- a/firmware/upy_clank/boot.py +++ b/firmware/upy_clank/boot.py @@ -0,0 +1 @@ +__secret__ = "dirp" diff --git a/firmware/upy_clank/config.py b/firmware/upy_clank/config.py index 63e5004..e718866 100644 --- a/firmware/upy_clank/config.py +++ b/firmware/upy_clank/config.py @@ -7,6 +7,7 @@ PIN_CONFIG = { "encoder": {"cpr": 1320, "pin_a": 2, "pin_b": 3}, "motor": {"pwm": 19, "in1": 18, "in2": 17}, }, + "bluetooth": {"uart_id": 8, "tx_pin": 35, "rx_pin": 34, "state_pin": 36}, } DUTY_MAX = 65535 diff --git a/firmware/upy_clank/motor.py b/firmware/upy_clank/motor.py index 5534ae1..26f14a9 100644 --- a/firmware/upy_clank/motor.py +++ b/firmware/upy_clank/motor.py @@ -12,27 +12,85 @@ class MotorController: def __init__(self, left_motor, right_motor) -> None: self.left = left_motor self.right = right_motor + self.speed = 65535 // 2 def forward(self): + """Forward move""" self.left.in1.value(1) self.left.in2.value(0) self.right.in2.value(1) self.right.in1.value(0) - self.left.pwm.duty_u16(65535 // 2) - self.right.pwm.duty_u16(65535 // 2) + self.left.pwm.duty_u16(self.speed) + self.right.pwm.duty_u16(self.speed) def reverse(self): + """Reverse move""" self.left.in1.value(0) self.left.in2.value(1) self.right.in2.value(0) self.right.in1.value(1) - self.left.pwm.duty_u16(65535 // 2) - self.right.pwm.duty_u16(65535 // 2) + self.left.pwm.duty_u16(self.speed) + self.right.pwm.duty_u16(self.speed) def stop(self): + """All stop""" self.left.pwm.duty_u16(0) self.right.pwm.duty_u16(0) + def right_forward(self): + """Right turn while moving forward""" + self.left.in1.value(1) + self.left.in2.value(0) + self.right.in2.value(1) + self.right.in1.value(0) + self.left.pwm.duty_u16(self.speed) + self.right.pwm.duty_u16(self.speed // 2) + + def right_spin(self): + """Spins clockwise in place""" + self.left.in1.value(1) + self.left.in2.value(0) + self.right.in2.value(0) + self.right.in1.value(1) + self.left.pwm.duty_u16(self.speed) + self.right.pwm.duty_u16(self.speed // 2) + + def right_reverse(self): + """Right turn while moving in reverse""" + self.left.in1.value(0) + self.left.in2.value(1) + self.right.in2.value(0) + self.right.in1.value(1) + self.left.pwm.duty_u16(self.speed) + self.right.pwm.duty_u16(self.speed // 2) + + def left_forward(self): + """Right turn while moving forward""" + self.left.in1.value(1) + self.left.in2.value(0) + self.right.in2.value(1) + self.right.in1.value(0) + self.left.pwm.duty_u16(self.speed // 2) + self.right.pwm.duty_u16(self.speed) + + def left_spin(self): + """Spins counter-clockwise in place""" + self.left.in1.value(0) + self.left.in2.value(1) + self.right.in2.value(1) + self.right.in1.value(0) + self.left.pwm.duty_u16(self.speed) + self.right.pwm.duty_u16(self.speed) + + def left_reverse(self): + """Left turn while moving in reverse""" + self.left.in1.value(0) + self.left.in2.value(1) + self.right.in2.value(0) + self.right.in1.value(1) + self.left.pwm.duty_u16(self.speed // 2) + self.right.pwm.duty_u16(self.speed) + @classmethod def from_config(cls, pin_config): return cls(