工作と競馬

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

カテゴリ:11.電子工作(IoT) > 11.1 Raspberry Pi

Raspberry piで、scipyをインストールしたとき、

sudo apt-get install scipy

だと、0.18.1がインストールされる。

しかし、バージョンが古いので、

sudo pip install scipy --upgrade

をやるが、途中で止まる???

と思ったが、単に時間がかかっているだけで、1.5時間後くらいに、以下の表示が出て終了した模様。

Successfully built scipy
Installing collected packages: scipy
  Found existing installation: scipy 0.18.1
    Uninstalling scipy-0.18.1:
      Successfully uninstalled scipy-0.18.1
Successfully installed scipy-1.1.0

念のため、バージョンを確認のため、

import scipy
scipy.__version__

をすると 、無事1.1がインストールされていた。

ちなみに、pandasについても同様で、

sudo pip install pandas --upgrade

で時間はかかるが、ちゃんとインストールされた。

概要

AWSのGreengrassを使い、遠隔でGPIOを操作しLEDの点滅ができた。


背景と目的

先日のGreengrass使い始めに続き、ドキュメントに沿っていろいろ試したところ、遠隔でエッジのLambda関数をトリガする方法もわかった。また、エッジのローカルリソース(ドライブや、シリアルポート、GPIOなど)にもアクセスできるとの記述がある。そこで、Raspberry PiのGPIOを遠隔で操作してみることにした。


詳細

0.参考資料

AWSドキュメント内の以下URLを参考にした。GPIOにアクセスできるとの旨が書いてある。

https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/access-local-resources.html


1.Lambda関数

Lambda関数は、基本的にRaspberry Pi上でGPIOをいじるときと同じコード。

# coding:utf-8
import sys
import greengrasssdk
import RPi.GPIO as GPIO
import time
import platform
import os
import logging

# Create a Greengrass Core SDK client.
client = greengrasssdk.client('iot-data')

# GPIOの設定
GPIO_NUM = 4
GPIO.cleanup()
GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_NUM, GPIO.OUT)

