Raspberry Pi 3 B+ を NOOBS 1.92からセットアップ直後からスタートする。
利用するGPS製品ははこれ
GPS受信機キット 1PPS出力付き 「みちびき」対応: センサ一般 秋月電子通商 電子部品 ネット通販
Vcc
GND
Txd
Rxd
と 1pps出力の5線あるうち1pps出力以外の4線を利用する。
Vcc に 5V、TxdとRxdは3.3VでOK
製品購入状態では、UART(シリアル)9600bpsでNMEA 0183 フォーマットの測地情報
を吐き出すので、Raspberry Pi側でNMEAフォーマットを解析する gpsd
を利用して位置情報
を取得する。
NOOBS 1.92でセットアップした直後のRaspbian Jessieでは、GUIブートしますので、GUI画面で[Ctrl]+[Alt]+T (若しくは画面の上部にある黒い画面のコンピュータアイコンをダブルクリック)で、 LXTerminal
を起動します。その中で、設定を入力していきます。
(GUIが起動したら、Ctrl-Alt-F1でtty1に降りてもOK)
RaspberryPi: raspi-config コマンドラインから設定(ノンイタラクティブ) - Qiitaより
pi@raspberrypi:~ $ sudo raspi-config nonint do_wifi_country JP
pi@raspberrypi:~ $ sudo wpa_cli wps_pbc
Selected interface 'wlan0'
OK
pi@raspberrypi:~ $
以降、他マシン( mDNS環境・Bonjour
or Avahi
導入済みの環境)から ssh [email protected]
でログインして設定する。(パスワードは raspberry
)
mDNS環境じゃない場合は、ifconfig
で wlan0
に割り当てられた IPアドレスへ、他マシンからログインする。
Raspbian Jessieは systemd
ベースなので、 sudo dpkg-reconfigure --frontend noninteractive tzdat
ではなく、 sudo timedatectl set-timezone Asia/Tokyo
で設定する。
pi@raspberrypi:~ $ timedatectl status
Local time: Fri 2016-05-27 11:51:06 UTC
Universal time: Fri 2016-05-27 11:51:06 UTC
RTC time: n/a
Time zone: Etc/UTC (UTC, +0000)
NTP enabled: no
NTP synchronized: yes
RTC in local TZ: no
DST active: n/a
pi@raspberrypi:~ $ sudo timedatectl set-timezone Asia/Tokyo
pi@raspberrypi:~ $ timedatectl status
Local time: Fri 2016-05-27 20:51:35 JST
Universal time: Fri 2016-05-27 11:51:35 UTC
RTC time: n/a
Time zone: Asia/Tokyo (JST, +0900)
NTP enabled: no
NTP synchronized: yes
RTC in local TZ: no
DST active: n/a
pi@raspberrypi:~ $
Raspberry Piデフォルトでは en_GB.utf8
しか生成されていないので、 ja_JP.utf8
を生成する。
ロケールの設定は systemd
スタイルのlocalectl
で行う。
ついでに、 jfbterm
を入れると同時に入る日本語フォントで、(GUIは使わないが)
GUIの文字化けを防ぐ。
ついでに、GUI用の日本語変換 ibus-anthy
も入れておく。
※256MB Raspberry Pi A+では、jfbterm
ibus-anthy
のインストールが非常に時間がかかるため、後回しにしてもよい。
pi@raspberrypi:~ $ sudo sed -i -e '/ja_JP.UTF-8/s/^# *//' /etc/locale.gen
pi@raspberrypi:~ $ sudo locale-gen
Generating locales (this might take a while)...
ja_JP.UTF-8... done
Generation complete.
pi@raspberrypi:~ $ sudo localectl set-locale LANG=ja_JP.utf8
pi@raspberrypi:~ $ sudo apt-get -y install jfbterm ibus-anthy
これらも Debian
スタイルではなくて、systemd
スタイルで設定する。
pi@raspberrypi:~ $ localectl status
System Locale: LANG=ja_JP.utf8
VC Keymap: n/a
X11 Layout: gb
X11 Model: pc105
pi@raspberrypi:~ $ sudo localectl set-keymap jp106
pi@raspberrypi:~ $ localectl status
System Locale: LANG=ja_JP.utf8
VC Keymap: jp106
X11 Layout: jp
X11 Model: jp106
X11 Options: terminate:ctrl_alt_bksp
pi@raspberrypi:~ $
RaspberryPi: raspi-config コマンドラインから設定(ノンイタラクティブ) - Qiitaより
pi@raspberrypi:~ $ sudo raspi-config nonint do_boot_behaviour B2
pi@raspberrypi:~ $ cat << EOS | sudo tee -a /boot/config.txt
max_usb_current=1
safe_mode_gpio=4
EOS
設定後、 reboot
で有効になるが、次の設定で reboot
するので、ここでは reboot
を実行しない。
Rasbpian
では dphys-swapfile
というデーモンで swap
ファイルを作って、システムに接続しているので、このデーモンを止めるとよい。
pi@raspberrypi:~ $ free
total used free shared buffers cached
Mem: 947748 140876 806872 6520 17336 64988
-/+ buffers/cache: 58552 889196
Swap: 102396 0 102396
pi@raspberrypi:~ $ sudo dphys-swapfile swapoff
pi@raspberrypi:~ $ free
total used free shared buffers cached
Mem: 947748 142100 805648 6520 17368 65532
-/+ buffers/cache: 59200 888548
Swap: 0 0 0
pi@raspberrypi:~ $ # sudo dphys-swapfile swapon # swapを使いたくなったら
pi@raspberrypi:~ $ sudo systemctl stop dphys-swapfile
pi@raspberrypi:~ $ sudo systemctl disable dphys-swapfile
Synchronizing state for dphys-swapfile.service with sysvinit using update-rc.d...
Executing /usr/sbin/update-rc.d dphys-swapfile defaults
Executing /usr/sbin/update-rc.d dphys-swapfile disable
insserv: warning: current start runlevel(s) (empty) of script `dphys-swapfile' overrides LSB defaults (2 3 4 5).
insserv: warning: current stop runlevel(s) (2 3 4 5) of script `dphys-swapfile' overrides LSB defaults (empty).
pi@raspberrypi:~ $
Raspberry Piの暴走を検知するWatchdog timerを入れる。
pi@raspberrypi:~ $ sudo apt-get -y install watchdog
pi@raspberrypi:~ $ sudo sed -i -e '/\[Install\]/a WantedBy=multi-user.target' /lib/systemd/system/watchdog.service
#(これがないと watchdogをsystemctlでenableできない)
pi@raspberrypi:~ $ sudo systemctl enable watchdog
pi@raspberrypi:~ $ sudo modprobe bcm2835_wdt
# これで /dev/watchdog ができる
pi@raspberrypi:~ $ cat << 'EOS'| sudo tee -a /etc/watchdog.conf
max-load-1 = 24
watchdog-device = /dev/watchdog
watchdog-timeout = 10
EOS
pi@raspberrypi:~ $ sudo systemctl start watchdog
テストは後でやろう
pi@raspberrypi:~ $ :(){ :|:& };:
[1] 1239
pi@raspberrypi:~ $
1分ほどで1分足のLoad averageが24以上になっていることが検知され、自動でrebootがかかる。
SoCの機能のWatchdog Timerはテストできていないんじゃないですかね……
Raspberry Pi 3は、 GPIO 14(TXD)
/ GPIO 15(RXD)
は今までの /dev/ttyAM0
ではなくて /dev/ttyS0
で利用するので、注意。
pi@raspberrypi:~ $ cat << EOS | sudo tee -a /boot/config.txt
core_freq=250
enable_uart=1
EOS
RaspberryPi: raspi-config コマンドラインから設定(ノンイタラクティブ) - Qiitaより
pi@raspberrypi:~ $ cat /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
pi@raspberrypi:~ $ grep -e enable_uart /boot/config.txt
enable_uart=1
pi@raspberrypi:~ $ sudo raspi-config nonint do_serial 1
pi@raspberrypi:~ $ cat /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
pi@raspberrypi:~ $ grep -e enable_uart /boot/config.txt
enable_uart=0
/dev/ttyS0(/dev/ttyAMA0)はデバイスとして認識して欲しいので、/boot/config.txt に enable_uart=1
を入れます(raspi-configでは enable_uart=0
に設定されてしまいます)。
pi@raspberrypi:~ $ sudo sed -i -e 's/enable_uart=0/enable_uart=1/' /boot/config.txt
[email protected]
を止め、UART
と getty
を切り離します。
pi@raspberrypi:~ $ sudo systemctl stop [email protected]
pi@raspberrypi:~ $ sudo systemctl mask [email protected]
設定を有効にする( /dev/ttyS0
を getty
から切り離す)ため reboot
します。
reboot後、 /dev/ttyS0
の通信速度のデフォルト値を設定します。
pi@raspberrypi:~ $ sudo stty -F /dev/ttyS0 ispeed 9600
さらに、 GPSを /dev/gps0
でアクセスできるように、 udev
にて
シンボリックリンクを作るようにします。Raspberry 3以前では、UARTが
/dev/ttyAMA0
となりますので、ここで KERNEL=="ttyAMA0"
としておけば、以降デバイス名の際は吸収できます。
Raspberry Pi 3の場合:
pi@raspberrypi:~ $ sudo cat << 'EOS' | sudo tee /etc/udev/rules.d/40-selialgps.rules
KERNEL=="ttyS0", SYMLINK+="gps0"
EOS
Raspberry Pi 3より前の場合
pi@raspberrypi:~ $ sudo cat << 'EOS' | sudo tee /etc/udev/rules.d/40-selialgps.rules
KERNEL=="ttyAMA0", SYMLINK+="gps0"
EOS
/dev/gps0
は /dev/ttyS0
もしくは /dev/ttyAMA0
を kernelが認識するタイミング
つまりboot時に作られるので、リブートします。
#sudo udevadm control --reload-rules しなくても良い
pi@raspberrypi:~ $ sudo reboot
GPSから出てくる情報を解析する gpsd
デーモンをインストールします。
pi@raspberrypi:~ $ sudo apt-get -y install gpsd gpsd-clients
本当は /dev/ttyS0
からGPSの情報が読めるかとか、
gpsd
がそれを読み込めるかとか、さらに /dev/gps0
からGPS情報が
読み取れるかとか、試行錯誤するのだけれども、
試行錯誤した結果以下の設定で読めることが分かった。
pi@raspberrypi:~ $ cat << EOS | sudo tee -a /etc/default/gpsd
USBAUTO="false"
DEVICES="/dev/gps0"
EOS
pi@raspberrypi:~ $ sudo systemctl start gpsd
pi@raspberrypi:~ $ sudo systemctl enable gpsd
Synchronizing state for gpsd.service with sysvinit using update-rc.d...
Executing /usr/sbin/update-rc.d gpsd defaults
Executing /usr/sbin/update-rc.d gpsd enable
pi@raspberrypi:~ $
pi@raspberrypi:~ $ cgps -s
http://qiita.com/athlonz/items/fb1e5a7d8b1a4e073d8c http://nyanchew.com/jp/gps%E3%81%AEpps%E4%BF%A1%E5%8F%B7%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F-stratum-1-ntp%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9
モジュールの読み込みを設定する。
pi@raspberrypi:~ $ echo pps-gpio | sudo tee -a /etc/modules
モジュールの動作パラメータを設定する。
pi@raspberrypi:~ $ echo dtoverlay=pps-gpio,gpiopin=18 | sudo tee -a /boot/config.txt
リブート前。 pps_gpio
pps_core
が入っていない。
pi@raspberrypi:~ $ lsmod
Module Size Used by
ppp_deflate 4520 0
zlib_deflate 22039 1 ppp_deflate
bsd_comp 6079 0
ppp_async 8326 1
crc_ccitt 1732 1 ppp_async
ppp_generic 26985 7 bsd_comp,ppp_async,ppp_deflate
slhc 5997 1 ppp_generic
cdc_acm 18718 2
snd_bcm2835 23163 0
snd_pcm 95473 1 snd_bcm2835
snd_timer 22396 1 snd_pcm
snd 68368 3 snd_bcm2835,snd_timer,snd_pcm
i2c_bcm2708 5740 0
bcm2835_gpiomem 3823 0
bcm2835_wdt 4133 1
uio_pdrv_genirq 3718 0
uio 10230 1 uio_pdrv_genirq
i2c_dev 6578 2
fuse 89800 1
ipv6 367575 28
pi@raspberrypi:~ $ sudo reboot
Connection to localhost closed by remote host.
Connection to localhost closed.
リブート後には、 pps_gpio
pps_core
が増えている。
pi@raspberrypi:~ $ lsmod
Module Size Used by
ppp_deflate 4520 0
zlib_deflate 22039 1 ppp_deflate
bsd_comp 6079 0
ppp_async 8326 1
crc_ccitt 1732 1 ppp_async
ppp_generic 26985 7 bsd_comp,ppp_async,ppp_deflate
slhc 5997 1 ppp_generic
cdc_acm 18718 2
snd_bcm2835 23163 0
snd_pcm 95473 1 snd_bcm2835
snd_timer 22396 1 snd_pcm
snd 68368 3 snd_bcm2835,snd_timer,snd_pcm
i2c_bcm2708 5740 0
bcm2835_gpiomem 3823 0
bcm2835_wdt 4133 1
uio_pdrv_genirq 3718 0
uio 10230 1 uio_pdrv_genirq
pps_gpio 2993 0
pps_core 8756 1 pps_gpio
i2c_dev 6578 2
fuse 89800 1
ipv6 367575 28
pi@raspberrypi:~ $ lsmod | grep pps
pps_gpio 2993 0
pps_core 8756 1 pps_gpio
pi@raspberrypi:~ $ sudo sed -i -e '/^server [0-9].debian.pool.ntp.org/s/^/#/' /etc/ntp.conf
pi@raspberrypi:~ $ cat << 'EOS' | sudo tee -a /etc/ntp.conf
server ntp.nict.jp iburst prefer
server 127.127.22.0 minpoll 4 maxpoll 4
fudge 127.127.22.0 flag3 1 refid PPS
EOS
pi@raspberrypi:~ $ sudo systemctl restart ntp
pi@raspberrypi:~ $ ntpq -p
pi@raspberrypi:~ $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get install -y nodejs
注意:ARMv6系SoC採用のRaspberry Pi(1/1+/Zero)では、Node.js公式のDebian・Ubuntu系パッケージリポジトリは使用できない模様。
pi@raspberrypi:~ $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
## Installing the NodeSource Node.js v6.x repo...
## You appear to be running on ARMv6 hardware. Unfortunately this is not currently supported by the NodeSource Linux
distributions. Please use the 'linux-armv6l' binary tarballs available directly from nodejs.org for Node.js v4 and
later.
pi@raspberrypi:~ $ mkdir testapp
pi@raspberrypi:~ $ cd testapp
pi@raspberrypi:~/testapp $ npm install node-gpsd
pi@raspberrypi:~/testapp $ nano app.js
'use strict'
var gpsd = require('node-gpsd');
var gpsListener = new gpsd.Listener({
port: 2947,
hostname: 'localhost',
logger: {
info: function() {
},
warn: console.warn,
error: console.error
},
parse: true
});
function startGPS () {
gpsListener.connect();
gpsListener.watch();
gpsListener.on('TPV', function (tpvData) {
console.log(tpvData);
});
}
startGPS();
実行
pi@raspberrypi:~/testapp $ node app.js
⑯ AWS-IOTのアプリを作る
git clone https://github.com/aws/aws-iot-device-sdk-js.git
cd aws-iot-device-sdk-js
npm install
cd aws-iot-device-sdk-js/
- certificate.pem.crt
- private.pem.key
- public.pem.key
を AWS-IoT
で Raspberry Piとして登録した時に出来たそれを配置する
nano examples/device-example2.js
//node.js deps
//npm deps
//app deps
const deviceModule = require('..').device;
const cmdLineProcess = require('./lib/cmdline');
var gpsd = require('node-gpsd');
var execSync = require('child_process').execSync;
var deviceid = 0; // GPIOにつながったDIP SWで決定させるなど
console.log("DeviceId: " + deviceid);
//begin module
function processTest(args) {
//
// The device module exports an MQTT instance, which will attempt
// to connect to the AWS IoT endpoint configured in the arguments.
// Once connected, it will emit events which our application can
// handle.
//
const device = deviceModule({
keyPath: args.privateKey,
certPath: args.clientCert,
caPath: args.caCert,
clientId: args.clientId,
region: args.region,
baseReconnectTimeMs: args.baseReconnectTimeMs,
keepalive: args.keepAlive,
protocol: args.Protocol,
port: args.Port,
host: args.Host,
debug: args.Debug
});
const gpsListener = new gpsd.Listener({
port: 2947,
hostname: 'localhost',
logger: {
info: function() {
},
warn: console.warn,
error: console.error
},
parse: true
});
// 'topic_1' というトピック名で送信
device.subscribe('topic_1');
var getRaspberryPiTemperature = function() {
// execSyncはnode v0.11からの機能
var temperature = "" + execSync('vcgencmd measure_temp');
// 出力形式は "59.6'C\n" となるので置換で単位と改行を取り除く
temperature = temperature.replace(/'C\n/,'').split('=')[1];
return temperature;
};
var startGPS = function() {
gpsListener.connect();
gpsListener.watch();
gpsListener.on('TPV', function (tpvData) {
//exec('vcgencmd measure_temp', function(err, stdout, stderr){
temperature = getRaspberryPiTemperature();
console.log(temperature);
//});
// var epoch = ((new Date).getTime()).toString().substring(10,-1);
var epoch = Date.parse(tpvData.time).toString().substring(10,-1);
device.publish('topic_1', JSON.stringify({
deviceid: deviceid,
timestamp: epoch,
gpsinfo: tpvData,
temperature: temperature
}));
//console.log(tpvData);
});
};
startGPS();
device
.on('connect', function() {
console.log('connect');
});
device
.on('close', function() {
console.log('close');
});
device
.on('reconnect', function() {
console.log('reconnect');
});
device
.on('offline', function() {
console.log('offline');
});
device
.on('error', function(error) {
console.log('error', error);
});
device
.on('message', function(topic, payload) {
console.log('message', topic, payload.toString());
});
}
module.exports = cmdLineProcess;
if (require.main === module) {
cmdLineProcess('connect to the AWS IoT service and publish/subscribe to topics using MQTT, test modes 1-2',
process.argv.slice(2), processTest);
}
node examples/device-example2.js -g ap-northeast-1