Examples
All code examples can be found in the examples directory of the repository.
Find all devices
Find and display all Free-Wili devices.
1"""Example to find all Free-Wilis connected over USB."""
2
3import result
4
5from freewili import FreeWili
6
7# Find the first device and raise an exception otherwise
8try:
9 device = FreeWili.find_first().expect("Failed to find a FreeWili")
10except result.UnwrapError as ex:
11 print(ex)
12
13# Find all and display information about it.
14devices = FreeWili.find_all()
15print(f"Found {len(devices)} FreeWili(s)")
16for i, free_wili in enumerate(devices, start=1):
17 print(f"{i}. {free_wili}")
18 print(f"\t{free_wili.main}")
19 print(f"\t{free_wili.display}")
20 print(f"\t{free_wili.ftdi}")
Upload files
Upload files to the first Free-Wili device.
1"""Upload a wasm file to a Free-Wili."""
2
3import pathlib
4
5from freewili import FreeWili
6
7# The fwi file to upload
8my_fwi_file = pathlib.Path(r"~/path/to/MyFile.fwi")
9# The wasm file to upload
10my_wasm_file = pathlib.Path(r"~/path/to/MyFile.wasm")
11
12# Find connected Free-Wilis
13devices = FreeWili.find_all()
14if not devices:
15 print("No Free-Wili devices found!")
16 exit(1)
17
18# Pick the first Free-Wili
19device = devices[0]
20
21# We can leave target_name and processor None and it will automatically
22# figure out where to send the file.
23device.send_file(my_fwi_file, None, None).expect("Failed to upload file")
24device.send_file(my_wasm_file, None, None).expect("Failed to upload file")
25device.run_script(my_wasm_file.name).expect("Failed to run script")
Toggle IO
Toggles IO on the first Free-Wili device.
1"""Toggle IO on a Free-Wili."""
2
3from freewili import FreeWili
4from freewili.types import IOMenuCommand
5
6# find a FreeWili device and open it
7device = FreeWili.find_first().expect("Failed to find a FreeWili")
8device.open().expect("Failed to open")
9
10# Set IO 25 high
11print(device.set_io(25, IOMenuCommand.High).expect("Failed to set IO high"))
12# Set IO 25 Low
13print(device.set_io(25, IOMenuCommand.Low).expect("Failed to set IO low"))
14# Toggle IO 25 Low
15print(device.set_io(25, IOMenuCommand.Toggle).expect("Failed to toggle IO"))
16# PWM IO 25
17print(device.set_io(25, IOMenuCommand.Pwm, 10, 50).expect("Failed to toggle IO"))
18
19device.close()
Set Board LEDs
Set Board LEDs on the first Free-Wili device.
1"""Set Board RGB on a Free-Wili."""
2
3import time
4
5from freewili import FreeWili
6
7# find a FreeWili device and open it
8device = FreeWili.find_first().expect("Failed to find a FreeWili")
9device.open().expect("Failed to open")
10
11# Turn the LEDs on
12for led_num in range(7):
13 print(device.set_board_leds(led_num, 10, 10, led_num * 2).expect("Failed to set LED"))
14# Wait so we can see them
15time.sleep(3)
16# Turn the LEDS off
17for led_num in reversed(range(7)):
18 print(device.set_board_leds(led_num, 0, 0, 0).expect("Failed to set LED"))
19
20device.close()
SparkFun 9DoF IMU Breakout - ISM330DHCX, MMC5983MA (Qwiic)
SparkFun 9DoF IMU Breakout example over I2C.
1"""Example I2C on a FreeWili with SparkFun 9DoF IMU Breakout - ISM330DHCX, MMC5983MA (Qwiic) attached.
2
3https://www.sparkfun.com/sparkfun-9dof-imu-breakout-ism330dhcx-mmc5983ma-qwiic.html
4ISM330DHCX I2C Address: 0x6B (Default)
5MMC5983MA Magnetometer I2C Address: 0x30
6"""
7
8import enum
9
10from result import Err, Ok
11
12from freewili import FreeWili
13
14MMC5983MA_ADDR = 0x30
15ISM330DHCX_ADDR = 0x6B
16
17
18class MMC5983MA(enum.Enum):
19 """Register list for MMC5983MA Magnetometer."""
20
21 Xout0 = 0x00 # Xout [17:10]
22 Xout1 = 0x01 # Xout [9:2]
23 Yout0 = 0x02 # Yout [17:10]
24 Yout1 = 0x03 # Yout [9:2]
25 Zout0 = 0x04 # Zout [17:10]
26 Zout1 = 0x05 # Zout [9:2]
27 XYZout2 = 0x06 # Xout[1:0], Yout[1:0], Zout[1:0]
28 Tout = 0x07 # Temperature output
29 Status = 0x08 # Device status
30 Control0 = 0x09 # Control register 0
31 Control1 = 0x0A # Control register 1
32 Control2 = 0x0B # Control register 2
33 Control3 = 0x0C # Control register 3
34 ProductID = 0x2F # Product ID
35
36
37class ISM330DHCX(enum.Enum):
38 """Register list for ISM330DHCX."""
39
40 FUNC_CFG_ACCESS = 0x01
41 PIN_CTRL = 0x02
42 FIFO_CTRL1 = 0x07
43 FIFO_CTRL2 = 0x08
44 FIFO_CTRL3 = 0x09
45 FIFO_CTRL4 = 0x0A
46 COUNTER_BDR_REG1 = 0x0B
47 COUNTER_BDR_REG2 = 0x0C
48 INT1_CTRL = 0x0D
49 INT2_CTRL = 0x0E
50 WHO_AM_I = 0x0F
51 CTRL1_XL = 0x10
52 CTRL2_G = 0x11
53 CTRL3_C = 0x12
54 CTRL4_C = 0x13
55 CTRL5_C = 0x14
56 CTRL6_C = 0x15
57 CTRL7_G = 0x16
58 CTRL8_XL = 0x17
59 CTRL9_XL = 0x18
60 CTRL10_C = 0x19
61 ALL_INT_SRC = 0x1
62 WAKE_UP_SRC = 0x1B
63 TAP_SRC = 0x1C
64 DRD_SRC = 0x1D
65 STATUS_REG = 0x1E
66 STATUS_SPIAux = 0x1E
67 OUT_TEMP_L = 0x20
68 OUT_TEMP_H = 0x21
69 OUTX_L_G = 0x22
70 OUTX_H_G = 0x23
71 OUTY_L_G = 0x24
72 OUTY_H_G = 0x25
73 OUTZ_L_G = 0x26
74 OUTZ_H_G = 0x27
75 OUTX_L_A = 0x28
76 OUTX_H_A = 0x29
77 OUTY_L_A = 0x2A
78 OUTY_H_A = 0x2B
79 OUTZ_L_A = 0x2C
80 OUTZ_H_A = 0x2D
81 EMB_FUNC_STATUS_MAINPAGE = 0x35
82 FSM_STATUS_A_MAINPAGE = 0x36
83 FSM_STATUS_B_MAINPAGE = 0x37
84 MLC_STATUS_MAINPAGE = 0x38
85 STATUS_MASTER_MAINPAGE = 0x39
86 FIFO_STATUS1 = 0x3A
87 FIFO_STATUS2 = 0x3B
88 TIMESTAMP0 = 0x40
89 TIMESTAMP1 = 0x41
90 TIMESTAMP2 = 0x42
91 TIMESTAMP3 = 0x43
92 TAP_CFG0 = 0x56
93 TAP_CFG1 = 0x57
94 TAP_CFG2 = 0x58
95 TAP_THS_6D = 0x59
96 INT_DUR2 = 0x5A
97 WAKE_UP_THS = 0x5B
98 WAKE_UP_DUR = 0x5C
99 FREE_FALL = 0x5D
100 MD1_CFG = 0x5E
101 MD2_CFG = 0x5F
102 INTERNAL_FREQ_FINE = 0x63
103 INT_OIS = 0x6F
104 CTRL1_OIS = 0x70
105 CTRL2_OIS = 0x71
106 CTRL3_OIS = 0x72
107 X_OFS_USR = 0x73
108 Y_OFS_USR = 0x74
109 Z_OFS_USR = 0x75
110 FIFO_DATA_OUT_TAG = 0x78
111 FIFO_DATA_OUT_X_L = 0x79
112 FIFO_DATA_OUT_X_H = 0x7A
113 FIFO_DATA_OUT_Y_L = 0x7B
114 FIFO_DATA_OUT_Y_H = 0x7C
115 FIFO_DATA_OUT_Z_L = 0x7D
116 FIFO_DATA_OUT_Z_H = 0x7E
117
118
119def get_mmc5983ma_temperature(device: FreeWili) -> tuple[float, int]:
120 """Get temperature on MMC5983MA.
121
122 Arguments:
123 ----------
124 device: FreeWili
125 FreeWili device to use.
126
127 Returns:
128 --------
129 tuple[float, int]:
130 (Temperature in degrees Celcius, timestamp in ns).
131 """
132 resp = device.write_i2c(MMC5983MA_ADDR, MMC5983MA.Control0.value, bytes([0x2A])).expect("Enable temp measure")
133 # print(resp.is_ok())
134 # print("Waiting for temperature measurement...")
135 while True:
136 resp = device.read_i2c(MMC5983MA_ADDR, MMC5983MA.Status.value, 1).expect("Reading Status failed")
137 status = resp.response_as_bytes().expect("Status bytes")[0]
138 if (status & 0x2) == 0x2:
139 # print("Temperature measurement done!")
140 break
141 resp = device.read_i2c(MMC5983MA_ADDR, MMC5983MA.Tout.value, 1).expect("Reading Tout failed")
142 # Temperature output, unsigned format. The range is -75~125°C, about 0.8°C/LSB, 00000000 stands for -75°C
143 temp = resp.response_as_bytes().expect("MMC5983MA.Tout")
144 temp_int = int.from_bytes(temp, byteorder="little", signed=False)
145 converted = temp_int * 0.8 - 75
146 # print(resp._raw.strip())
147 return (converted, resp.timestamp)
148
149
150def get_mmc5983ma_magnetic_sensor(device: FreeWili) -> tuple[tuple[int, int, int], int]:
151 """Get magnetic field data on MMC5983MA.
152
153 Arguments:
154 ----------
155 device: FreeWili
156 FreeWili device to use.
157
158 Returns:
159 --------
160 tuple[tuple[int, int, int], int]:
161 ((x, y, z), timestamp in ns).
162 """
163 resp = device.write_i2c(MMC5983MA_ADDR, MMC5983MA.Control0.value, bytes([0x29])).expect("Enable magnetic field")
164 # print(resp.is_ok())
165 # print("Waiting for temperature measurement...")
166 while True:
167 resp = device.read_i2c(MMC5983MA_ADDR, MMC5983MA.Status.value, 1).expect("Reading Status failed")
168 status = resp.response_as_bytes().expect("Status bytes")[0]
169 if (status & 0x1) == 0x1:
170 # print("Temperature measurement done!")
171 break
172 resp = device.read_i2c(MMC5983MA_ADDR, MMC5983MA.Xout0.value, 6).expect("Reading Tout failed")
173 data = resp.response_as_bytes().expect("MMC5983MA.Xout0")
174 x = int.from_bytes(data[0:2], byteorder="little", signed=False) << 2
175 y = int.from_bytes(data[2:4], byteorder="little", signed=False) << 2
176 z = int.from_bytes(data[4:6], byteorder="little", signed=False) << 2
177 # print(resp._raw.strip())
178 return ((x, y, z), resp.timestamp)
179
180
181# find a FreeWili device
182match FreeWili.find_first():
183 case Ok(d):
184 device = d
185 device.stay_open = True
186 print(f"Using {device}")
187 case Err(msg):
188 print(msg)
189 exit(1)
190
191try:
192 # Poll the I2C to make sure we can read the breakout board
193 print("Polling I2C...")
194 resp = device.poll_i2c().expect("Failed to poll i2c")
195 addresses = resp.response_as_bytes().expect("Failed to get response bytes")
196 if addresses != bytes([2, MMC5983MA_ADDR, ISM330DHCX_ADDR]):
197 print(f"Expected addresses on I2C are incorrect, got {list(addresses)}!")
198 exit(1)
199
200 first_ts = resp.timestamp
201 print(resp.timestamp_as_datetime().expect("Failed to convert to datetime"))
202 while True:
203 try:
204 temp_c, ts = get_mmc5983ma_temperature(device)
205 temp_f = temp_c * 1.8 + 32
206 print(f"[{ts - first_ts}] Temperature: {temp_c:.2f}C ({temp_f:.2f}F)")
207 magnetic_data, ts = get_mmc5983ma_magnetic_sensor(device)
208 print(f"[{ts - first_ts}] Magnetic Field: {magnetic_data}")
209 except KeyboardInterrupt:
210 break
211finally:
212 device.close()
213
214print("Done.")