def function_handler(event, context):
    try:
        client.publish(topic='LRA/test', payload="Sent from AWS Greengrass Core.")
        GPIO.output(GPIO_NUM, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(GPIO_NUM, GPIO.LOW)
        time.sleep(1)
    except Exception as e:
        logging.error("Experiencing error :{}".format(e))
        client.publish(topic='LRA/test', payload="Experiencing error")
    return


2.リソースの設定

Greengrass>グループ>リソースで、/dev/gpionumというリソースに対して、Lambda関数がアクセスできるように設定した。

リソース


3.サブスクリプションの設定

以下2つを設定した。IoT Cloud側からLRA/test/triggerトピックに、送信することで、Lambdaが呼び出せる。

  • "LRA/test/trigger"トピックをIoT Cloud ⇒ Lambda関数で設定
  • "LRA/test"トピックをLambda関数 ⇒ IoTCloudで設定


4.テスト

以上の設定で、Greengrass CoreにLambdaをデプロイし、IoT Cloud側からLRA/test/triggerトピックにメッセージを送信した。ところ、GPIO4に接続したLEDが1秒間光り、"LRA/test"トピックに、Lambdaからのメッセージが来た。正しく、Lambdaが呼び出せている。


まとめ

AWSのGreengrassを使い、遠隔でGPIOを操作しLEDの点滅ができた。

概要

ここに、概要を2行くらいで書きます。


背景と目的

先日、Raspberry Piで、Webアクセスをするプログラムを動かしたところ、レスポンスが遅かったので、解決策を調べる。


詳細

1.症状

  • Pythonのurllib2を使ってプログラムを書いていたときに起こった
  • 試しにcurlでアクセスを試したところ、同様に遅い(約5秒)
  • pingも遅い(1発目のレスポンスが来るまで、2発目以降は1秒ごと)

という状況だった。

2.調査

そこで、Web上でいろいろ調べた結果わかったのは、

 ipv6のDNSに接続しに行ってタイムアウトし、ipv4のDNSに接続しなおしている

ということのようだった。

3.対策

こちらなどを見ると、curlの引数に、-4という、ipv4だけを使うようにするオプションがある。そこで、-4という引数を付けたところ、素早くレスポンスが帰ってきた。

というわけで、ipv6のDNSに接続しに行ってタイムアウトするのを防ぐためには、

 curlで-4という引数を付ける

でよい。

ただし、この対策は根本治癒ではないので、curlが使えない状況などがあるとまずい。(私の場合Pythonでプログラムを作ってきてしまっていたのでsubprocessで、curlを実行しレスポンスをもらうという方法でどうにか乗り切れた。)


まとめ

Webアクセスが妙に遅い場合、ipv6のDNSに接続しに行ってタイムアウトを疑ってみて、curlの-4オプションをつけて早くなればそれが原因と推定できる。

概要

ラズパイ上に立てたWebサーバ(Apache)に対して、クロスドメインアクセスできるように設定を行い、した。


背景と目的

ラズパイ上に立てたWebサーバに対して、クロスドメインアクセスする必要が出たので、実装してその方法をメモる。


詳細

0.条件

  1. ラズベリーパイ上にApache(バージョンApache/2.4.25 (Raspbian))をインストールして、Webサーバを稼働
  2. ラズパイ上のサーバには、テスト用として何らかのJSONを返すCGIスクリプトを配置
  3. ラズパイのWebサーバと異なるドメインを持つWebサーバ上に、HTMLファイルを配置
  4. 上記HTMLでは、jquery(ajax)にて、ラズパイのCGIスクリプトにアクセス→ここでクロスドメインアクセスが発生


1.apache2.confの設定

まず、headers.loadというモジュールを有効化。

sudo cp /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load

/etc/apache2/apache2.confの末尾に、以下を追記。


<Location /usr/lib/cgi-bin>   
      Header set Access-Control-Allow-Headers "Content-Type"
      Header set Access-Control-Allow-Origin "*"
</Location>


Apache2を再起動。

sudo service apache2 restart


2.テスト用サイト

以下のテスト用HTMLファイルを作成し、ラズパイのWebサーバとは異なるドメインを持つWebサーバなどに配置する。私の場合、AWSのS3に配置して公開。


<html>
<head>
    <meta charset="utf-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
    <p id="message"></p>
    <script>
        window.onload = function () {
            $.ajax({
                url: "http://{ラズパイのIPアドレス}/cgi-bin/test.cgi",
                type: "GET",
                success: successCallback,
                error: errorCallback
            });
            function successCallback(data, dataType) {
                $("#message").text(JSON.stringify(data));
            }
            function errorCallback(err) {
                window.alert(err);
            }
        }
    </script>
</body>
</html>



3.動作確認

2.で作成したHTMLのURLにブラウザでアクセスしたところ、以下のように表示され、正しく動作した。(CGIは、時刻をJSONで返すだけのスクリプトとしている)

{"datetime":"2018-06-23 17:27:54"}


まとめ

無事、クロスドメインアクセスすることができた。

ASUS Xtion2を入手したので、Raspberry Piにつないで動かそうとしたらだめだった。

いろいろ試したが、個人的な見解としては、

  • ASUSからRaspberry Pi向けのSDKが出るまで待つ

ことにした。

過去に、Raspberry PiでXtionを動かしている例はあるが、Xtion2は見つからない。

ASUSのLinux対応という書き方に多少騙された感じもするが、よく読むとUbuntuとも書いてあるので、何とも言えない。

見る人が見れば、何を無駄なことをしているのかと、思うかもしれない状況ではあるが、とりあえずここまででいったん止めよう。

試したこと

  • ASUSのSDKを使ってみたけど、64ビット用のドライバだから使えない?というようなエラーでだめだった。どうやら、Raspberry PiはARMのCPUを使っていて、Intel x64を使うLinux Ubuntu用しか提供されていないので、無理なようだ。
  • [[こちら>]]どうやら、libSenDuck.soというファイルがXtion2用のドライバ?これがASUSからRaspberry Pi向けに出ないと、どうやっても無理かな?
  • Depthセンサの出力をOpenCVなどで取り込んだが、縞模様の得体のしれない画像になってしまい、理解不能
  • こちらから、Debian用をビルドしたけどそもそもXtion2のドライバがないので意味がなさそう
  • 上のソースコードを読んで、縞模様の得体のしれない画像がDepth画像に変換できないか、見てみたけどちょっとすぐにはできなそう
  • その他いろいろ

どなたか、実は動くよという情報をお持ちであれば教えてください。。。

概要

ラズパイZeroWから、Google Homeを喋らせることができた。


背景と目的

以前、WindowsPCからGoogle Homeを喋らせた。今回は、手持ちのRaspberry Pi Zero Wを使ってしゃべらせることにした。


詳細

1.Node.jsとnpmのインストール

まず、nodejsとnpmのインストールは、こちらにしたがい、

sudo apt-get update
sudo apt-get install -y nodejs npm
sudo npm install npm n -g
sudo n stable

という感じ。以下で、バージョンの確認。バージョンはそれぞれ、v9.4.0と5.6.0となった。

node -v
npm -v


2.google-home-notifierのインストール

次に、こちらにしたがい、以下コマンドを実行。

sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
git clone https: //github.com/noelportugal/google-home-notifier
cd google-home-notifier
npm install

ここでインストール完了と思い、4のコードを実行したが、エラーが発生。こちらを参考に、以下を追加で実行。

sudo npm install --unsafe-perm mdns
sudo npm install --unsafe-perm homebridge


3.コーディング

以前と同じ以下のコードを作成。

var googlehome = require('google-home-notifier');
var language = 'ja';
 
// IPアドレスの設定
googlehome.device('Google Home', language).accent(language).ip('xxx.xxx.xxx.xxx');
 
// しゃべらせる
googlehome.notify('こんにちは', function(res) {
  console.log(res);
});


4.実行

上記をnodeで実行したところ、

ディロン!...こんにちは。

としゃべった。というわけで、しゃべりが相変わらずノロいが成功だ。

ただし、以下のような警告メッセージが出る。どうやったら、直せるのか現状ではわからない。このあたりをやれば解決するんだろうか。。。

*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>


まとめ

ラズパイZeroWから、Google Homeを喋らせることができた。Windowsの時もそうだったが、どうもインストールがすんなり行かない。いろいろ、試しながら上記の手順に落ち着いたが、今後もOSのバージョンが変わったりすると、うまくいかなくなりそうな気がする。

概要

Raspberry Piで、ESP-WROOM-32開発ボードとUSB経由でシリアル通信してみた。


背景と目的

Raspberry PiとESP-WROOM-32で通信する必要が出たので、USB経由でシリアル通信してみることにする。


詳細

1.pipのインストール

本筋とは関係ないが、たまたま手持ちのRaspberry Pi Zero Wはセットアップしたばかりで、pipが入っていなかったので、インストール。こちらを参考に、以下を実行。3番目は、バージョンの確認。

curl -kL https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
pip -V

2.python用シリアル通信モジュール

pipのインストールが完了したので、続いてPython用のシリアル通信制御モジュールpyserialをインストールした。

sudo pip install pyserial

上記実施後、Pythonで以下を実行したところ、エラーなくインポートできた。

import serial


3.ESP-WROOM-32を接続

ESP-WROOM-32開発ボードは、[[これ>]]を使用。USBで接続すればシリアル通信できるもの。Raspberry Piとの接続は、以下のようにUSBでつなぐだけ。白いケーブルが、ESP32とつながっている。(Raspberry Pi ZeroWは、microB端子しかないので、いったんA端子に変換している。)

DSC_0204

確認のため、

python -m serial.tools.list_ports

を実行し、

/dev/ttyAMA0
/dev/ttyUSB0
2 ports found

という感じで、ttyUSB0というシリアルポートが認識されていればOK。


4.シリアルで受信

以下をPythonにて実行し、1行を読み取ってみた。

import serial
s = serial.Serial()
s.port = '/dev/ttyUSB0'
s.baudrate = 115200 # これはESP32側の設定による
print s.readline()

無事、読み取ることができた。というわけで、シリアル通信ができた。


まとめ

Raspberry Piで、ESP-WROOM-32開発ボードとUSB経由でシリアル通信することができた。

概要

Raspberry Pi ZeroWを起動させてみた。


背景と目的

Raspberry Pi ZeroWを、2017年7月のMaker Fairで衝動買いしたくせに、全然動かしていなかったので、いい加減動かしてみる。


詳細

1.OSイメージの準備

RASPBIAN STRETCH LITEを使う。NOOBSだとキーボードやマウスを接続してセットアップしなければいけないが、今回はDesktopを使いそうもないので、OSイメージのみで十分。とりあえず、zipをダウンロード、解凍して、Win32DiskImagerでSDカードに書き込んだ。


2.SSHの有効化

SSHがデフォルトで無効になっているので、こちらあたりを参考に手順を進めた。


3.Wi-Fiの設定

こちらを参考に、wpa_supplicant.confを、SDカードに作成。


4.起動

起動して、LAN経由で無事SSHログインできた。Zero Wは非常にサイズが小さい!素晴らしい。


まとめ

無事、Raspberry Pi ZeroWを起動できた。

概要

NASをラズベリーパイからアクセスできるようにするためのメモ。


背景と目的

NAS内のファイルにラズベリーパイからアクセスしたいので、設定する。


詳細

0.情報収集

手順は、以下などを参考にした。


1.マウント先ディレクトリを作成

sudo mkdir /mnt/nas


2.マウントする

次に、マウント。私の環境の場合、192.168.xxx.yyy/disk。ラズパイのrootのパスワードを聞かれるので、入力。

sudo mount -t cifs //NASのIPアドレス/ディレクトリ /mnt/nas -o iocharset=utf8

成功すれば、以下でディレクトリが列挙できる。

ls /mnt/nas


3.起動時に自動的にマウントする設定

こちらによれば、/etc/fstabは自動マウントのための設定ファイルなので、これに書き込めばよい。

sudo nano /etc/fstab

以下を書き込む。

//NASのIPアドレス/ディレクトリ /mnt/nas cifs username=xxxxx,password=xxxxx,file_mode=0755,dir_mode=0755,iocharset=utf8,uid=1000,gid=1000,forceuid,forcegid,_netdev 0 0

さらに、起動時にネットワーク接続される前にマウントしようとしても意味がないので、ネットワーク接続が完了してから起動するように、Raspberry Piの設定をする。

sudo raspi-config

で、3 Boot Options>B2 Wait for Network at Bootと進み、

BlogPaint

というように、Enableにする。

ここで、再起動して再度lsコマンドでディレクトリが列挙されれば起動時に自動マウントされている。


まとめ

NAS内のファイルにラズベリーパイからアクセスできるようになった。

概要

gatttoolのインタラクティブモードにコマンドを流し込み(=パイプを利用)、任意のタイミングで終了させる方法を試し、動作を確認した。


背景と目的

以前、gatttoolのインタラクティブモードに無理やりコマンドを流し込み(=パイプを利用)、ノンインタラクティブのように動かしたが、sleepで決まった秒数経った後に終了することしかできていなかった。そこで、任意のタイミングで終了させられるようにする。


詳細

1.方法

以前作成したgattcommand.shというスクリプトを改造。test_gatt.shは変更なし。

  • まず、スイッチの役割をするファイルfile1を用意する。file1には、0か1が書き込まれるとする。
  • 次に、gattcommand.shでは、file1に1を書き込む
  • そして、file1の中身が1の間はwhileループでスリープをし続けるようにする。
  • whileループを抜け、Bluetoothの接続を切り、インタラクティブモードから抜けるexitを出力する

としておく。こうすることで、任意のタイミングでfile1に0を書き込めば、gatttoolを終了させられる。


2.実装

gattcommand.shを改造した結果は、以下の通り。


echo "1" >switch

sleep 1
echo connect

while [ `cat switch` = "1" ]
do
  sleep 1
done

echo disconnect
echo exit

3.動作確認

sudo bash test_gatt.sh &

でgatttoolのインタラクティブモードを起動。次に、任意のタイミングで、

echo "0" >file1

を実行。すると、インタラクティブモードが終了した。ということで、狙い通りの動きになった。

まとめ

gatttoolのインタラクティブモードにコマンドを流し込み(=パイプを利用)、任意のタイミングで終了させることができた。これを応用すれば、任意のタイミングで、任意のコマンドを流し込めそうだ。

このページのトップヘ