スマートホーム構築記

IoTの恩恵を受けたいけど家庭用はなかなか出てこない。なら作ろうというブログ

Rasberry Pi 3でirsendが使えなくなったことに対する対応 【続報】

はじめに

前回の記事でkernelアップグレードに対して/boot以下の設定を書き変えることで使用できるようにしたのですが、
部屋のライトは制御できて,エアコンが制御できない現象が発生しました。

Rasberry Pi 3でirsendが使えなくなったことに対する対応 - 家庭でIoTを実現しよう(Rasberry Pi3 & Jetson Nano)

今回はその対策です。
kernelを書き変えますので同じことをやって起動しなくなる可能性もありますので自己責任にてお願いいたします。
SDカードのバックアップを取ってから実行することをお勧めします。 手順は以下の通りです

  1. OSおよびカーネルを最新版にアップデート
  2. カーネルのソースを一部変更しインストール

環境

項目 内容
バイス Rasberry Pi 3 B+
OS rasbian stretch

今回すべてのコマンドはraspi上で行っています。

OSおよびカーネルのアップデート

既に最新になっている方は読み飛ばしてください。
現在のパッケージを最新版にする。

$ sudo apt update
$ sudo apt upgrade
$ sudo apt dist-upgrade

カーネルをstretchの最新版にアップデートする

$ sudo rpi-update

私のrasbianはstretchだったので最新版のbusterに更新します。
/etc/apt/sources.list と/etc/apt/sources.list.d以下のファイルのstretchをbusterに書き変えてください。
書き変え後以下のようにアップグレードします。途中失敗する場合もありますが,upgradeで失敗してもdist-upgradeを実行してください。
どうやらupgradeは一部パッケージの依存関係を解決できないみたいです。
dist-upgradeが成功すれば大丈夫です。

$ sudo apt update
$ sudo apt upgrade
$ sudo apt dist-upgrade
$ sudo apt autoremove

一度rebootします。

$ sudo reboot

リブートして以下のコマンドで10.以上の数値が出ればアップデートが正常にできています。

$ cat /etc/debian_version

カーネルのビルド。

公式のドキュメントを参考に実行します。環境に合わせて公式に記載の内容で読み替えてください。 一部ソースの書き換えが入ります。 www.raspberrypi.org

ビルドに必要なパッケージをインストールする。

$ sudo apt-get install git bc bison flex libssl-dev

カーネルのソースをダウンロードする

$ git clone --depth=1 https://github.com/raspberrypi/linux

ソースコードの修正

LIRCのコマンドのバッファーサイズを大きくします。 参考 [Stretch/Buster] Using LIRC with kernel 4.19.X and gpio-ir - Raspberry Pi Forums

@ linux/drivers/media/rc/lirc_dev.c
#define LIRCBUF_SIZE 256 > #define LIRCBUF_SIZE 1024

カーネルのビルド

Raspi3用のコンパイル設定を設定してコンパイルします。

$ cd linux
$ KERNEL=kernel7
$ make bcm2709_defconfig
$ make -j4 zImage modules dtbs

インストール

