rabbit-slide-hasumikin-RubyConfAfrica2024 2024.07.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
592
|
+
relative_height="95"
|
593
|
+
}
|
594
|
+
|
595
|
+
# PRK Firmware on Meishi2 (4-keys macro pad)
|
596
|
+
{:
|
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
|
+
{:
|
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
|
+
{:
|
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
|