この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
テントの中から失礼します、CX事業本部のてんとタカハシです!
前回の記事(Rust & Raspberry Pi で温度センサーの値を AWS IoT Core に Pub してみた)を書く際に、Rust を使ってLチカを試したのですが、何だか色んな言語で Raspberry Pi を操作したい欲求に駆られてしまい、こんな素敵な記事を書いてみました。
Raspberry Pi を使った電子工作では、セットアップ不要 かつ ドキュメント豊富な Python がよく使われると思いますが、Python の経験が無い方にとっては、少々ハードルを感じてしまうかもしれません。しかし、この記事を見ればもう大丈夫。だって10個の言語でLチカを試したんだから。読者の方々が触れたことある言語、きっと1つはあるはず。皆様、是非是非安心して、電子工作の第一歩、Lチカを試して楽しんで頂ければなと思います。
各言語のプログラムは下記に置いてありますので、Lチカを試す際はリポジトリをローカルに落として、これから記載する手順に従って実行してみてください。
GitHub - iam326/l-tika-10-languages
今回Lチカで使用する言語の一覧
- Python
- Node.js
- C言語
- Golang
- Rust
- Shell Script
- Java
- PHP
- Ruby
- Perl
Raspberry Pi の環境
Raspberry Pi OS のバージョンは下記の通りです。
$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 10 (buster)
Release: 10
Codename: buster
Raspberry Pi 自体のモデルは、「Raspberry Pi 2 Model B」を使用して記事を書いていますが、今回使用する Pin の配置は、Raspberry Pi 3 or 4 系 と同じになります。
配線
下記の通りの配線してください。
プログラムの流れ
全ての言語共通でプログラムの流れは下記の通りになります。
- LED と接続している GPIO23(物理ピン番号16)を出力モードに設定する
- 無限ループで1秒おきに LED の ON/OFF を切り替えて、チカチカさせる
- Ctrl + C で無限ループを抜ける
- プログラムを終了する
また、プログラムが終了した後も LED が ON になり続ける状態を回避するため、必要に応じて後処理を行います。言語(というより使用するライブラリ)によっては、プログラムの終了と同時に LED を自動 OFF してくれるものもあります。
実装見ていくぞー
Python
定番の Python からやっていきます。こちらはセットアップ不要で動いちゃいます。
import RPi.GPIO as GPIO
from time import sleep
LED_PIN = 23
GPIO.setmode(GPIO.BCM)
GPIO.setup(LED_PIN, GPIO.OUT)
try:
while True:
GPIO.output(LED_PIN, GPIO.HIGH)
sleep(1.0)
GPIO.output(LED_PIN, GPIO.LOW)
sleep(1.0)
except KeyboardInterrupt:
GPIO.cleanup()
下記の手順でプログラムを実行します。
$ cd python/
$ python3 main.py
使用しているライブラリのドキュメントはこちら。SourceForge - raspberry-gpio-python
Raspberry Pi の公式ドキュメントでは、GPIO Zero
というライブラリを使ったLチカのプログラムが紹介されています。 raspberrypi.org - GPIO in Python
GPIO Zero
知らなかった、今度使って遊んでみようと思います。
Node.js
次は Node.js でやっていきます。Node.js で Raspberry Pi を操作している記事もよく見かける気がしています。
const Gpio = require('onoff').Gpio;
const LED_PIN = new Gpio(23, 'out');
process.on('SIGINT', () => {
LED_PIN.unexport();
process.exit();
});
setInterval(() => {
LED_PIN.writeSync(LED_PIN.readSync() === 0 ? 1 : 0);
}, 1000);
npm trends を見て、一番人気がありそうな onoff というライブラリを使用しました。
下記の手順でセットアップ & プログラムを実行します。
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
$ sudo apt-get install -y nodejs
$ node --version
v14.6.0
$ npm --version
6.14.6
$ cd nodejs/
$ npm install
$ node main.js
C言語
組み込みといえばC言語。こちらはセットアップ不要で動いちゃいます。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>
#define LED_PIN 4
int end = 0;
void abort_handler(int signal);
int main(void) {
wiringPiSetup();
pinMode(LED_PIN, OUTPUT);
if (signal(SIGINT, abort_handler) == SIG_ERR) {
exit(1);
}
while (!end) {
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
delay(1000);
}
return 0;
}
void abort_handler(int signal) {
end = 1;
}
WiringPi というライブラリを使用しています。
下記の手順でプログラムを実行します。
$ cd c/
$ gcc -Wall -o main main.c -lwiringPi
$ ./main
Golang
C言語と構文が似てる感じの Golang。
package main
import (
"time"
"gobot.io/x/gobot"
"gobot.io/x/gobot/drivers/gpio"
"gobot.io/x/gobot/platforms/raspi"
)
func main() {
r := raspi.NewAdaptor()
led := gpio.NewLedDriver(r, "16")
work := func() {
gobot.Every(1 * time.Second, func() {
led.Toggle()
})
}
robot := gobot.NewRobot("ltika",
[]gobot.Connection{r},
[]gobot.Device{led},
work,
)
robot.Start()
}
GoBot というロボティックス・IoT向けのフレームワークを使用しています。ドキュメントに書いてあるプログラムそのままで動作しました。ちょっとこのGoBot
面白そうなので、何かの機会で試してみたいなという気持ちになっています。
下記の手順でセットアップ & プログラムを実行します。
$ wget https://golang.org/dl/go1.14.6.linux-armv6l.tar.gz
$ sudo tar -C /usr/local -xzf go1.14.6.linux-armv6l.tar.gz
$ echo export 'PATH=$PATH:/usr/local/go/bin' >> ~/.profile
$ source ~/.profile
$ go version
go version go1.14.6 linux/arm
$ cd golang/
$ go build main.go
$ ./main
Rust
この記事を書くきっかけとなった Rust。
use std::error::Error;
use std::thread;
use std::time::Duration;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use ctrlc;
use rppal::gpio::Gpio;
const GPIO_LED: u8 = 23;
fn main() -> Result<(), Box<dyn Error>> {
let mut pin = Gpio::new()?.get(GPIO_LED)?.into_output();
pin.set_reset_on_drop(true);
let running = Arc::new(AtomicBool::new(true));
let r = running.clone();
ctrlc::set_handler(move || {
r.store(false, Ordering::SeqCst);
}).expect("Error setting Ctrl-C handler");
while running.load(Ordering::SeqCst) {
pin.set_high();
thread::sleep(Duration::from_millis(1000));
pin.set_low();
thread::sleep(Duration::from_millis(1000));
}
Ok(())
}
rppal というクレートを使用しています。
下記の手順でセットアップ & プログラムを実行します。
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source ~/.profile
$ cargo --version
cargo 1.45.0 (744bd1fbb 2020-06-15)
$ cd rust/ltika/
$ cargo run
Ctrl + C らへんの処理はドキュメントのまま書いて動いたのですが、何やってるかはよく分かりませんでした。勉強不足です勉強します。
Shell Script
Shell Script で手軽に Raspberry Pi を制御したいっていうケースはよくありそう。こちらはセットアップ不要で動いちゃいます。
#!/bin/bash
set -euo pipefail
LED_PIN=23
gpio export $LED_PIN out
trap 'gpio unexport $LED_PIN' SIGINT
while true
do
gpio -g write $LED_PIN 1
sleep 1
gpio -g write $LED_PIN 0
sleep 1
done
これも WiringPi を使用しています。gpio
コマンドを使って制御していますね。
下記の手順でプログラムを実行します。
$ cd sh/
$ ./main.sh
Java
調べてみたのですが、Java って組み込みでもよく使われるんですね。
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
public class Ltika {
public static void main(String[] args) throws InterruptedException {
final GpioController gpio = GpioFactory.getInstance();
final GpioPinDigitalOutput pin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_04, "LED", PinState.LOW);
pin.setShutdownOptions(true, PinState.LOW);
Runtime.getRuntime().addShutdownHook(new Thread(
() -> gpio.shutdown()
));
while (true) {
pin.toggle();
Thread.sleep(1000);
}
}
}
Pi4J というライブラリを使用しています。
下記の手順でセットアップ & プログラムを実行します。
$ sudo apt install default-jdk
$ java --version
openjdk 11.0.7 2020-04-14
OpenJDK Runtime Environment (build 11.0.7+10-post-Raspbian-3deb10u1)
OpenJDK Server VM (build 11.0.7+10-post-Raspbian-3deb10u1, mixed mode)
$ curl -sSL https://pi4j.com/install | sudo bash
$ cd java/
$ javac -classpath .:classes:/opt/pi4j/lib/'*' -d . Ltika.java
$ java -classpath .:classes:/opt/pi4j/lib/'*' Ltika
PHP
PHP でも Raspberry Pi 操作できるよってのは、電子工作のハードルをかなり下げてくれそうなお話。
<?php
require_once "vendor/autoload.php";
use PiPHP\GPIO\GPIO;
use PiPHP\GPIO\Pin\PinInterface;
declare(ticks = 1);
pcntl_signal(SIGINT, "signal_handler");
$end = false;
$gpio = new GPIO();
$led_pin = $gpio->getOutputPin(23);
while (!$end) {
$led_pin->setValue(PinInterface::VALUE_HIGH);
sleep(1);
$led_pin->setValue(PinInterface::VALUE_LOW);
sleep(1);
}
$led_pin->unexport();
function signal_handler($signal) {
global $end;
switch($signal) {
case SIGINT:
$end = true;
break;
default:
break;
}
}
?>
PiPHP/GPIO というライブラリを使用しています。
下記の手順でセットアップ & プログラムを実行します。
$ sudo apt-get install php
$ php --version
PHP 7.3.19-1~deb10u1 (cli) (built: Jul 5 2020 06:46:45) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.19, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.3.19-1~deb10u1, Copyright (c) 1999-2018, by Zend Technologies
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer
$ composer --version
Composer version 1.10.9 2020-07-16 12:57:00
$ cd php/
$ composer install
$ sudo php main.php
PHP でLチカのやりかたを検索すると、Webページから LED の ON/OFF を制御するみたいな記事が結構出てきます。かなり面白そうなので、これもその内試してみたいなと思いました。
Ruby
Ruby でもやっていきますー。
require 'bundler/setup'
require 'pi_piper'
led_pin = PiPiper::Pin.new :pin => 23, :direction => :out
begin
loop do
led_pin.on
sleep 1
led_pin.off
sleep 1
end
rescue Interrupt
PiPiper::Platform.driver.unexport_pin(23)
end
pi_piper というライブラリを使用しています。
下記の手順でセットアップ & プログラムを実行します。
$ sudo apt-get install ruby
$ ruby --version
ruby 2.5.5p157 (2019-03-15 revision 67260) [arm-linux-gnueabihf]
$ sudo apt-get install ruby2.5-dev libssl-dev
$ sudo gem install bundler
$ gem --version
2.7.6.2
$ bundler -v
Bundler version 2.1.4
$ cd ruby/
$ bundle install
$ sudo ruby main.rb
Perl
Perl は人生で初めて触りました。cpan
の使い方がよく分からず結構ハマりました。
#! /usr/bin/perl
use strict;
use warnings;
use RPi::WiringPi;
use RPi::Const qw(:all);
my $end = 0;
my $pi = RPi::WiringPi->new;
my $led_pin = $pi->pin(23);
$led_pin->mode(OUTPUT);
sub sigint_handler {
$end = 1;
}
$SIG{'INT'} = 'sigint_handler';
while (!$end) {
$led_pin->write(OFF);
sleep(1);
$led_pin->write(ON);
sleep(1);
}
$pi->cleanup();
これまた WiringPi ですね。
下記の手順でセットアップ & プログラムを実行します。
$ cpan
cpan[1]> install RPi::WiringPi
cpan[2]> install RPi::Const
cpan[3]> exit
$ cd perl/
$ perl main.pl
おわりに
今回は、Raspberry Pi & 10個の言語を使ってLチカを試してみましたが、いかがだったでしょうか。個人的には色々なバリエーションを経験することができて、とても楽しかったです。需要があるのか分かりませんが、他の言語を使った第二弾もやりてえなああ〜とか思ったりしています(触ったことないけど Elixir
とか?)。
前の記事でもご紹介しましたが、もっと Raspberry Pi を使った電子工作にチャレンジしてみたいと思った方には、ブルーバックス出版の Raspberry Piで学ぶ電子工作 作る、動かす、しくみがわかる! がオススメです。こちらの本では Python を使って、様々なセンサーを動かしながら、電子工作の基礎を学ぶことができますよ。
では、今回は以上になります。最後まで読んで頂きありがとうございました!