Skip to content

Instantly share code, notes, and snippets.

@hasumikin
Last active February 16, 2026 08:08
Show Gist options
  • Select an option

  • Save hasumikin/efec6e6ff27a8daf46d3d4cf7b350774 to your computer and use it in GitHub Desktop.

Select an option

Save hasumikin/efec6e6ff27a8daf46d3d4cf7b350774 to your computer and use it in GitHub Desktop.

※和文はページ下部にあります

PicoRuby Workshop 2025 - Useful Gems

Previous sections:

  1. Setup + LED: https://tinyurl.com/picoruby-2025
  2. Microphone: https://tinyurl.com/picoruby-mic
  3. Buzzer: https://tinyurl.com/picoruby-buzzer

So far we've learned the fundamental peripherals: GPIO, ADC, and PWM. These are the building blocks of all microcontroller programming. Now let's explore how PicoRuby's gem system makes working with complex sensors much easier!

Understanding Peripherals

Before diving into gems, let's review what we've learned:

Core Peripherals:

  • GPIO (General Purpose Input/Output): Digital on/off control

    • Examples: LED control, button reading
    • GPIO.new(pin, GPIO::OUT) or GPIO.new(pin, GPIO::IN)
  • ADC (Analog-to-Digital Converter): Reading analog signals

    • Examples: Microphone, temperature sensor, light sensors
    • ADC.new(pin) gives 12-bit values (0-4095)
  • PWM (Pulse Width Modulation): Simulating analog output

    • Examples: Buzzer tones, LED brightness, motor speed control
    • PWM.new(pin) with frequency() and duty() methods
  • [new!] I2C (Inter-Integrated Circuit): Digital communication protocol

    • Examples: OLED displays, advanced sensors, EEPROMs
    • Two-wire communication: SDA (data) and SCL (clock)
    • I2C is slightly complex to try in IRB (but doable)

Gems: High-Level Hardware Abstraction

PicoRuby gems wrap these basic peripherals to provide easy-to-use interfaces for specific hardware modules. Instead of manually handling GPIO timing or I2C protocols, gems give you simple, intuitive methods.

Let's explore two powerful gems:

HC-SR04 Ultrasonic Distance Sensor

The HC-SR04 uses GPIO pins with precise timing to measure distance using ultrasonic sound waves.

Components needed:

  • 1x HC-SR04 ultrasonic sensor
  • Jumper wires

Wiring:

RP2[3V3]  --- HC-SR04[VCC]
RP2[GND]  --- HC-SR04[GND]
RP2[GP0]  --- HC-SR04[Echo]
RP2[GP1]  --- HC-SR04[Trig]

See the wiring diagram in the previous section.

Basic Distance Measurement

irb> require 'hcsr04'
irb> hcsr04 = HCSR04.new(echo: 0, trig: 1)
irb> hcsr04.distance_cm
=> 23.4

The gem handles all the complex timing internally:

  1. Sends a short trigger pulse to the Trig pin
  2. Measures the duration of the Echo pin's high state
  3. Calculates distance using: distance = (duration × sound_speed) / 2

You can find the implementation here: https://github.com/picoruby/picoruby/blob/master/mrbgems/picoruby-hcsr04/mrblib/hcsr04.rb

Distance Monitor with LED

Save this as distance_monitor.rb:

require 'pwm'
require 'hcsr04'

hcsr04 = HCSR04.new(echo: 0, trig: 1)
buzzer = PWM.new(11)
buzzer.duty 50
buzzer.frequency 0

puts "Distance Monitor Started!"
puts "Buzzer will sound when an object is detected within range."

while true
  begin
    distance = hcsr04.distance_cm
    puts "Distance: #{distance} cm"
    # closer = faster blink
    buzzer.frequency((5000 - (distance * 10)) / 10)
  rescue
    puts "Distance: Out of range"
    buzzer.frequency 0
    sleep 1
  end
  sleep 0.5
end

SSD1306 OLED Display

The SSD1306 is a popular OLED display that uses I2C communication. The gem handles all the complex I2C protocol details.

