Skip to content

Commit 8c2f827

Browse files
committed
initial@
0 parents  commit 8c2f827

File tree

108 files changed

+3321
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+3321
-0
lines changed
+278
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
---
2+
title: "Microbit Python Program with pySerial and GUIZero"
3+
layout: text-width-sidebar
4+
5+
# Meta description for google and sharing
6+
meta-description: "Using GUIZero & pySerial to send commands to the microbit."
7+
8+
#############
9+
## Options ##
10+
#############
11+
12+
share: true
13+
author: jez
14+
15+
#################################
16+
## Component Template Specific ##
17+
#################################
18+
19+
video:
20+
teaser: microbit_blink_led_example
21+
22+
video:
23+
- teaser: true
24+
25+
# About Box is on the left of the program page
26+
about: "Using GUIZero---a learner-friendly tkinter wrapper---to create a serial connection to the microbit in Python with pySerial."
27+
28+
# Category of howto: I2C, other, visual basic, component examples, python, data logging
29+
cats: python
30+
31+
# Name of Component for index page
32+
simple-description: pySerial Microbit GUI
33+
34+
date: 2016-12-23T10:20:00Z
35+
---
36+
37+
![GUI Zero example](images/GUIZero-pySerial-microbit-how-to-connect-app.png){:.ui .image .small .floated .right}
38+
39+
It is possible to send commands to the microbit over a serial connection from your computer. The `REPL` function in the mu editor is simply a serial connection. For example, `display.show(Image.HAPPY)` causes a face to show on the microbit's display.
40+
41+
There's [more about the USB serial connection on our website](http://localhost:4000/howto/microbit-serial-connection-over-usb).
42+
43+
To send Python commands, the microbit must be running a micropython `.hex` file (eg, created in mu).
44+
45+
In this example, a Python GUI program sends commands to the microbit flashed in mu with a blank script.
46+
47+
### About the Program
48+
49+
This program uses two Python modules: pySerial and GUIZero.
50+
51+
* pySerial handles the serial communication. It scans for the microbit and creates a serial connection.
52+
53+
* GUIZero is for drawing the GUI. It is a learner-friendly wrapper for TKInter.
54+
55+
#### pySerial
56+
57+
Handles the serial connection to the microbit.
58+
59+
##### `find_microbit_comport()`
60+
61+
```
62+
def find_microbit_comport():
63+
ports = list(list_ports.comports())
64+
for p in ports:
65+
if (p.pid == 516) and (p.vid == 3368):
66+
return str(p.device)
67+
```
68+
69+
This function returns a string of the microbit's COM port. On Windows this might be `COM3`, on Linux `/dev/ttyS2`.
70+
71+
The `product ID` & `vendor ID` of each attached device is evaluated. If it is the same as the ones on a microbit (`516` & `3368`) then return the device name (eg COM4).
72+
73+
`serial.tools.list_ports` must be imported.
74+
75+
##### Initialise
76+
77+
Create a new instance of the Serial class as `ser`:
78+
79+
```
80+
ser = serial.Serial()
81+
```
82+
83+
Set `ser` baud rate to 115200. This is the default baud rate of the microbit:
84+
85+
```
86+
ser.baudrate = 115200
87+
```
88+
89+
Set the `ser` COM port to the one found by `find_microbit_comport()` .
90+
91+
```
92+
ser.port = find_microbit_comport()
93+
```
94+
95+
##### Writing Data
96+
97+
Before writing data the COM port must be opened. `Serial.open()` throws an exception if a connection cannot be made.
98+
99+
```
100+
ser.open()
101+
```
102+
103+
With the COM port open, we can write a command:
104+
105+
```
106+
ser.write("display.show(Image.HAPPY) \r".encode() )
107+
108+
```
109+
110+
The `\r` is a carriage return. It tells `REPL` on the microbit that return has been pressed and it should execute the line sent.
111+
112+
`.encode()` turns the string into bytes.
113+
114+
### GUI Zero
115+
116+
GUI Zero is a learner-friendly wrapper for `Tkinter`. It allows beginners to easily create GUIs for the program by removing many of the complexities of `Tkinter`.
117+
118+
It's still at the beginning phase and I'm hoping this is the first program using it!
119+
120+
##### App window
121+
122+
The program's window is an instance of the `App` class. In this example it's assigned to `app`.
123+
124+
```
125+
app = App()
126+
127+
# The app window can be modified by with parameters.
128+
# EG app = App(title="My Microbit Program") for a title.
129+
# The width, height, and other things can be changed.
130+
```
131+
132+
[App() GUIZero docs](https://lawsie.github.io/guizero/pushbutton/)
133+
134+
135+
##### Create Button
136+
137+
```
138+
connect_button = PushButton(app, text="Connect", command=connect)
139+
140+
# create an instance of the PushButton class.
141+
# The GUI parent (or master) is app (main app window).
142+
# Text is "Connect"
143+
# When it is clicked, connect() is executed
144+
```
145+
146+
[PushButton() GUIZero docs](https://lawsie.github.io/guizero/pushbutton/)
147+
148+
##### Display the GUI
149+
150+
The final line is `app.display()`. This renders the GUI we have set up.
151+
152+
##### Note About Box()
153+
154+
`Box()` in GUIZero extends the `Frame` class in `Tkinter`. It allows GUI elements such as `PushButton()` or `ButtonGroup()` to be arranged together.
155+
156+
```
157+
button_box = Box(app)
158+
```
159+
160+
In the example below, the `connect` and `disconnect` sit within the `button_box` instance of `Box()`
161+
162+
```
163+
connect_button = PushButton(button_box, text="Connect", command=connect)
164+
```
165+
166+
This allows the collection buttons to sit together in the GUI.
167+
168+
[Box() GUIZero docs](https://lawsie.github.io/guizero/box/)
169+
170+
### Final Code
171+
172+
{% highlight python %}
173+
174+
from guizero import *
175+
176+
import serial
177+
from serial.serialutil import SerialException
178+
from serial.tools import list_ports
179+
180+
def connect():
181+
try:
182+
ser.open()
183+
ser.write("from microbit import * \r".encode())
184+
except SerialException:
185+
alerts.error(app, "No Connection! Unplug microbit and try again")
186+
187+
def disconnect():
188+
ser.close()
189+
190+
"""
191+
send_data()
192+
run when send_button is clicked. Gets data from faces_to_send_list
193+
and writes to serial port as bytes
194+
195+
1. .get selected face from faces_to_send_list
196+
2. convert to bytes
197+
3. .write to serial port
198+
199+
Alternatively, 1 + 2 + 3 all on the same:
200+
ser.write((faces_to_send_list.get() + '\r').encode())
201+
"""
202+
203+
def send_data():
204+
command_to_send = faces_to_send_list.get() + '\r'
205+
command_to_send_bytes = command_to_send.encode()
206+
try:
207+
ser.write(command_to_send_bytes)
208+
except SerialException:
209+
alerts.error(app, "Could not Send. Connected?")
210+
211+
"""
212+
find_microbit_comport()
213+
returns COM port / device the microbit is attached to.
214+
215+
For each com port on the computer, check whether the
216+
attached device's product ID and vendor ID match
217+
the microbits.
218+
"""
219+
220+
def find_microbit_comport():
221+
ports = list(list_ports.comports())
222+
for p in ports:
223+
if (p.pid == 516) and (p.vid == 3368):
224+
return str(p.device)
225+
226+
# Main Program Begins
227+
228+
# serial ports
229+
ser = serial.Serial()
230+
ser.baudrate = 115200
231+
ser.port = find_microbit_comport()
232+
233+
234+
# Window setup
235+
app = App(layout='grid',
236+
height='300',
237+
width='200',
238+
title="Python Microbit Smile")
239+
240+
# button_box and its elements
241+
button_box = Box(app, grid=[0, 0])
242+
243+
connect_button = PushButton(button_box,
244+
text="Connect",
245+
command=connect,
246+
padx=3,
247+
pady=3)
248+
249+
disconnect_button = PushButton(button_box,
250+
text="Disconnect",
251+
command=disconnect,
252+
padx=3,
253+
pady=3)
254+
255+
# faces box and its elements
256+
face_box = Box(app, grid=[0, 1])
257+
258+
faces_to_send_list = ButtonGroup(face_box, [
259+
["Happy", "display.show(Image.HAPPY)"],
260+
["Sad", "display.show(Image.SAD)"],
261+
["Silly", "display.show(Image.SILLY)"],
262+
["Yes", "display.show(Image.YES)"],
263+
["No", "display.show(Image.NO)"],
264+
["Pacman", "display.show(Image.PACMAN)"],
265+
["Cow", "display.show(Image.COW)"]
266+
],
267+
"display.show(Image.HAPPY)"
268+
)
269+
270+
send_button = PushButton(face_box,
271+
text="Send",
272+
command=send_data)
273+
274+
275+
# render app window
276+
app.display()
277+
278+
{% endhighlight %}

0 commit comments

Comments
 (0)