""" MicroPython for AlphaBot2-Ar from Waveshare. https://github.com/vittascience/stm32-libraries https://www.waveshare.com/wiki/AlphaBot2-Ar MIT License Copyright (c) 2021 leomlr (Léo Meillier) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ __version__ = "0.0.0-auto.0" __repo__ = "show" from stm32_TRsensors import TRSensors from stm32_pcf8574 import PCF8574 import machine import pyb import utime ALPHABOT_V2_PIN_AIN2 = 'A0' ALPHABOT_V2_PIN_AIN1 = 'A1' ALPHABOT_V2_PIN_BIN1 = 'A2' ALPHABOT_V2_PIN_BIN2 = 'A3' ALPHABOT_V2_PIN_ECHO = 'D2' ALPHABOT_V2_PIN_TRIG = 'D3' ALPHABOT_V2_PIN_IR = 'D4' ALPHABOT_V2_PIN_PWMB = 'D5' ALPHABOT_V2_PIN_PWMA = 'D6' ALPHABOT_V2_PIN_RGB = 'D7' ALPHABOT_V2_PIN_OLED_D_C = 'D8' ALPHABOT_V2_PIN_OLED_RESET = 'D9' ALPHABOT_V2_PIN_TRS_CS = 'D10' ALPHABOT_V2_PIN_TRS_DOUT = 'D11' ALPHABOT_V2_PIN_TRS_ADDR = 'D12' ALPHABOT_V2_PIN_TRS_CLK = 'D13' ALPHABOT_V2_PCF8574_I2C_ADDR = 0x20 ALPHABOT_V2_OLED_I2C_ADDR_DC_OFF = 0x3c ALPHABOT_V2_OLED_I2C_ADDR_DC_ON = 0x3d class AlphaBot_v2(object): def __init__(self): self.ain1 = pyb.Pin(ALPHABOT_V2_PIN_AIN1, pyb.Pin.OUT) self.ain2 = pyb.Pin(ALPHABOT_V2_PIN_AIN2, pyb.Pin.OUT) self.bin1 = pyb.Pin(ALPHABOT_V2_PIN_BIN1, pyb.Pin.OUT) self.bin2 = pyb.Pin(ALPHABOT_V2_PIN_BIN2, pyb.Pin.OUT) self.pin_PWMA = pyb.Pin(ALPHABOT_V2_PIN_PWMA, pyb.Pin.OUT_PP) tim_A = pyb.Timer(1, freq=500) self.PWMA = tim_A.channel(1, pyb.Timer.PWM, pin=self.pin_PWMA) self.pin_PWMB = pyb.Pin(ALPHABOT_V2_PIN_PWMB, pyb.Pin.OUT_PP) tim_B = pyb.Timer(2, freq=500) self.PWMB = tim_B.channel(1, pyb.Timer.PWM, pin=self.pin_PWMB) self.stop() print('[Alpha_INFO]: Motors initialised') self.trig = pyb.Pin(ALPHABOT_V2_PIN_TRIG, pyb.Pin.OUT) self.echo = pyb.Pin(ALPHABOT_V2_PIN_ECHO, pyb.Pin.IN) self.pin_RGB = pyb.Pin(ALPHABOT_V2_PIN_RGB, pyb.Pin.OUT) self.tr_sensors = TRSensors( cs = ALPHABOT_V2_PIN_TRS_CS, dout = ALPHABOT_V2_PIN_TRS_DOUT, addr = ALPHABOT_V2_PIN_TRS_ADDR, clk = ALPHABOT_V2_PIN_TRS_CLK ) print('[Alpha_INFO]: TR sensors initialised') self.i2c = machine.I2C(1) self.LEFT_OBSTACLE = 'L' self.RIGHT_OBSTACLE = 'R' self.BOTH_OBSTACLE = 'B' self.NO_OBSTACLE = 'N' self.JOYSTICK_UP = 'up' self.JOYSTICK_RIGHT = 'right' self.JOYSTICK_LEFT = 'left' self.JOYSTICK_DOWN = 'down' self.JOYSTICK_CENTER = 'center' print('[Alpha_INFO]: IR detectors initialised (for obstacles)') self.pin_IR = pyb.Pin(ALPHABOT_V2_PIN_IR, pyb.Pin.IN) print('[Alpha_INFO]: IR receiver initialised (for remotes)') self.pin_oled_reset = pyb.Pin(ALPHABOT_V2_PIN_OLED_RESET, pyb.Pin.OUT) self.pin_oled_reset.off() utime.sleep_ms(10) self.pin_oled_reset.on() self.pin_DC = pyb.Pin(ALPHABOT_V2_PIN_OLED_D_C, pyb.Pin.OUT) print('[Alpha_INFO]: OLED screen initialised') self._pcf8574 = PCF8574(self.i2c, addr=ALPHABOT_V2_PCF8574_I2C_ADDR) def setPWMA(self, value): self.PWMA.pulse_width_percent(value) def setPWMB(self, value): self.PWMB.pulse_width_percent(value) def setMotors(self, left=None, right=None): if left is not None: if left >= 0 and left <= 100: self.ain1.off() self.ain2.on() self.setPWMA(left) elif left >= -100 and left < 0: self.ain1.on() self.ain2.off() self.setPWMA(-left) if right is not None: if right >= 0 and right <= 100: self.bin1.off() self.bin2.on() self.setPWMB(right) elif right >= -100 and right < 0: self.bin1.on() self.bin2.off() self.setPWMB(-right) def stop(self): self.setMotors(left=0, right=0) def moveForward(self, speed, duration_ms=0): self.setMotors(left=speed, right=speed) if duration_ms: utime.sleep_ms(duration_ms) self.stop() def moveBackward(self, speed, duration_ms=0): self.setMotors(left=-speed, right=-speed) if duration_ms: utime.sleep_ms(duration_ms) self.stop() def turnLeft(self, speed, duration_ms=0): if speed < 20: self.setMotors(left=speed, right=50-speed) else: self.setMotors(left=30-speed, right=speed) if duration_ms: utime.sleep_ms(duration_ms) self.stop() def turnRight(self, speed, duration_ms=0): if speed < 20: self.setMotors(left=50-speed, right=speed) else: self.setMotors(left=speed, right=30-speed) if duration_ms: utime.sleep_ms(duration_ms) self.stop() def calibrateLineFinder(self): print("[Alpha_INFO]: TR sensors calibration ...\\n") for i in range(0, 100): if i<25 or i>= 75: self.turnRight(15) else: self.turnLeft(15) self.TRSensors_calibrate() self.stop() print("Calibration done.\\n") print(str(self.tr_sensors.calibratedMin) + '\\n') print(str(self.tr_sensors.calibratedMax) + '\\n') utime.sleep_ms(500) def TRSensors_calibrate(self): self.tr_sensors.calibrate() def TRSensors_read(self, sensor = 0): return self.tr_sensors.analogRead() def TRSensors_readLine(self, sensor = 0): position, sensor_values = self.tr_sensors.readLine() if sensor is 0: return sensor_values else: return sensor_values[sensor-1] def TRSensors_position_readLine(self, sensor = 0): return self.tr_sensors.readLine() def readUltrasonicDistance(self, length=15, timeout_us = 30000): measurements = 0 for i in range(length): self.trig.off() utime.sleep_us(2) self.trig.on() utime.sleep_us(10) self.trig.off() self.echo.value() measurements += machine.time_pulse_us(self.echo, 1, timeout_us)/1e6 # t_echo in seconds duration = measurements/length return 343 * duration/2 * 100 def getOLEDaddr(self): if self.pin_DC.value(): return ALPHABOT_V2_OLED_I2C_ADDR_DC_ON else: return ALPHABOT_V2_OLED_I2C_ADDR_DC_OFF # Drivers for PCF8574T def controlBuzzer(self, state): self._pcf8574.pin(5, state) def getJoystickValue(self): i = 0 for i in range(5): if not self._pcf8574.pin(i): break elif i == 4: i = None if i == 0: return self.JOYSTICK_UP elif i == 1: return self.JOYSTICK_RIGHT elif i == 2: return self.JOYSTICK_LEFT elif i == 3: return self.JOYSTICK_DOWN elif i == 4: return self.JOYSTICK_CENTER else: return None def readInfrared(self): left = not self._pcf8574.pin(7) right = not self._pcf8574.pin(6) if left and not right: return self.LEFT_OBSTACLE elif not left and right: return self.RIGHT_OBSTACLE elif left and right: return self.BOTH_OBSTACLE else: return self.NO_OBSTACLE