Components needed:

  • 1x SSD1306 OLED Display (128x64 pixels)
  • Jumper wires

Wiring:

RP2[3V3] --- OLED[VCC]
RP2[GND] --- OLED[GND]
RP2[GP8] --- OLED[SDA]
RP2[GP9] --- OLED[SCL]

Basic Display Setup

irb> require 'ssd1306'
irb> width = 128
irb> height = 64
irb> i2c = I2C.new(unit: :RP2040_I2C0, sda_pin: 8, scl_pin: 9)
irb> display = SSD1306.new(i2c: i2c, w: width, h: height)

Drawing Graphics

# Clear the display
irb> display.clear

# Draw lines (Display does not auto-update at this point)
irb> display.draw_line(0, 0, width-1, height-1, 1)
irb> display.draw_line(width-1, 0, 0, height-1, 1)

# Update display to show changes
irb> display.update_display

Drawing Shapes

# Clear and draw rectangles
irb> display.clear
irb> display.draw_rect(10, 10, 30, 20, 1, false)  # Outline rectangle
irb> display.draw_rect(50, 20, 25, 15, 1, true)   # Filled rectangle
irb> display.update_display

Displaying Text

# Clear and show text
irb> display.clear
irb> display.draw_text(:terminus_6x12, 0, 24, "Hello PicoRuby!")
irb> display.draw_text(:terminus_6x12, 0, 40, "Workshop 2025")
irb> display.update_display

Complete OLED Demo

Save this as oled_demo.rb:

require 'ssd1306'

width = 128
height = 64
i2c = I2C.new(unit: :RP2040_I2C0, sda_pin: 8, scl_pin: 9, frequency: 400_000)
display = SSD1306.new(i2c: i2c, w: width, h: height)

puts "OLED Demo Started!"

# Demo 1: Text welcome
display.clear
display.draw_text(:terminus_6x12, 0, 0, "EuRuKo 2025")
display.draw_text(:terminus_16x32, 0, 16, "PicoRuby")
display.draw_text(:terminus_8x16, 0, 48, "Workshop Demo")
display.update_display
sleep 3

# Demo 2: Geometric patterns
display.clear
display.draw_line(0, 0, width-1, height-1, 1)
display.draw_line(width-1, 0, 0, height-1, 1)
display.draw_line(width/2, 0, width/2, height-1, 1)
display.draw_line(0, height/2, width-1, height/2, 1)
display.update_display
sleep 3

# Demo 3: Rectangles
display.clear
display.draw_rect(10, 10, 30, 20, 1, false)
display.draw_rect(50, 20, 25, 15, 1, true)
display.draw_rect(85, 35, 35, 25, 1, false)
display.update_display
sleep 3

# Demo 4: Animation - moving dot
display.clear
display.draw_text(:terminus_12x24, 0, 0, "Moving Dot!")
x = 0
y = 16
10.times do
  display.draw_rect(x, y, 4, 4, 1, true)
  display.update_display_optimized # only update changed pages
  display.erase(x, y, 4, 4)
  sleep 0.3
  x += 12
  y += 4
end

puts "Demo complete!"

You can find the full API list here: https://github.com/picoruby/picoruby/blob/master/mrbgems/picoruby-ssd1306/sig/ssd1306.rbs

Exercises

Challenge yourself with these advanced projects:

  1. OLED Sound Visualizer: Display microphone levels on the OLED in real-time:

    # Show sound level as a bar graph
    # Include peak hold indicator
  2. Interactive Distance Game: Create a game using the OLED display:

    • Display a target distance (e.g., "Get 25cm away!")
    • Show current distance and "warmer/colder" feedback
    • Score based on how quickly user achieves target
    • Multiple rounds with different targets
  3. OLED Animation Engine: Create a simple animation system:

    # Bouncing ball physics
    # Multiple moving objects
    # Collision detection with distance sensor
    # Sound effects synchronized with animations

便利な Gems