$sudo make modules_install
$sudo cp arch/arm/boot/dts/*.dtb /boot/
$sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
$sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
$sudo cp arch/arm/boot/zImage /boot/$KERNEL.img
$sudo reboot

おわりに

お疲れさまでした。以上でirsendでエアコンなどの長い信号も送信できるようになったと思います。
正直全部書き変える必要もないのではと思ったりしているのですが,とりあえず今回はこの方法でうまくいったので記事をまとめました。 一応公式にもこのバグは認識されているとは思うのでそのうち修正されるといいなとは思っていますがとりあえず今は自分で対応するしかありませんね。

Rasberry Pi 3でirsendが使えなくなったことに対する対応

はじめに

数か月放置していたraspi 3のアップデートを2019年の7月にアップデートしてからirsendが動かなくなったので,それに対して対応した方法の備忘録

環境

  • Rasberry Pi 3 Model B+
  • kernel version: 4.19.57-v7+
  • hardware.confと/boot/config.txtで設定していた

対応方法

hardware.confが不要になっているようなので読み込まれないようにリネームする。

$ sudo mv /etc/lirc/hardware.conf /etc/lirc/hardware.conf.dist

/boot/config.txtの記載方法が変わっているのでbeforeに記載している部分をafterで記載している部分へ書き換える。

before

dtoverlay=llirc-rpi
dtparam=gpio_in_pin=4
dtparam=gpio_out_pin=17

after

dtoverlay=gpio-ir,gpio_pin=4
dtoverlay=gpio-ir-tx,gpio_pin=17

Jetson Nanoでリモートデスクトップ(XRDP)を使う

はじめに

Jetson NanoでWindowsリモートデスクトップクライアントから簡単に接続できるXRDPを導入します。 最近のWindows 10の開発者向けの機能拡張が充実してきていて,WindowsLinuxデュアルブートの必要性とかほとんどなくなってきています。
Visual Studio CodeHyper-Vや WSL2を使ってほとんど事足りてしまいますし。

XRDPの導入

Jetson NanoのベースOSはUbuntu 18.04なので基本的にこちらのサイトに記載されている方法でできます。
手順は記載しておきます。またシェルスクリプトも公開しておきますのでお試しください。

インストール

$ sudo apt install -y xrdp

設定

カーソル周りが黒くならないようにする

$ sudo sed -e 's/^new_cursors=true/new_cursors=false/g' \
           -i /etc/xrdp/xrdp.ini
$ sudo systemctl restart xrdp

Ubuntu 18.04向けの設定をロードする

$ D=/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktop
$ cat <<EOF > ~/.xsessionrc
export GNOME_SHELL_SESSION_MODE=ubuntu
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
export XDG_DATA_DIRS=${D}
export XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
EOF

認証まわりで落ちるのを回避

$ cat <<EOF | \
  sudo tee /etc/polkit-1/localauthority/50-local.d/xrdp-color-manager.pkla
[Netowrkmanager]
Identity=unix-user:*
Action=org.freedesktop.color-manager.create-device
ResultAny=no
ResultInactive=no
ResultActive=yes
EOF
$ sudo systemctl restart polkit

シェルスクリプト

Githubにて公開中です。どうぞご利用ください。

Jetson NanoでWi-Fi(WN-G150UM)を使う

はじめに

Jetson NanoでWi-Fiを使う方法について記載します。
いろいろなサイトで検証されていますし,とりあえず私がやった内容とそれに関する元記事をまとめておきます。

環境

項目 内容
Jetson nano image jetson-nano-sd-r32.1.1-2019-05-31
Wifi Dongle(USB) I-O DATA WN-G150UMK

使用したのはRasberry Piでもよく使われるUSB Dongleタイプのものです。

接続の作法

落とし穴としては,USB接続直後に一瞬使えたとしても再起動すると認識すらしなくなるところです。
NVIDIAの公式フォーラム内のJetson nano wifiではドライバの問題とのことから 以下のコマンドを実行するように回答されています。

$ echo "blacklist rtl8192cu" | sudo tee -a /etc/modprobe.d/blacklist.conf

まとめ

Jetson Nanoを2.4GHz対のWi-Fiには接続できるようになります。これでLANケーブルが不要になるので次はディスプレイがいらなくなるようリモートデスクトップに対応させたいと思います。

久々に再開

はじめに

ここ数年,忙しくてブログの更新滞ってましたが再開したいと思います。

これまでとこれから

Rasberry Pi3を使ってエアコンの制御をやるシステムを作っていました。裏ではGoogle Homeと連携させたり,Webから制御する画面を作ったりしていました。
正直ちょっと手を広げすぎて書ききれなくなっていたのと、仕事の方が忙しかったので放置してました。
久々にJetson Nanoというおもちゃも手に入れたのでブログのタイトルを変更してJetson Nanoを扱った内容も取り扱っていきたいと思います。
引き続きよろしくお願いします。

エアコンIoTの今後の開発方針について

はじめに

Raspberry Pi3でエアコンの信号を出力してコントロールできるようになったので一度、今後の開発方針について整理したいと思います。
なので一度仕様を定義していきます。

仕様定義

要件定義

私が求めているものは以下の2つです。

  1. 家にいる間、快適な環境で過ごしたい
  2. 電気代は無駄に使いたくない
  3. 手間は少ないほうがうれしい
  4. 居住者のみ使用できるようにしたい

使用環境定義

  1. 使用できるデバイスはRaspberry Pi 3
  2. 居住者は2人
    • 出社時間はほぼ固定
    • 帰宅時間はばらばら
  3. raspiによってエアコンの機能は全ての機能を制御することができる
    • raspiで居室内の気温・湿度・大気圧を計測が可能
  4. 部屋の温度は外気温と日照量によって変化する

開発コンセプト定義

  • rev1 遠隔地から手動制御(要件1)
  • rev2 曜日、時間帯を登録して操作を定義し自動実行(要件3)
  • rev3 部屋内温度と外気温からON/OFFを制御機能を追加(要件2)
  • rev4 居住者の位置情報と時間帯からON/OFFの要否判定を自動化(要件1,2)

rev1の機能と実装方法

  1. 居住者が設定を編集する機能
    • Webサーバを用いたシステム(各種端末によって使用するため)
  2. 現在の室温と湿度を表示する機能(ユーザがON/OFFの判断をするため)
    • html5,jqueryで作成(勉強のため)
      • 一日のログをグラフ表示するとよいかも
  3. 設定からエアコンを制御する機能
    • 前回構築したシステムを使用する。
    • よってdjangoからは設定データをjsonで出力

rev1の画面イメージ

スマホから操作しやすいようなるべくシンプルにします。
f:id:kagemomiji:20161022114336p:plain:w640

まとめ

今回仕様を定義してrev1の実装方法について荒く検討しました。
おおよその方針が決まりましたのでこれから地道に開発を進めていこうと思います。

Raspberry Pi3 でlircを使ってエアコンに信号を送信する

目的

前回信号を生成することができたので、
今回はlircを使ってエアコンに生成した信号を送信することを目的とします。

方針

以下の2つのステップで進めていきます.

  1. raspberry pi3の設定
  2. 赤外線発光回路作成
  3. lircの設定生成と送信テスト
  4. 統合スクリプト作成

raspberry pi3の設定

最初に接続回路を接続するためにraspberry pi3の設定を変更します。
今回はGPIO17を使用して赤外線LEDを制御します。
なので違うGPIOピンを使用する場合は17を自分のピン番号に読みかえて設定してください。
まずGPIOピンの設定を出力/プルNoneに変更します.

$raspi-gpio set 17 op pn

次にlircを使用する上でGPIO17を出力ピンとして設定するため/boot/config.txtを以下のように編集します
前回に一度編集していますのでそちらを変更前がどのように変更されたかは前回記事を参照ください。

dtoverlay=lirc-rpi,gpio_in_pin=4 (変更前)
dtoverlay=lirc-rpi,gpio_in_pin=4,gpio_out_pin=17 (変更後)

変更が終了したら一度再起動します。
以上で赤外線発光回路を接続するための準備が完了しました。

赤外線発光回路作成

Raspberry Pi3で赤外線を発光するための回路を作成します。
使用する赤外線LEDはOSI5LA5113Aを使用します。
指向性が高いので直接対象に向ける必要があります強力で安価な赤外線LED素子ですので使用していきます。

回路は以下の図のようになります。
(以下の回路で駆動しますが素人が付け焼刃で作成したものなので専門家の方は自分で設計していただいた方がよいかと思います)
f:id:kagemomiji:20161015095821:plain:w320

以下が設計で加味した部分です。
1.点灯時には約50mA流れる設計
2.50mAはGPIOからは供給できないので5Vラインから点灯用の電源を供給
3.トランジスタ2SC1815
4.抵抗値はオーバードライブを加味した抵抗値
5.リーク電流対策にベースGND間に抵抗を追加

この回路図に従ってブレッドボードとRaspberry Pi3で以下のように配線します。
f:id:kagemomiji:20161015104714p:plain:w480
実際に配線した線は以下のようになります。
f:id:kagemomiji:20161015144054j:plain:w480

以上で赤外線発光回路の作成は完了です。

lircの信号生成と信号送信テスト

前回作成したlirc信号生成スクリプトファイルではlirc用に信号を生成するには若干の改造がpythonスクリプトjsonに必要なのでスクリプトを改造します。
方針としては

  1. lircのRAW_CODESフォーマットで記述する
  2. /etc/lirc/lircd.confをpythonスクリプトから直接編集する
  3. 設定を反映する

RAW_CODESフォーマットで記述する

lircのRAW_CODESフォーマットは以下のようになります.

begin remote
 name 機器名(英字)
 flags RAW_CODES
 eps 30
 aeps 100
 gap 200000
  begin raw_codes
    name 信号名
    (pulse) (space) (pulse) (space)・・・・(繰り返し)
  end raw_codes
end remote 

begin remote~end remoteで一つの機器を設定する定義部となります。
各設定については以下の公式helpページを参照ください.
LIRC - Linux Infrared Remote Control

その中で
begin raw_codes~end raw_codes
が信号一つ一つの定義部となります。
raw_codes形式ではmode2で取得したpulseとspaceの数値を順番に並べていくことで信号を定義することができます。
また1行で全て定義すると読み込みができなくなるとのことなので、10個毎程度で改行をします。

ではスクリプトjsonを改造していきます。
まず、以下のような3部品に分割して考えます

部品 内容
header begin remote ~ name 信号名
body 信号の数値烈|
footer end raw_codes~end remote

このうちheader と footerは機器毎に固定となるのでjsonに以下のように追記して定義します

"signal":{
                #追記 "header":"begin remote \n name aircon \n flags RAW_CODES \n eps 30 \n aeps 100 \n gap 200000 \n  begin raw_codes \n   name json", 
                #追記 "footer":"  end raw_codes \nend remote",
"T":436,
                "trailer_t":10000,

このように編集したjsonを読みこんで先ほどのRAW_CODESフォーマットのテキストを出力するようにpythonスクリプトを改造します.

まずheaderとfooterを読みこむ部分を追記します.

##################################
#convert setting to binary signal
##################################

#initialize
signal = format["signal"]
rule = signal["rule"]
format_type = format["type"]
header = signal["header"] #追記
footer = signal["footer"] #追記

次に

pulse 436
space 436

のように出力されていた信号生成部を改造します。

###################################
#convert binary signal to ir_signal
###################################

#initialize
T = signal["T"]
ir_signal = ''

#AEHA format setting
if format_type == 'AEHA':
        trailer_t = signal["trailer_t"]

        for i in xrange(len(bin_signal)):
                #append 0 #pulse space 改行を削除
                if bin_signal[i] == '0':
                        ir_signal = ir_signal + str(T) + ' ' + str(T) + ' '
                #append 1  #pulse space 改行を削除
                elif bin_signal[i] == '1':
                        ir_signal = ir_signal  + str(T) + ' ' + str(3*T)+ ' '
                #append Leader #pulse space 改行を削除
                elif bin_signal[i] == 'L':
                        ir_signal = ir_signal +  str(8*T) + ' ' + str(4*T)+ ' '
                #append Trailer  #pulse space 改行を削除 またspaceのパルス長は最終出力には不要なので削除
                elif bin_signal[i] == 'T' :
                        if  i < len(bin_signal)-1:
                                ir_signal = ir_signal + str(T) + ' ' + str(trailer_t) + ' '
                        else:
                                ir_signal = ir_signal + str(T)
                #append \n for lircd.conf #10個毎に改行(2個セットになるので%5)
                if i % 5 == 0:
                        ir_signal = ir_signal + '\n'

最後に

print header
print ir_signal
print footer

とするとRAW_CODESフォーマットの信号が標準出力に出力されます。

/etc/lirc/lircd.confに直接記述する。

RAW_CODESフォーマットで出力された文字列を/etc/lirc/lircd.confに記述します。

##################################
#initialize
##################################
#check argvs
argvs = sys.argv
argc = len(argvs)
if(argc !=2):
        print 'Usage: #python %s filename' % argvs[0]
        quit()

#set local value
SIGNAL_LIB_DIR = "../../settings/format/"
LIRCD_CONF = "/etc/lirc/lircd.conf" #追記

lircd.confへのパスを定義します.

#################################
#open lircd.conf
#################################
try:
        lf = open(LIRCD_CONF,'w')
except IOError:
        print 'usage: sudo python %s filename' % argvs[0]
        quit()

これをload format等の下に追記。
lircd.confはrootでしか編集ができないのでsudoを使って実行するようにします。

##################################
#write /etc/lirc/lircd.conf #追記
##################################
lf.write(header + '\n')
lf.write(ir_signal + '\n')
lf.write(footer)

##################################
# finish
##################################
s.close()
f.close()
lf.close() #追記

header,ir_signal,footerの順にlircd.confに書き込み、終了処理を追記して完了です。

設定を反映

/etc/lirc/lircd.confを編集しても設定は反映されません。
lircdを再起動する必要があります。

$ sudo /etc/init.d/lirc restart

を実行してもうまく設定が反映されません。
なので

$ sudo /etc/init.d/lirc stop
$ sudo /etc/int.d/lirc start

を順番に実行する必要があります。

次に設定が反映されているかを確認します

$irsend LIST "" ""

設定が反映されていれば

irsend: aircon

のように設定されたremoteのnameが表示されます。
以上で設定の反映は終了です。

以下のコマンド入力すると信号が読みこまれて信号が送信されます。

$ irsend SEND_ONCE 機器名 信号名

統合スクリプトの作成

信号生成から信号送信までの一連の操作を一つのコマンドで実行できるスクリプトを作成します。

#!/bin/sh
SCRIPT_DIR='スクリプトのパス’
sudo python $SCRIPT_DIR/json2signal.py $1
sudo service lirc stop
sudo service lirc start
irsend SEND_ONCE aircon json

まとめ

今回赤外線発光回路を作成し、信号生成スクリプトを改造し、lircからエアコンへ信号を送信することができました。
今回作成したスクリプト
github.com
に公開していますのでご自由に編集等して利用してください。