#1.はじめに
工場などで使われる産業機器を、GROVEコネクタに接続して、制御できるようにしてみました。
昨年のアドベントカレンダーにも同様の記事を投稿していましたが、Grove対応版が結局間に合わず、1年経ってしまいました・・・今回改めて作り直しましたので、紹介します。
#2.ハードウェア
SeeedさんのGroveシリーズには、接続インターフェースのラインナップがありませんので、自作してみました。
外観はこんな感じです。(左:出力用、右:入力用)
Grove Base HAT経由でRaspberryPiに接続します。
##(1)考え方
GROVEの制御電圧はDC3.3VあるいはDC5Vです。
一方、産業機器の多くはDC24Vで動作しますので、GROVEコネクタとは直結できません。
「電圧レベルの変換」と呼ばれる工夫が必要です。
今回のユニットでは、フォトカプラを使っています。
TLP627やTLP222は、定格電流が100mA以上流せるので、ランプやリレーは直結して駆動ができます。
NOTE
リレーなどコイルを使用しているものをトランジスタ・FETなどに接続する際は、コイルOFF時の逆起電力による破損防止のため「還流ダイオード」1の接続が必要です。
市販のリレーには、始めからダイオードが内蔵されているものもありますので、購入する際に予め型式を指定しておきましょう。
例)
##(2)基板を作ってみる
KiCADを使って基板を設計してみました。
ガーバデータや回路図含め、データ一式はGitHubに公開しています。
READMEで紹介しているとおり、基板裏面のジャンパーを切り替えることで、シンク(NPN)/ソース(PNP)駆動を切り替えることができますので、国内外問わず使用可能です。
基板の製造については、一例としてSeeedさんが運営の「Fusion PCB」での発注の例を、下記にまとめていますのでご参考ください。
#3.ソフトウェア
Pythonは多くの例があるので、ここでは敢えてそれ以外の言語で操作してみました。
言語 | 制御ライブラリ |
---|---|
Go | GOBOT |
Rust | rppal |
Elixir | Elixir Circuits |
##配線の接続
下記の様に繋いでいます。
HATのコネクタ | GPIO(BCM番号) | 接続先 |
---|---|---|
D5 | 5 | 押しボタン |
D16 | 16 | ランプ |
##(1)Golang
入出力制御のライブラリ gobotを使います。
インストールは上記リンク先の「How to Install」か、別記事で紹介しているものを参考願います。
ソースコード
押しボタンを押すと、ランプが点灯します。
ピン番号指定の注意!!
gobotでの入出力ピン番号指定は**物理ピン番号(Physical)**です。
BCM番号ではありませんのでご注意ください。
package main
import (
"fmt"
"gobot.io/x/gobot"
"gobot.io/x/gobot/drivers/gpio"
"gobot.io/x/gobot/platforms/raspi"
)
// GPIOを物理ピン番号で指定
const GPIO_LED = "36" //BCM16→Pin36
const GPIO_BTN = "29" //BCM5 →Pin29
func main() {
r := raspi.NewAdaptor()
//定義
led := gpio.NewLedDriver(r, GPIO_LED)
button := gpio.NewButtonDriver(r, GPIO_BTN)
//イベントを定義
work := func() {
//ボタンがONの時
button.On(gpio.ButtonPush, func(data interface{}) {
fmt.Println("button pressed")
//点灯
led.On()
})
//ボタンがOFFの時
button.On(gpio.ButtonRelease, func(data interface{}) {
fmt.Println("button released")
//消灯
led.Off()
})
}
//スタート
robot := gobot.NewRobot("buttonBot",
[]gobot.Connection{r},
[]gobot.Device{button, led},
work,
)
robot.Start()
}
実行
$ go run led.go
2020/12/20 11:02:18 Initializing connections...
2020/12/20 11:02:18 Initializing connection RaspberryPi-2B0CDE57 ...
2020/12/20 11:02:18 Initializing devices...
2020/12/20 11:02:18 Initializing device Button-649D051A ...
2020/12/20 11:02:18 Initializing device LED-7FCF738D ...
2020/12/20 11:02:18 Robot buttonBot initialized.
2020/12/20 11:02:18 Starting Robot buttonBot ...
2020/12/20 11:02:18 Starting connections...
2020/12/20 11:02:18 Starting connection RaspberryPi-2B0CDE57...
2020/12/20 11:02:18 Starting devices...
2020/12/20 11:02:18 Starting device Button-649D051A on pin 29...
2020/12/20 11:02:18 Starting device LED-7FCF738D on pin 36...
2020/12/20 11:02:18 Starting work...
button pressed
button released
button pressed
button released
button pressed
button released
[Ctrl-C]で終了
##(2)Rust
RaspberryPiの入出力制御のクレート rppalを使います。
ソースコード
はじめはランプが0.5sec間隔で点滅している状態になっていて、押しボタンを押すと、ランプの点滅速度が速くなります。
・・・(省略)
[dependencies]
rppal = "0.11.3"
use std::error::Error;
use std::thread;
use std::time::Duration;
use rppal::gpio::Gpio;
// GPIOをBCM番号で指定
const GPIO_LED: u8 = 16;
const GPIO_BTN: u8 = 5;
//メイン
fn main() -> Result<(), Box<dyn Error>> {
// GPIOの設定・出力
let mut pin_led = Gpio::new()?.get(GPIO_LED)?.into_output();
// GPIOの設定・入力
let pin_btn = Gpio::new()?.get(GPIO_BTN)?.into_input();
//無限ループ
loop {
if pin_btn.is_low() {
//ボタンを離しているときは0.5sec間隔で点滅
pin_led.toggle();
thread::sleep(Duration::from_millis(500));
} else {
//ボタンを押しているときは0.1sec間隔で点滅
pin_led.toggle();
thread::sleep(Duration::from_millis(100));
}
}
}
実行
$ cargo run
Compiling led v0.1.0 (/home/pi/gitwork/rust/led)
Finished dev [unoptimized + debuginfo] target(s) in 1.41s
Running `target/debug/led`
[Ctrl-C]で終了
##(3)Elixir
入出力制御のライブラリ Elixir Circuitsを使います。
ソースコード
押しボタンを押すと、ランプが1秒だけ点灯してから消灯します。
defmodule ButtonLamp do
@moduledoc """
Documentation for `Button`.
WebAPI送信とボタン・LEDの連携
## Examples
"""
# 関連するライブラリを読み込み
use GenServer
require Logger
alias Circuits.GPIO
# 定数
# 押しボタン接続のBCM番号
@button 5
# ランプ接続のBCM番号
@led 16
@doc """
GenServer起動
"""
def start_link() do
GenServer.start_link(__MODULE__, [])
end
@doc """
初期化の処理
"""
def init(_) do
# GPIO入力の初期化(押しボタン用)
{:ok, button} = GPIO.open(@button, :input, pull_mode: :pullup)
# 押しボタン入力の割込を許可(押しボタンを押すとhandle_info関数を呼び出し)
GPIO.set_interrupts(button, :rising)
# GPIO出力の初期化(ランプ用)
{:ok, led} = GPIO.open(@led, :output)
{:ok, %{button: button, led: led}}
end
@doc """
押しボタン入力の割込の処理
"""
def handle_info({:circuits_gpio, @button, _timestamp, value}, state) do
IO.puts(" Button On")
# ランプを点灯
GPIO.write(state.led, 1)
# 待機(単位ms)
Process.sleep(1000)
# ランプを消灯
GPIO.write(state.led, 0)
{:noreply, state}
end
end
mix.exsには、circuits_gpio
を追記します。
・・・(省略)・・・
defp deps do
[
{:dep_from_hexpm, "~> 0.3.0"}, #ここのコメントを外す
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
{:circuits_gpio, "~> 0.4"} #ここを追加
]
end
・・・(省略)・・・
実行
$ mix deps.get
$ iex -S mix
・・・
iex(1)> ButtonLamp.start_link
{:ok, #PID<0.289.0>}
Button On
Button On
・・・
[Ctrl-C]二回押し、あるいは[Ctrl-]で終了。
#4.おわりに
Grove Base HAT経由でRaspberryPiに接続が可能な、産業機器用制御インターフェースを作ってみました。
PLCに取って代わる・・・まではいかないにしても、IT系の方々が気軽にFACTORY系の機器を作れるようになることを願って製作しました。
今後、少しずつ作例を増やしていきますので、お待ちくださいね~