前のセクション:

  1. Setup + LED: https://tinyurl.com/picoruby-2025
  2. Microphone: https://tinyurl.com/picoruby-mic
  3. Buzzer: https://tinyurl.com/picoruby-buzzer

これまでに、基本となる周辺機能である GPIOADCPWM を学びました。これらは、あらゆるマイコンプログラミングの土台です。ここからは、PicoRuby の gem システムによって、複雑なセンサをどれだけ簡単に扱えるようになるのかを見ていきましょう!

周辺機能を理解する

gem に入る前に、これまで学んだことを振り返ります。

基本の周辺機能:

  • GPIO(General Purpose Input/Output): デジタルのオン/オフ制御

    • 例: LED 制御、ボタンの読み取り
    • GPIO.new(pin, GPIO::OUT) または GPIO.new(pin, GPIO::IN)
  • ADC(Analog-to-Digital Converter): アナログ信号の読み取り

    • 例: マイク、温度センサ、光センサ
    • ADC.new(pin) は 12 ビット値(0〜4095)を返します
  • PWM(Pulse Width Modulation): アナログ出力の擬似的な再現

    • 例: ブザーの音、LED の明るさ、モータの速度制御
    • PWM.new(pin)frequency()duty() メソッド
  • [new!] I2C(Inter-Integrated Circuit): デジタル通信プロトコル

    • 例: OLED ディスプレイ、高度なセンサ、EEPROM
    • 2 本の線で通信します: SDA(data)と SCL(clock)
    • I2C は IRB で試すには少し複雑です(ただし可能です)

Gems: 高レベルなハードウェア抽象化

PicoRuby の gem は、これらの基本周辺機能をラップして、特定のハードウェアモジュールのための使いやすいインターフェースを提供します。GPIO のタイミング制御や I2C プロトコルを手作業で扱う代わりに、gem でシンプルで直感的なメソッドを使えるようになります。

ここでは、強力な 2 つの gem を試します。

HC-SR04 超音波距離センサ

HC-SR04 は、超音波の反射を使って距離を測ります。距離測定には、正確なタイミングで GPIO ピンを扱う必要があります。

必要な部品:

  • 1x HC-SR04 超音波センサ
  • ジャンパーワイヤ

配線:

RP2[3V3]  --- HC-SR04[VCC]
RP2[GND]  --- HC-SR04[GND]
RP2[GP0]  --- HC-SR04[Echo]
RP2[GP1]  --- HC-SR04[Trig]

配線図は前のセクションを参照してください。

基本的な距離測定

irb> require 'hcsr04'
irb> hcsr04 = HCSR04.new(echo: 0, trig: 1)
irb> hcsr04.distance_cm
=> 23.4

gem は内部で次のような複雑なタイミング処理をすべて行っています。

  1. Trig ピンへ短いトリガパルスを送ります
  2. Echo ピンが high になっている時間を測ります
  3. distance = (duration × sound_speed) / 2 を使って距離を計算します

実装はこちらで確認できます: https://github.com/picoruby/picoruby/blob/master/mrbgems/picoruby-hcsr04/mrblib/hcsr04.rb

LED 付き距離モニタ

これを distance_monitor.rb として保存してください。

require 'pwm'
require 'hcsr04'

hcsr04 = HCSR04.new(echo: 0, trig: 1)
buzzer = PWM.new(11)
buzzer.duty 50
buzzer.frequency 0

puts "Distance Monitor Started!"
puts "Buzzer will sound when an object is detected within range."

while true
  begin
    distance = hcsr04.distance_cm
    puts "Distance: #{distance} cm"
    # closer = faster blink
    buzzer.frequency((5000 - (distance * 10)) / 10)
  rescue
    puts "Distance: Out of range"
    buzzer.frequency 0
    sleep 1
  end
  sleep 0.5
end

SSD1306 OLED ディスプレイ

SSD1306 は、I2C 通信を使う一般的な OLED ディスプレイです。この gem は、複雑な I2C プロトコルの詳細を内部で扱います。

