top of page

Forum Posts

Berndt Hamboeck
May 26, 2021
In Software
I connected a ESP32Cam module to the serial port of my Bittle. First I flashed a BIOS, which includes Micropython and the CAM drive on the ESP32 cam module. The ESP32Cam module is connected to my PC using a FTDI module to send the commands through VSCode to my Bittle through the ESP32Cam module (this connection is required for flashing the BIOS anyway). ESP32Cam FTDI U0TXD RX U0RXD TX GND GND 5V 5V Finally, I connected the Bittle with the ESP32Cam module: Bittle ESP32Cam GND GND RX GPIO14 TX GPIO12 I powered the Bittle through another cable, which delivers the 5V for the board. Now, it's time to send commands to the Bittle: from machine import UART uart = UART(1, baudrate=115200, bits=8, parity=None, stop=1, tx=12, rx=14, rts=-1, cts=-1, txbuf=256, rxbuf=256, timeout=5, timeout_char=2) uart.init() # uart.write("krest".encode()) uart.write("ksit".encode()) # uart.write("kbalance".encode()) The next step is to deploy a simple web server, power the ESP32CAM module from the nyboard and position the camera to get usable images.........
Bittle, Micropython + ESP32Cam module content media
2
0
209
Berndt Hamboeck
May 23, 2021
In Software
I extended the code available and described here to also be able to use the Bittle connected to the serial port (as in my bittle box was no bluetooth/wifi adapter). I added some messages on the screen, I thought this might come in handy... You need to: pip install pyBittle pygame bittle_xbox_controller.py: """This program allow to control Bittle using Xbox controller. """ import math import pyBittle import pygame import sys import time __initialauthor__ = "EnriqueMoran" # Define some colors. BLACK = pygame.Color('black') WHITE = pygame.Color('white') BUTTONS_MAP = { 0: pyBittle.Command.BALANCE, # A 1: pyBittle.Command.REST, # B 2: pyBittle.Command.GREETING, # X 3: pyBittle.Command.SIT, # Y 4: pyBittle.Command.STEP, # LB 5: pyBittle.Command.GYRO # RB } class TextPrint(object): def __init__(self): self.reset() self.font = pygame.font.Font(None, 20) def tprint(self, window, textString): textBitmap = self.font.render(textString, True, BLACK) window.blit(textBitmap, (self.x, self.y)) self.y += self.line_height def reset(self): self.x = 10 self.y = 10 self.line_height = 15 def indent(self): self.x += 10 def unindent(self): self.x -= 10 class Controller(): def __init__(self, window_size=(1, 1), connect_wifi=False, connect_bluetooth=False, connect_com=False, ip_addr=None, device_name=None, bt_port=None): self.window_size = window_size self.window = None self.joystick = None self.n_axes = 0 self.n_buttons = 0 self.n_hats = 0 self.bittle = None self.connect_wifi = connect_wifi self.connect_bluetooth = connect_bluetooth self.connect_com = connect_com self.ip_addr = ip_addr self.device_name = device_name self.bt_port = bt_port self.direction = pyBittle.Command.BALANCE def initialize(self): # os.environ["DISPLAY"] = ":0" # os.environ["SDL_VIDEODRIVER"] = "dummy" # Hide window pygame.init() controller_found = False self.window = pygame.display.set_mode(self.window_size) pygame.display.set_caption("Bittle controller") self.clock = pygame.time.Clock() pygame.joystick.init() self.textPrint = TextPrint() self.bittle = pyBittle.Bittle() if self.connect_wifi: self.bittle.wifiManager.ip = self.ip_addr elif self.connect_bluetooth: self.isconnected = self.bittle.connect_bluetooth() elif self.connect_com: self.isconnected = self.bittle.connect_serial(True) try: self.joystick = pygame.joystick.Joystick(0) self.joystick.init() self.n_axes = self.joystick.get_numaxes() self.n_buttons = self.joystick.get_numbuttons() self.n_hats = self.joystick.get_numhats() print(f"Joystick found: {self.joystick.get_name()}") controller_found = True except: print("No controller found!") return controller_found def read_inputs(self): new_direction = self.direction x_axis_value = 0 y_axis_value = 0 for i in range(self.n_axes): axis_value = self.joystick.get_axis(i) if i == 0: # Horizontal x_axis_value = axis_value elif i == 1: # Vertical y_axis_value = -axis_value # Set FORWARD as positive value if abs(x_axis_value) > 0.8 or abs(y_axis_value) > 0.8: angle = self.get_angle(x_axis_value, y_axis_value) if angle >= 337.5 or angle < 22.5: new_direction = pyBittle.Direction.FORWARD elif angle >= 22.5 and angle < 67.5: new_direction = pyBittle.Direction.FORWARDRIGHT elif angle >= 67.5 and angle < 112.5: new_direction = pyBittle.Direction.FORWARDRIGHT elif angle >= 112.5 and angle < 157.5: new_direction = pyBittle.Direction.BACKWARDRIGHT elif angle >= 157.5 and angle < 202.5: new_direction = pyBittle.Direction.BACKWARD elif angle >= 202.5 and angle < 247.5: new_direction = pyBittle.Direction.BACKWARDLEFT elif angle >= 247.5 and angle < 292.5: new_direction = pyBittle.Direction.FORWARDLEFT elif angle >= 292.5 and angle < 337.5: new_direction = pyBittle.Direction.FORWARDLEFT elif abs(x_axis_value) < 0.2 or abs(y_axis_value) < 0.2: new_direction = pyBittle.Command.BALANCE # Stop if self.direction != new_direction: self.direction = new_direction self.send_direction(self.direction) self.textPrint.tprint(self.window, "Direction: {}".format(self.direction)) for i in range(self.n_buttons): button = self.joystick.get_button(i) if button == 1: try: command = BUTTONS_MAP[i] self.send_command(command) self.textPrint.tprint(self.window, "Command: {}".format(command)) except Exception as e: print(e) for i in range(self.n_hats): gait = None hat = self.joystick.get_hat(i) if hat == (-1, 0): # Left pad gait = pyBittle.Gait.CRAWL elif hat == (1, 0): # Right pad gait = pyBittle.Gait.TROT elif hat == (0, -1): # Down pad gait = pyBittle.Gait.WALK elif hat == (0, 1): # Up pad gait = pyBittle.Gait.RUN if gait: self.bittle.gait = gait print(f"New gait selected: {gait}") time.sleep(0.2) self.textPrint.tprint(self.window, "Gait: {}".format(self.bittle.gait)) def run(self): initialized = self.initialize() if initialized: running = True clock = pygame.time.Clock() while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.JOYBUTTONDOWN: print("Joystick button pressed.") elif event.type == pygame.JOYBUTTONUP: print("Joystick button released.") self.window.fill(WHITE) self.textPrint.reset() if self.connect_wifi: self.textPrint.tprint(self.window, "WIFI Connnection") elif self.connect_bluetooth: self.textPrint.tprint(self.window, "Bluetooth Connnection") else: self.textPrint.tprint(self.window, "COM Connnection") if not self.connect_wifi: self.textPrint.tprint(self.window, "Connnected: {}".format(self.isconnected)) # Get count of joysticks. joystick_count = pygame.joystick.get_count() self.textPrint.tprint(self.window, "Number of joysticks: {}".format(joystick_count)) self.textPrint.indent() # For each joystick: for i in range(joystick_count): joystick = pygame.joystick.Joystick(i) joystick.init() try: jid = joystick.get_instance_id() except AttributeError: # get_instance_id() is an SDL2 method jid = joystick.get_id() self.textPrint.tprint(self.window, "Joystick {}".format(jid)) self.textPrint.indent() # Get the name from the OS for the controller/joystick. name = joystick.get_name() self.textPrint.tprint(self.window, "Joystick name: {}".format(name)) try: guid = joystick.get_guid() except AttributeError: # get_guid() is an SDL2 method pass else: self.textPrint.tprint(self.window, "GUID: {}".format(guid)) # Usually axis run in pairs, up/down for one, and left/right for # the other. axes = joystick.get_numaxes() self.textPrint.tprint(self.window, "Number of axes: {}".format(axes)) self.textPrint.indent() for i in range(axes): axis = joystick.get_axis(i) self.textPrint.tprint(self.window, "Axis {} value: {:>6.3f}".format(i, axis)) self.textPrint.unindent() buttons = joystick.get_numbuttons() self.textPrint.tprint(self.window, "Number of buttons: {}".format(buttons)) self.textPrint.indent() for i in range(buttons): button = joystick.get_button(i) if(button == 1): self.textPrint.tprint(self.window, "Button {:>2} value: {}".format(i, button)) self.textPrint.unindent() hats = joystick.get_numhats() self.textPrint.tprint(self.window, "Number of hats: {}".format(hats)) self.textPrint.indent() # Hat position. All or nothing for direction, not a float like # get_axis(). Position is a tuple of int values (x, y). for i in range(hats): hat = joystick.get_hat(i) self.textPrint.tprint(self.window, "Hat {} value: {}".format(i, str(hat))) self.textPrint.unindent() self.textPrint.unindent() self.read_inputs() pygame.display.flip() self.clock.tick(20) pygame.quit() def send_command(self, command): if self.connect_wifi: if self.bittle.has_wifi_connection(): self.bittle.send_command_wifi(command) elif self.connect_bluetooth: self.bittle.send_command_bluetooth(command) elif self.connect_com: self.bittle.send_command_serial(command) print(f"Action: {command} sent") time.sleep(0.5) # Let Bittle rest to prevent damage return True def send_direction(self, direction): if self.connect_wifi: if self.bittle.has_wifi_connection(): if direction == pyBittle.Command.BALANCE: self.bittle.send_command_wifi(direction) else: self.bittle.send_movement_wifi(direction) elif self.connect_bluetooth: if direction == pyBittle.Command.BALANCE: self.bittle.send_command_bluetooth(direction) else: self.bittle.send_movement_bluetooth(direction) elif self.connect_com: if direction == pyBittle.Command.BALANCE: self.bittle.send_command_serial(direction) else: self.bittle.send_movement_serial(direction) print(f"Direction: {direction} sent") # Let Bittle rest to prevent damage, modify this under your own risk time.sleep(0.5) return True def get_angle(self, xPercent, yPercent): """Returns joystick angle. """ angle_deg = 0 if xPercent > 0.9 and yPercent == 0: angle_deg = 90 elif xPercent < -0.9 and yPercent == 0: angle_deg = 270 elif xPercent == 0 and yPercent > 0.9: angle_deg = 1 elif xPercent == 0 and yPercent < -0.9: angle_deg = 180 elif (xPercent > 0 and yPercent > 0 and (xPercent > 0.2 or yPercent > 0.2)): angle_rad = math.atan2(xPercent, yPercent) angle_deg = angle_rad * 180 / math.pi elif (xPercent > 0 and yPercent < 0 and (xPercent > 0.2 or yPercent < -0.2)): angle_rad = math.atan2(xPercent, yPercent) angle_deg = angle_rad * 180 / math.pi elif (xPercent < 0 and yPercent < 0 and (xPercent < -0.2 or yPercent < -0.2)): angle_rad = math.atan2(xPercent, yPercent) angle_deg = angle_rad * 180 / math.pi angle_deg += 360 elif (xPercent < 0 and yPercent > 0 and (xPercent < -0.2 or yPercent > 0.2)): angle_rad = math.atan2(xPercent, yPercent) angle_deg = angle_rad * 180 / math.pi angle_deg += 360 return angle_deg if __name__ == '__main__': connect_wifi = False # Set to True to connect through WiFi connect_bluetooth = False # Set to True to connect through Bluetooth connect_com = True # Set to True to connect through COM port ip_addr = '192.168.1.138' # Here goes your Bittle's IP address controller = Controller(connect_wifi=connect_wifi, connect_bluetooth=connect_bluetooth, connect_com=connect_com, window_size=(500, 400), ip_addr=ip_addr) if not connect_wifi and not connect_bluetooth and not connect_com: print("No connection method selected.") input("Press any key to exit.") sys.exit() try: controller.run() except KeyboardInterrupt: if controller.connect_bluetooth: print("Closing Bluetooth connection with Bittle") try: controller.bittle.send_command_bluetooth(pyBittle.Command.REST) controller.bittle.disconnect_bluetooth() print("Connection Closed") except: pass input("Press any key to exit.") sys.exit()
Bittle + XBOX Controller + Serial Port content media
2
1
280

Berndt Hamboeck

More actions
bottom of page