rabbit-slide-hasumikin-RubyConfAfrica2024 2024.07.27.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rabbit +2 -0
- data/ABeginnersCompleteGuideToMicrocontrollerProgrammingWithRuby.md +659 -0
- data/README.rd +24 -0
- data/Rakefile +17 -0
- data/config.yaml +24 -0
- data/images/QR_github-com-peripheral-interface-guide.png +0 -0
- data/images/QR_github-com-picoruby.png +0 -0
- data/images/QR_picoruby.png +0 -0
- data/images/R2D2_mosaic.png +0 -0
- data/images/Terminal-dec-vt100.jpg +0 -0
- data/images/assets/background-slide.png +0 -0
- data/images/assets/background-title.png +0 -0
- data/images/assets/background.svg +70 -0
- data/images/assets/bullet-point-24.png +0 -0
- data/images/assets/bullet-point-36.png +0 -0
- data/images/assets/bullet-point-48.png +0 -0
- data/images/assets/bullet-point.png +0 -0
- data/images/assets/ruby_conf_logo.png +0 -0
- data/images/boot_button_1.png +0 -0
- data/images/crkbd_2.jpg +0 -0
- data/images/download-r2p2.png +0 -0
- data/images/drag-and-drop.png +0 -0
- data/images/hasumi.jpg +0 -0
- data/images/hello_nairobi.jpg +0 -0
- data/images/install-uf2.png +0 -0
- data/images/itoyanagi.jpg +0 -0
- data/images/lcd-and-thermo.jpg +0 -0
- data/images/lcd_and_thermo.png +0 -0
- data/images/meishi2.jpg +0 -0
- data/images/rp2-resistor-led_bb.png +0 -0
- data/images/rp2-resistor-led_schem.png +0 -0
- data/images/rp2-resistor-thermistor_bb.png +0 -0
- data/images/rp2-resistor-thermistor_schem.png +0 -0
- data/images/rp2040-peripheral-demo_bb-trim.png +0 -0
- data/images/rpi_pico.jpg +0 -0
- data/images/teraterm-0.png +0 -0
- data/images/teraterm.png +0 -0
- data/pdf/RubyConfAfrica2024-ABeginnersCompleteGuideToMicrocontrollerProgrammingWithRuby.rab.pdf +0 -0
- data/theme.rb +207 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5d880b3de7b1797b78a6917799a08fe49aa0c42803be14c3e2325c1832781d4f
|
4
|
+
data.tar.gz: 7f24cf24855037833884ae673321ed956d8fe58b422d6a2ae43dbbcb2be2327f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ab6400d9fdefbadca41052293f741ced5611b3b664d3e1268f1f5a9829c9693f2bd6c6ddd84cc754e5055ed5a23996cac04df5224219b5576a066d1952d96398
|
7
|
+
data.tar.gz: 939a9a7887e3fa4c44b3320a34996bde60ff12dc5e3d4ebcdb5ff30b152debc5da6953c4494443aad6b45b2043928a210baba58652eae6173dfed6a7a203a6b2
|
data/.rabbit
ADDED
@@ -0,0 +1,659 @@
|
|
1
|
+
# A Beginner's Complete Guide to Microcontroller Programming with Ruby
|
2
|
+
|
3
|
+
author
|
4
|
+
: hasumikin
|
5
|
+
|
6
|
+
content-source
|
7
|
+
: RubyConf Africa 2024
|
8
|
+
|
9
|
+
place
|
10
|
+
: Nairobi, Kenya
|
11
|
+
|
12
|
+
date
|
13
|
+
: 27 July 2024
|
14
|
+
|
15
|
+
allotted-time
|
16
|
+
: 33m
|
17
|
+
|
18
|
+
theme
|
19
|
+
: theme
|
20
|
+
|
21
|
+
# Today's content
|
22
|
+
|
23
|
+
{:.center}
|
24
|
+
{::tag name="x-small"}Part 1{:/tag}
|
25
|
+
Preparation\\n
|
26
|
+
|
27
|
+
{:.center}
|
28
|
+
{::tag name="x-small"}Part 2{:/tag}
|
29
|
+
Getting Started with Microcontroller\\n
|
30
|
+
|
31
|
+
{:.center}
|
32
|
+
{::tag name="x-small"}Part 3{:/tag}
|
33
|
+
Exploring PicoRuby Further\\n
|
34
|
+
|
35
|
+
{:.center}
|
36
|
+
{::tag name="x-small"}Part 4{:/tag}
|
37
|
+
PicoRuby Under the Hood\\n
|
38
|
+
|
39
|
+
|
40
|
+
# self.inspect
|
41
|
+
|
42
|
+
- Hitoshi HASUMI
|
43
|
+
- @hasumikin {::tag name="small"}(GitHub and Twitter){:/tag}
|
44
|
+
- ANDPAD: construction tech👷🏽♂️
|
45
|
+
- Creator of PicoRuby
|
46
|
+
- Contributor to CRuby and mruby
|
47
|
+
- Member of IRB maintainer team
|
48
|
+
|
49
|
+
![](images/hasumi.jpg){:
|
50
|
+
align="right"
|
51
|
+
relative-height="65"
|
52
|
+
relative_margin_top="10"
|
53
|
+
relative_margin_left="20"
|
54
|
+
}
|
55
|
+
|
56
|
+
# The former IRB maintainer
|
57
|
+
|
58
|
+
![](images/itoyanagi.jpg){:
|
59
|
+
align="center"
|
60
|
+
relative-width="100"
|
61
|
+
relative_margin_top="5"
|
62
|
+
relative_margin_left="0"
|
63
|
+
draw0="[rectangle, false, 0.55, 0.01, 0.18, 0.6, {color: red, line_width: 8\}]"
|
64
|
+
draw1="[text, Itoyanagi-san, 0.48, -0.14, {color: red, size: 50, font_family: 'Courier Prime', weight: bold\}]"
|
65
|
+
}
|
66
|
+
|
67
|
+
{:.center}
|
68
|
+
{::tag name="x-small"}RubyConf Africa 2019{:/tag}
|
69
|
+
|
70
|
+
# chapter
|
71
|
+
|
72
|
+
Part 1
|
73
|
+
{::tag name="xx-large"}Preparation{:/tag}
|
74
|
+
|
75
|
+
## Properties
|
76
|
+
hide-title
|
77
|
+
: true
|
78
|
+
|
79
|
+
# Setup (minimal)
|
80
|
+
- Raspberry Pi Pico
|
81
|
+
- Or other *RP2040)-based controller
|
82
|
+
- USB cable
|
83
|
+
- Terminal emulator on laptop
|
84
|
+
|
85
|
+
# Raspberry Pi *Pico*
|
86
|
+
- Raspberry Pi Pico: Microcontroller board
|
87
|
+
- MCU: RP2040
|
88
|
+
- Cortex-Mzero+ (dual)
|
89
|
+
- 264 KB RAM
|
90
|
+
- 2 MB flash ROM
|
91
|
+
- Generally runs without an OS
|
92
|
+
- Raspberry Pi: Single-board computer
|
93
|
+
- Generally needs an OS like Raspberry Pi OS\\nor Windows for Arm
|
94
|
+
|
95
|
+
![](images/rpi_pico.jpg){:
|
96
|
+
align="right"
|
97
|
+
relative-height="95"
|
98
|
+
relative_margin_top="0"
|
99
|
+
relative_margin_left="20"
|
100
|
+
draw0="[rectangle, false, 0.3, 0.41, 0.37, 0.2, {color: red, line_width: 8\}]"
|
101
|
+
draw1="[text, RP2040, 0.12, 0.61, {color: red, size: 70, font_family: 'Courier Prime', weight: bold\}]"
|
102
|
+
}
|
103
|
+
|
104
|
+
# Terminal emulator (recommendation)
|
105
|
+
- Linux -> GTKTerm
|
106
|
+
- Windows -> Tera Term
|
107
|
+
- macOS -> PuTTY
|
108
|
+
|
109
|
+
![](images/Terminal-dec-vt100.jpg){:
|
110
|
+
align="right"
|
111
|
+
relative-height="62"
|
112
|
+
relative_margin_top="0"
|
113
|
+
relative_margin_left="20"
|
114
|
+
}
|
115
|
+
|
116
|
+
{::tag name="large"}\\n\\n\\n{:/tag}
|
117
|
+
|
118
|
+
{:.right}
|
119
|
+
{::tag name="xx-small"}Creative Commons Attribution-ShareAlike 3.0
|
120
|
+
https://commons.wikimedia.org/w/index.php?curid=6693684{:/tag}
|
121
|
+
|
122
|
+
# Let's begin 1/4
|
123
|
+
- Download the latest\\n`R2P2-*.uf2`\\nfrom GitHub
|
124
|
+
|
125
|
+
![](images/download-r2p2.png){:
|
126
|
+
align="right"
|
127
|
+
relative-height="78"
|
128
|
+
relative_margin_left="19"
|
129
|
+
relative_margin_top="-5"
|
130
|
+
}
|
131
|
+
|
132
|
+
\\n\\n\\n\\n\\n
|
133
|
+
|
134
|
+
{:.right}
|
135
|
+
{::tag name="xx-small"}https://github.com/picoruby/R2P2/release{:/tag}
|
136
|
+
|
137
|
+
# Let's begin 1/4
|
138
|
+
BTW, R2P2 stands for
|
139
|
+
{::tag name="large"}*R*uby on *R*aspberry *P*i *P*ico{:/tag}
|
140
|
+
|
141
|
+
![](images/R2D2_mosaic.png){:
|
142
|
+
align="right"
|
143
|
+
relative-height="90"
|
144
|
+
relative_margin_left="10"
|
145
|
+
relative_margin_top="0"
|
146
|
+
}
|
147
|
+
|
148
|
+
# Let's begin 2/4
|
149
|
+
- Connect Pi Pico and PC while\\npressing the BOOTSEL button
|
150
|
+
- You'll find "RPI-RP2" drive in file manager
|
151
|
+
|
152
|
+
![](images/boot_button_1.png){:
|
153
|
+
align="right"
|
154
|
+
relative-height="78"
|
155
|
+
relative_margin_left="20"
|
156
|
+
relative_margin_top="-1"
|
157
|
+
}
|
158
|
+
|
159
|
+
\\n\\n\\n\\n\\n
|
160
|
+
|
161
|
+
{:.right}
|
162
|
+
{::tag name="xx-small"}https://www.raspberrypi.org/documentation/rp2040/getting-started{:/tag}
|
163
|
+
|
164
|
+
# Let's begin 3/4
|
165
|
+
|
166
|
+
- Drag & drop `R2P2-*.uf2` into RPI-RP2 drive
|
167
|
+
|
168
|
+
![](images/install-uf2.png){:
|
169
|
+
align="bottom"
|
170
|
+
relative-height="90"
|
171
|
+
relative_margin_left="0"
|
172
|
+
relative_margin_top="1"
|
173
|
+
}
|
174
|
+
|
175
|
+
# Let's begin 4/4
|
176
|
+
- Open a proper\\nserial port on\\nterminal emulator
|
177
|
+
|
178
|
+
![](images/teraterm-0.png){:
|
179
|
+
align="right"
|
180
|
+
relative-height="80"
|
181
|
+
relative_margin_left="22"
|
182
|
+
relative_margin_top="0"
|
183
|
+
}
|
184
|
+
|
185
|
+
# R2P2 Shell should start [Demo]
|
186
|
+
- Unix-like shell running on Raspberry Pi Pico
|
187
|
+
- You can use some\\ncommands like `cd`,\\n`ls`, `mkdir`, and *`irb`*
|
188
|
+
|
189
|
+
![](images/teraterm.png){:
|
190
|
+
align="right"
|
191
|
+
relative-height="75"
|
192
|
+
relative_margin_left="28"
|
193
|
+
relative_margin_top="5"
|
194
|
+
}
|
195
|
+
|
196
|
+
# PicoIRB [Demo]
|
197
|
+
- PicoRuby's IRB is running within the R2P2 shell on Raspberry Pi Pico
|
198
|
+
- Your Ruby snippet is compiled into mruby VM code and executed *on the fly*
|
199
|
+
- It means PicoRuby contains an mruby compiler which can run on a one-chip microcontroller (will be mentioned later)
|
200
|
+
|
201
|
+
# chapter
|
202
|
+
Part 2
|
203
|
+
{::tag name="xx-large"}Getting Started with Microcontroller{:/tag}
|
204
|
+
|
205
|
+
## Properties
|
206
|
+
hide-title
|
207
|
+
: true
|
208
|
+
|
209
|
+
# GPIO (General Purpose Input/Output)
|
210
|
+
- Fundamental digital I/O
|
211
|
+
- Variety of uses:
|
212
|
+
- Input: Detects on-off state of switch and button
|
213
|
+
- Output: Makes a voltage
|
214
|
+
- You can even implement a communication protocol by controlling GPIO in milli/micro sec
|
215
|
+
|
216
|
+
# GPIO --- Blinking LED [Demo]
|
217
|
+
|
218
|
+
irb> led = GPIO.new(25, GPIO::OUT)
|
219
|
+
irb> 5.times do
|
220
|
+
irb* led.write 1
|
221
|
+
irb* sleep 1
|
222
|
+
irb* led.write 0
|
223
|
+
irb* sleep 1
|
224
|
+
irb* end
|
225
|
+
|
226
|
+
{:.center}
|
227
|
+
{::tag name="small"}GPIO25 internally connects to\\non-board LED through a resistor{:/tag}
|
228
|
+
|
229
|
+
# GPIO --- Blinking LED by discrete parts
|
230
|
+
- Parts list:
|
231
|
+
- LED (RED)
|
232
|
+
- Resistor (1kΩ)
|
233
|
+
|
234
|
+
![](images/rp2-resistor-led_bb.png){:
|
235
|
+
align="right"
|
236
|
+
relative-height="90"
|
237
|
+
relative_margin_left="10"
|
238
|
+
relative_margin_top="0"
|
239
|
+
}
|
240
|
+
|
241
|
+
# GPIO --- Blinking LED by discrete parts
|
242
|
+
|
243
|
+
irb> pin = GPIO.new(15, GPIO::OUT)
|
244
|
+
|
245
|
+
![](images/rp2-resistor-led_bb.png){:
|
246
|
+
align="bottom"
|
247
|
+
relative-height="100"
|
248
|
+
relative_margin_left="0"
|
249
|
+
relative_margin_top="0"
|
250
|
+
}
|
251
|
+
|
252
|
+
# GPIO --- Blinking LED by discrete parts
|
253
|
+
GPIO15 ===> 1kΩ ===> LED ===> GND
|
254
|
+
<----- 1.5V -----><--- 1.8V ---->
|
255
|
+
<------------ 3.3V ------------->
|
256
|
+
|
257
|
+
- RP2040's logic level: 3.3V
|
258
|
+
- LED voltage drop: *1.8V*\\n(according to LED's datasheet)
|
259
|
+
- Current: (3.3V - 1.8V) / 1kΩ = *1.5mA*\\n(calculated by Ohm's Law)
|
260
|
+
|
261
|
+
![](images/rp2-resistor-led_schem.png){:
|
262
|
+
align="right"
|
263
|
+
relative-height="100"
|
264
|
+
relative_margin_left="15"
|
265
|
+
relative_margin_top="0"
|
266
|
+
}
|
267
|
+
|
268
|
+
# 🏫Study time: Physics
|
269
|
+
- Ohm's Law
|
270
|
+
- V = I - R ⇔ I = V / R ⇔ R = V / I
|
271
|
+
- Kirchhoff's Circuit Laws
|
272
|
+
- Current law: The algebraic sum of currents in a network of conductors meeting at a point is zero
|
273
|
+
- Voltage law: The directed sum of the potential differences (voltages) around any closed loop is zero
|
274
|
+
|
275
|
+
# Peripherals for serial communication
|
276
|
+
- I²C: To communicate between integrated circuits with support for multiple devices connected to the same bus
|
277
|
+
- SPI: To facilitate high-speed communication between microcontrollers and peripheral devices
|
278
|
+
- UART: To establish asynchronous serial communication between devices
|
279
|
+
|
280
|
+
# I²C --- Inter-Integrated Circuit
|
281
|
+
|
282
|
+
irb> require 'i2c'
|
283
|
+
irb> i2c = I2C.new(unit: :RP2040_I2C1, sda_pin: 26, scl_pin: 27)
|
284
|
+
irb> [0x38, 0x39, 0x14, 0x70, 0x56, 0x6c].each { |i| i2c.write(0x3e, 0, i); sleep_ms 1 }
|
285
|
+
irb> [0x38, 0x0c, 0x01].each { |i| i2c.write(0x3e, 0, i); sleep_ms 1 }
|
286
|
+
irb> "Hello,".bytes.each { |c| i2c.write(0x3e, 0x40, c); sleep_ms 1 }
|
287
|
+
irb> i2c.write(0x3e, 0, 0x80|0x40)
|
288
|
+
irb> "Nairobi!".bytes.each { |c| i2c.write(0x3e, 0x40, c); sleep_ms 1 }
|
289
|
+
|
290
|
+
![](images/hello_nairobi.jpg){:
|
291
|
+
relative_height="100"
|
292
|
+
relative_margin_top="0"
|
293
|
+
}
|
294
|
+
|
295
|
+
# LCD wraps I²C
|
296
|
+
|
297
|
+
# /lib/lcd.rb in R2P2 drive
|
298
|
+
require 'i2c'
|
299
|
+
class LCD
|
300
|
+
ADDRESS = 0x3e # 0x7c == (0x3e << 1) + 0 (R/W)
|
301
|
+
def initialize(i2c:)
|
302
|
+
@i2c = i2c
|
303
|
+
reset
|
304
|
+
end
|
305
|
+
def reset
|
306
|
+
[0x38, 0x39, 0x14, 0x70, 0x56, 0x6c].each { |i| @i2c.write(ADDRESS, 0, i) }
|
307
|
+
sleep_ms 200
|
308
|
+
[0x38, 0x0c, 0x01].each { |i| @i2c.write(ADDRESS, 0, i) }
|
309
|
+
end
|
310
|
+
def putc(c)
|
311
|
+
@i2c.write(ADDRESS, 0x40, c)
|
312
|
+
sleep_ms 1
|
313
|
+
end
|
314
|
+
def print(line)
|
315
|
+
line.bytes.each { |c| putc c }
|
316
|
+
end
|
317
|
+
# ...
|
318
|
+
# See https://github.com/picoruby/picoruby/tree/master/mrbgems
|
319
|
+
# /picoruby-ble/example/broadcaster-observer
|
320
|
+
{: lang="ruby"}
|
321
|
+
|
322
|
+
## properties
|
323
|
+
fill-color
|
324
|
+
: #f8f8f8
|
325
|
+
|
326
|
+
# LCD wraps I²C
|
327
|
+
|
328
|
+
irb> require 'lcd'
|
329
|
+
irb> lcd = LCD.new(i2c: I2C.new(unit: :RP2040_I2C1, sda_pin: 26, scl_pin: 27))
|
330
|
+
irb> lcd.print "Hello,"
|
331
|
+
irb> lcd.break_line
|
332
|
+
irb> lcd.print "Nairobi!"
|
333
|
+
|
334
|
+
![](images/hello_nairobi.jpg){:
|
335
|
+
relative_height="100"
|
336
|
+
relative_margin_top="0"
|
337
|
+
}
|
338
|
+
|
339
|
+
# SPI --- Serial Peripheral Interface
|
340
|
+
|
341
|
+
irb> require 'spi'
|
342
|
+
irb> spi = SPI.new(unit: :RP2040_SPI0, cipo_pin: 16,
|
343
|
+
cs_pin: 17, sck_pin: 18, copi_pin: 19)
|
344
|
+
irb> spi.select
|
345
|
+
irb> spi.write(255,255,255,255) # Reset
|
346
|
+
irb> spi.write(0x54) # Start continuous mode
|
347
|
+
irb> data = spi.read(2).bytes
|
348
|
+
irb> temp = data[0] << 8 | data[1]
|
349
|
+
irb> temp / 128.0 # Convert to Celsius
|
350
|
+
=> 19.5621
|
351
|
+
|
352
|
+
# THERMO wraps SPI
|
353
|
+
|
354
|
+
#/lib/thermo.rb in R2P2 drive
|
355
|
+
require 'spi'
|
356
|
+
class THERMO
|
357
|
+
def initialize(unit:, sck_pin:, cipo_pin:, copi_pin:, cs_pin:)
|
358
|
+
@spi = SPI.new(unit: unit, frequency: 500_000, mode: 0, cs_pin: cs_pin,
|
359
|
+
sck_pin: sck_pin, cipo_pin: cipo_pin, copi_pin: copi_pin
|
360
|
+
)
|
361
|
+
@spi.select
|
362
|
+
@spi.write 0xFF, 0xFF, 0xFF, 0xFF # Reset
|
363
|
+
@spi.write 0x54 # Start continuous mode
|
364
|
+
sleep_ms 240
|
365
|
+
end
|
366
|
+
|
367
|
+
def read
|
368
|
+
data = @spi.read(2).bytes
|
369
|
+
temp = (data[0] << 8 | data[1]) >> 3
|
370
|
+
# If it minus?
|
371
|
+
temp -= 0x2000 if 0 < temp & 0b1_0000_0000_0000
|
372
|
+
temp / 16.0 # Convert to Celsius
|
373
|
+
end
|
374
|
+
end
|
375
|
+
# See https://github.com/picoruby/picoruby/tree/master/mrbgems
|
376
|
+
# /picoruby-ble/example/broadcaster-observer
|
377
|
+
{: lang="ruby"}
|
378
|
+
|
379
|
+
# THERMO wraps SPI
|
380
|
+
|
381
|
+
irb> require 'thermo'
|
382
|
+
irb> thermo = THERMO.new(unit: :RP2040_SPI0,
|
383
|
+
cipo_pin: 16, cs_pin: 17, sck_pin: 18, copi_pin: 19)
|
384
|
+
irb> thermo.read
|
385
|
+
=> 19.5621
|
386
|
+
|
387
|
+
# LCD and THERMO
|
388
|
+
|
389
|
+
![](images/lcd_and_thermo.png){:
|
390
|
+
relative_height="100"
|
391
|
+
relative_margin_top="0"
|
392
|
+
}
|
393
|
+
|
394
|
+
# LCD and THERMO
|
395
|
+
|
396
|
+
irb> require 'lcd'
|
397
|
+
irb> lcd = LCD.new(i2c: I2C.new(unit: :RP2040_I2C1, sda_pin: 26, scl_pin: 27))
|
398
|
+
irb> require 'thermo'
|
399
|
+
irb> thermo = THERMO.new(unit: :RP2040_SPI0,
|
400
|
+
cipo_pin: 16, cs_pin: 17, sck_pin: 18, copi_pin: 19)
|
401
|
+
irb> lcd.print sprintf("%5.2f \xdfC", thermo.read)
|
402
|
+
|
403
|
+
|
404
|
+
![](images/lcd-and-thermo.jpg){:
|
405
|
+
relative_height="100"
|
406
|
+
relative_margin_top="0"
|
407
|
+
}
|
408
|
+
|
409
|
+
|
410
|
+
# chapter
|
411
|
+
Part 3
|
412
|
+
{::tag name="xx-large"}Exploring PicoRuby Further{:/tag}
|
413
|
+
|
414
|
+
## Properties
|
415
|
+
hide-title
|
416
|
+
: true
|
417
|
+
|
418
|
+
# PicoRuby killer applications
|
419
|
+
- R2P2
|
420
|
+
- Microcontroller application framework
|
421
|
+
- Unix-like shell system and IRB written in PicoRuby
|
422
|
+
- PRK Firmware
|
423
|
+
- Keyboard firmware framework for DIY keyboard
|
424
|
+
- You can write your keymap and keyboard's behavior with Ruby
|
425
|
+
|
426
|
+
# R2P2 (again)
|
427
|
+
- IRB
|
428
|
+
- Multiple-line editor
|
429
|
+
- Built-in commands and executables (all written in Ruby)
|
430
|
+
- You can write your own external command
|
431
|
+
|
432
|
+
# Executables in R2P2, for example,
|
433
|
+
|
434
|
+
# date
|
435
|
+
puts Time.now.to_s
|
436
|
+
{: lang="ruby"}
|
437
|
+
|
438
|
+
# mkdir
|
439
|
+
Dir.mkdir(ARGV[0])
|
440
|
+
{: lang="ruby"}
|
441
|
+
|
442
|
+
# Write a Ruby script file [Demo]
|
443
|
+
|
444
|
+
$> vim hello.rb
|
445
|
+
|
446
|
+
{:.center}
|
447
|
+
Edit the file and save it.
|
448
|
+
|
449
|
+
puts "Hello World!"
|
450
|
+
{: lang="ruby"}
|
451
|
+
|
452
|
+
{:.center}
|
453
|
+
Then run it.
|
454
|
+
|
455
|
+
$> ./hello.rb
|
456
|
+
|
457
|
+
# Make a standalone IoT device
|
458
|
+
|
459
|
+
# `/home/app.rb` automatically runs
|
460
|
+
require 'lcd'
|
461
|
+
require 'thermo'
|
462
|
+
|
463
|
+
led = GPIO.new(25, GPIO::OUT)
|
464
|
+
lcd = LCD.new(i2c: I2C.new(unit: :RP2040_I2C1,
|
465
|
+
sda_pin: 26, scl_pin: 27))
|
466
|
+
thermo = THERMO.new(unit: :RP2040_SPI0, cipo_pin: 16,
|
467
|
+
cs_pin: 17, sck_pin: 18, copi_pin: 19)
|
468
|
+
|
469
|
+
# Stop infinite loop by Ctrl-C
|
470
|
+
while true
|
471
|
+
temp = thermo.read
|
472
|
+
lcd.clear
|
473
|
+
sleep 0.1
|
474
|
+
lcd.print sprintf("%5.2f \xdfC", temp)
|
475
|
+
sleep 1
|
476
|
+
led.write(30 < temp ? 1 : 0)
|
477
|
+
end
|
478
|
+
{: lang="ruby"}
|
479
|
+
|
480
|
+
# Make a standalone IoT device
|
481
|
+
|
482
|
+
![](images/drag-and-drop.png){:
|
483
|
+
align="bottom"
|
484
|
+
relative-height="90"
|
485
|
+
relative_margin_left="0"
|
486
|
+
relative_margin_top="3"
|
487
|
+
}
|
488
|
+
|
489
|
+
# chapter
|
490
|
+
Part 4
|
491
|
+
{::tag name="xx-large"}PicoRuby Under the Hood{:/tag}
|
492
|
+
|
493
|
+
## Properties
|
494
|
+
hide-title
|
495
|
+
: true
|
496
|
+
|
497
|
+
# mruby and PicoRuby
|
498
|
+
- mruby
|
499
|
+
- General purpose embedded Ruby implementation written by Matz
|
500
|
+
- PicoRuby (PicoRuby compiler + mruby/c VM)
|
501
|
+
- Another implementation of murby targeting on one-chip microcontroller (*smaller foot print*)
|
502
|
+
- Based on the mruby's VM code standard
|
503
|
+
|
504
|
+
# Small foot print
|
505
|
+
|
506
|
+
$ valgrind \
|
507
|
+
--tool=massif \
|
508
|
+
--stacks=yes \
|
509
|
+
path/to/(mruby|picoruby) \
|
510
|
+
-e 'puts "Hello World!"'
|
511
|
+
|
512
|
+
{:.center}
|
513
|
+
`massif.out.[pid]` file will be created. Then,
|
514
|
+
|
515
|
+
$ ms_print massif.out.1234 | less
|
516
|
+
|
517
|
+
# Small foot print
|
518
|
+
|
519
|
+
--------------------------------------------------------------------------------
|
520
|
+
Command: mruby -e 'puts "Hello World!"'
|
521
|
+
Massif arguments: --stacks=yes
|
522
|
+
ms_print arguments: massif.out.18391
|
523
|
+
--------------------------------------------------------------------------------
|
524
|
+
KB
|
525
|
+
133.5^ #
|
526
|
+
| #
|
527
|
+
| #
|
528
|
+
| #
|
529
|
+
| #
|
530
|
+
| #
|
531
|
+
| #
|
532
|
+
| #
|
533
|
+
| @ :@:::@:#:
|
534
|
+
| @:@@@::::@:::@:#::
|
535
|
+
| ::@::::::@::::::::@:@@@::::@:::@:#::
|
536
|
+
| @:::::::::@@::::@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
537
|
+
| @@@:::@:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
538
|
+
| @ :: @:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
539
|
+
| @ :: @:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
540
|
+
| @ :: @:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
541
|
+
| @ :: @:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
542
|
+
| @ :: @:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
543
|
+
| @ :: @:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
544
|
+
| @ @ :: @:::::::::@ :: :@:::@::::::@:::::: :@:@@@::::@:::@:#::
|
545
|
+
0 +----------------------------------------------------------------------->Mi
|
546
|
+
0 1.281
|
547
|
+
Note: Measured in 64 bit Ubuntu
|
548
|
+
|
549
|
+
# Small foot print
|
550
|
+
|
551
|
+
--------------------------------------------------------------------------------
|
552
|
+
Command: picoruby -e 'puts "Hello World!"'
|
553
|
+
Massif arguments: --stacks=yes
|
554
|
+
ms_print arguments: massif.out.21752
|
555
|
+
--------------------------------------------------------------------------------
|
556
|
+
KB
|
557
|
+
9.820^ #
|
558
|
+
| @:#:::
|
559
|
+
| @:#:::::
|
560
|
+
| @:#:::::
|
561
|
+
| @:#:::::
|
562
|
+
| @ @:#:::::
|
563
|
+
| @ @:#:::::
|
564
|
+
| @ : @:#:::::
|
565
|
+
| @ ::: @:#:::::
|
566
|
+
| @ : ::: @:#:::::
|
567
|
+
| @ ::@::::@:#:::::@
|
568
|
+
| @ ::@::::@:#:::::@
|
569
|
+
| @: :::::@::::@:#:::::@
|
570
|
+
| @::: :: :::@::::@:#:::::@
|
571
|
+
| @:: ::: :::@::::@:#:::::@
|
572
|
+
| @:: : ::: :::@::::@:#:::::@
|
573
|
+
| @:: : ::: :::@::::@:#:::::@
|
574
|
+
| :@:: : : :: :@:@: : :@@: ::@::::: ::: :::@::::@:#:::::@
|
575
|
+
| :@:: :::::::::::::::@:@:@:::::@ ::: @:: : :::: :::@::::@:#:::::@
|
576
|
+
|::::::@::@:: ::: ::: :::::@:@:@:: ::@ : : @:: : :::: :::@::::@:#:::::@
|
577
|
+
0 +----------------------------------------------------------------------->ki
|
578
|
+
0 324.5
|
579
|
+
Note: Measured in 64 bit Ubuntu
|
580
|
+
|
581
|
+
# Small foot print
|
582
|
+
|
583
|
+
- RAM consumption of `puts "Hello World!"`
|
584
|
+
- mruby: 133.5 KB (on 64 bit)
|
585
|
+
- PicoRuby: 9.82 KB (on 64 bit)
|
586
|
+
- RP2040 (32 bit) has 264 KB RAM
|
587
|
+
- Only small applications written in mruby should work
|
588
|
+
- R2P2 and PRK Firmware should be written in PicoRuby
|
589
|
+
|
590
|
+
# PRK Firmware: DIY keyboard firmware
|
591
|
+
![](images/crkbd_2.jpg){:
|
592
|
+
relative_height="95"
|
593
|
+
}
|
594
|
+
|
595
|
+
# PRK Firmware on Meishi2 (4-keys macro pad)
|
596
|
+
![](images/meishi2.jpg){:
|
597
|
+
relative_height="95"
|
598
|
+
}
|
599
|
+
|
600
|
+
# PRK Firmware on Meishi2 (4-keys macro pad)
|
601
|
+
|
602
|
+
require "consumer_key"
|
603
|
+
kbd = Keyboard.new
|
604
|
+
kbd.init_pins(
|
605
|
+
[ 6, 7 ], # row0, row1
|
606
|
+
[ 28, 27 ] # col0, col1
|
607
|
+
)
|
608
|
+
kbd.add_layer :default, %i[ RAISE KC_2 KC_A KC_4 ]
|
609
|
+
kbd.add_layer :raise, %i[ RAISE
|
610
|
+
KC_AUDIO_VOL_UP
|
611
|
+
KC_AUDIO_VOL_DOWN
|
612
|
+
KC_AUDIO_MUTE ]
|
613
|
+
kbd.define_mode_key :RAISE, [ :KC_SPACE, :raise, 200, 200 ]
|
614
|
+
kbd.start!
|
615
|
+
{: lang="ruby"}
|
616
|
+
|
617
|
+
# PicoRuby ecosystem
|
618
|
+
- Picogems
|
619
|
+
- PRK Firmware is also a Picogem
|
620
|
+
- Peripheral gems
|
621
|
+
- picoruby-gpio, picoruby-adc, picoruby-i2c,\\npicoruby-spi, picoruby-uart, picoruby-pwm
|
622
|
+
- Peripheral interface guide
|
623
|
+
- https://github.com/mruby/\\nmicrocontroller-peripheral-interface-guide
|
624
|
+
|
625
|
+
![](images/QR_github-com-peripheral-interface-guide.png){:
|
626
|
+
align="right"
|
627
|
+
relative_height="70"
|
628
|
+
relative_margin_top="0"
|
629
|
+
relative_margin_left="22"
|
630
|
+
}
|
631
|
+
|
632
|
+
# PicoRuby ecosystem
|
633
|
+
- Build system forked from mruby
|
634
|
+
- You can build your application in a similar way to mruby
|
635
|
+
- You can also write your gem and host it on your GitHub
|
636
|
+
- RP2040 is the only target as of now though,
|
637
|
+
- Carefully designed to keep portability
|
638
|
+
|
639
|
+
# Conclusion
|
640
|
+
- PicoRuby is a Ruby implementaiton targeting on one-chip microcontroller
|
641
|
+
- You can prototype your microcontroller application step-by-step using R2P2 and IRB
|
642
|
+
- You don't need any compiler or linker
|
643
|
+
- Educational and fun to learn about microcontroller programming
|
644
|
+
|
645
|
+
# chapter
|
646
|
+
|
647
|
+
{::tag name="xx-large"}Stargaze at{:/tag}
|
648
|
+
|
649
|
+
![](images/QR_picoruby.png){:
|
650
|
+
relative_height="70"
|
651
|
+
}
|
652
|
+
|
653
|
+
github.com/picoruby/picoruby
|
654
|
+
|
655
|
+
|
656
|
+
## Properties
|
657
|
+
hide-title
|
658
|
+
: true
|
659
|
+
|
data/README.rd
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
= A Beginner's Complete Guide to Microcontroller Programming with Ruby
|
2
|
+
|
3
|
+
Presentation slide for Euruko 2023
|
4
|
+
|
5
|
+
== For author
|
6
|
+
|
7
|
+
=== Show
|
8
|
+
|
9
|
+
rake
|
10
|
+
|
11
|
+
=== Publish
|
12
|
+
|
13
|
+
rake publish
|
14
|
+
|
15
|
+
== For viewers
|
16
|
+
|
17
|
+
=== Install
|
18
|
+
|
19
|
+
gem install rabbit-slide-hasumikin-Euruko2023
|
20
|
+
|
21
|
+
=== Show
|
22
|
+
|
23
|
+
rabbit rabbit-slide-hasumikin-Euruko2023.gem
|
24
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rabbit/task/slide"
|
2
|
+
|
3
|
+
# Edit ./config.yaml to customize meta data
|
4
|
+
|
5
|
+
spec = nil
|
6
|
+
Rabbit::Task::Slide.new do |task|
|
7
|
+
spec = task.spec
|
8
|
+
# spec.files += Dir.glob("doc/**/*.*")
|
9
|
+
# spec.files -= Dir.glob("private/**/*.*")
|
10
|
+
# spec.add_runtime_dependency("rabbit-theme-YOUR-THEME")
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Tag #{spec.version}"
|
14
|
+
task :tag do
|
15
|
+
sh("git", "tag", "-a", spec.version.to_s, "-m", "Publish #{spec.version}")
|
16
|
+
sh("git", "push", "--tags")
|
17
|
+
end
|