必要な部品:

  • 1x SSD1306 OLED Display(128x64 pixels)
  • ジャンパーワイヤ

配線:

RP2[3V3] --- OLED[VCC]
RP2[GND] --- OLED[GND]
RP2[GP8] --- OLED[SDA]
RP2[GP9] --- OLED[SCL]

基本の表示セットアップ

irb> require 'ssd1306'
irb> width = 128
irb> height = 64
irb> i2c = I2C.new(unit: :RP2040_I2C0, sda_pin: 8, scl_pin: 9)
irb> display = SSD1306.new(i2c: i2c, w: width, h: height)

図形を描く

# Clear the display
irb> display.clear

# Draw lines (Display does not auto-update at this point)
irb> display.draw_line(0, 0, width-1, height-1, 1)
irb> display.draw_line(width-1, 0, 0, height-1, 1)

# Update display to show changes
irb> display.update_display

形を描く

# Clear and draw rectangles
irb> display.clear
irb> display.draw_rect(10, 10, 30, 20, 1, false)  # Outline rectangle
irb> display.draw_rect(50, 20, 25, 15, 1, true)   # Filled rectangle
irb> display.update_display

テキストを表示する

# Clear and show text
irb> display.clear
irb> display.draw_text(:terminus_6x12, 0, 24, "Hello PicoRuby!")
irb> display.draw_text(:terminus_6x12, 0, 40, "Workshop 2025")
irb> display.update_display

完全な OLED デモ

これを oled_demo.rb として保存してください。

require 'ssd1306'

width = 128
height = 64
i2c = I2C.new(unit: :RP2040_I2C0, sda_pin: 8, scl_pin: 9, frequency: 400_000)
display = SSD1306.new(i2c: i2c, w: width, h: height)

puts "OLED Demo Started!"

# Demo 1: Text welcome
display.clear
display.draw_text(:terminus_6x12, 0, 0, "EuRuKo 2025")
display.draw_text(:terminus_16x32, 0, 16, "PicoRuby")
display.draw_text(:terminus_8x16, 0, 48, "Workshop Demo")
display.update_display
sleep 3

# Demo 2: Geometric patterns
display.clear
display.draw_line(0, 0, width-1, height-1, 1)
display.draw_line(width-1, 0, 0, height-1, 1)
display.draw_line(width/2, 0, width/2, height-1, 1)
display.draw_line(0, height/2, width-1, height/2, 1)
display.update_display
sleep 3

# Demo 3: Rectangles
display.clear
display.draw_rect(10, 10, 30, 20, 1, false)
display.draw_rect(50, 20, 25, 15, 1, true)
display.draw_rect(85, 35, 35, 25, 1, false)
display.update_display
sleep 3

# Demo 4: Animation - moving dot
display.clear
display.draw_text(:terminus_12x24, 0, 0, "Moving Dot!")
x = 0
y = 16
10.times do
  display.draw_rect(x, y, 4, 4, 1, true)
  display.update_display_optimized # only update changed pages
  display.erase(x, y, 4, 4)
  sleep 0.3
  x += 12
  y += 4
end

puts "Demo complete!"

完全な API 一覧はこちらで確認できます: https://github.com/picoruby/picoruby/blob/master/mrbgems/picoruby-ssd1306/sig/ssd1306.rbs

演習

次の発展課題に挑戦してください。

  1. OLED 音ビジュアライザ: マイクのレベルを OLED にリアルタイム表示してください。

    # Show sound level as a bar graph
    # Include peak hold indicator
  2. 対話型距離ゲーム: OLED ディスプレイを使ってゲームを作ってください。

    • 目標距離を表示(例:"Get 25cm away!")
    • 現在距離と "warmer/colder" のフィードバックを表示
    • 目標に到達するまでの速さでスコアを付ける
    • 目標を変えながら複数ラウンド
  3. OLED アニメーションエンジン: 簡単なアニメーションシステムを作ってください。

    # Bouncing ball physics
    # Multiple moving objects
    # Collision detection with distance sensor
    # Sound effects synchronized with animations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment