Servo control via radio + Raw REPL
Using Raw REPL it is possible to to talk with your microbit over a serial interface, this demo uses that feature to control a servo motor from a PC with two microbits communicating over radio.
The GUI is built from python 3 on a Windows PC but will work on a Mac also. The GUI code looks fairly daunting but can be split into widget creation, serial interface control, initializing and exiting Raw REPL and the method that transmits the micro python code to the microbit. At the moment there is very little in the way of error trapping but it works well enough to show the example.
The method that sends the micropython code is "write_py_code" and takes any valid microbit instruction as a string, the demo controls a servo but can be modified to communicate and control many other devices.
The transmitter needs no programming the GUI takes care of it, the receiver has a 10 line program for basic control of the servo.
RECEIVER
from microbit import * import radio radio.on() pin16.set_analog_period(20) while True: incoming=radio.receive() # 26 to 128 if incoming != None: value=int(incoming) pin16.write_analog(value) incoming=None
GUI
from tkinter import * from tkinter import ttk from threading import * import threading import serial.tools.list_ports import time from tkinter import messagebox root=Tk() var1=StringVar() count = 0 event = threading.Event() root.title("Servo Control") screen_width= root.winfo_screenwidth() screen_height= root.winfo_screenheight() root_width=500 root_height=485 root.resizable(False,False) x_location=(screen_width/2) - (root_width/2) y_location=(screen_height/2) - (root_height/2) root.geometry(f"{root_width}x{root_height}+{int(x_location)}+{int(y_location)}") root.configure(bg="light blue") port_list=[] ports = list(serial.tools.list_ports.comports()) baud_list=[9600,19200,38400,57600,115200,] for p in ports: port_list.append(p.name) ser = serial.Serial() def port_open(my_port): my_port=my_port if not ser.isOpen(): ser.port=my_port ser.baudrate=combobox2.get() ser.open() time.sleep(2) raw_repl() def port_close(): if ser.isOpen(): ser.close() def thread_start(): t1=Thread(target=write_slider,daemon=True) t1.start() def thread_break(): event.set() exit_raw_repl() port_close() def raw_repl(): ser.timeout=0.5 for i in range(3): ser.write(b"\r\x03") time.sleep(0.01) ser.write(b"\r\x01") input_string=ser.read(400) txt.insert(END,input_string) initialize_uBit() def exit_raw_repl(): ser.timeout=2 ser.write(b"\r\x02") input_string=ser.read(400) txt.insert(END,input_string) def initialize_uBit(): write_py_code("from microbit import *") write_py_code("import radio") write_py_code("radio.on()") thread_start() def write_py_code(py_code): ser.write(py_code.encode("utf-8")) ser.write(b"\x04") response=ser.read_until(b"\x04>") def write_slider(): new_val=0 slide_1.set(77) while True: if event.is_set(): break time.sleep(0.005) s1=slide_1.get() old_val=s1 if old_val != new_val: write_py_code(f"radio.send(str({s1}))") new_val=old_val def clear(): txt.delete("1.0",END) def close_app(): root.destroy() def on_closing(): if messagebox.askokcancel("Quit", "Are you sure you want to exit?"): close_app() root.protocol("WM_DELETE_WINDOW", on_closing) comms_frame=LabelFrame(root,text="Comms") comms_frame.grid(row=0,column=0,padx=10,pady=5,sticky="w") command_frame=LabelFrame(root,text="Commands") command_frame.grid(row=0,column=1,sticky="nw",pady=5) btn1 = Button(comms_frame, text='OpenPort',bg="light gray",command=lambda:port_open(ports_cmb.get()),width=15) btn1.grid(row=0,column=0,pady=5,padx=5) btn2 = Button(comms_frame, text='ClosePort',bg="light gray",command=lambda:thread_break(),width=15) btn2.grid(row=1,column=0,pady=5,padx=5) btn3 = Button(comms_frame, text='Clear',bg="light gray",command=lambda:clear(),width=15) btn3.grid(row=0,column=2,pady=5,padx=5) slide_1 = Scale(root, from_= 28, to= 128,orient=HORIZONTAL,length=350) slide_1.grid(row=3,column=0,columnspan=2) txt=Text(root,width=60,height=15,relief="sunken",borderwidth=5) txt.grid(row=2,column=0,columnspan=2,padx=5,pady=5) ports_cmb = ttk.Combobox(comms_frame,values=port_list,width=6) ports_cmb.grid(row=0,column=1,pady=5,padx=10) ports_cmb.current(0) combobox2 = ttk.Combobox(comms_frame,values=baud_list,width=6) combobox2.grid(row=1,column=1,pady=5,padx=10) combobox2.current(4) root.mainloop()