SSブログ

Edisonに天気予報をしゃべらせてみる [edison]

前回Open JTalkを使ってEdisonをしゃべらせることができるようになったので,今回は天気予報をしゃべらせてみる.

天気予報の情報はlivedoorの,お天気Webサービス - Weather Hacksからスクレイピングすることにする.

で,天気予報情報を取得したら,Open JTalkで合成音声を出力するようにしておく.
あとは,Edisonにスイッチをつけて,スイッチを押したら天気予報をしゃべるようにする.

今回は,node.jsでやってみた.

では,早速だがコードを示そう.

まず,main.js
var http = require('http');
var exec = require('child_process').exec;
var mraa = require('mraa');

var city = '140010';
var url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=' + city;
var weather_info = '';

var waveFilePath = '/tmp/';
var waveFileName = 'weather_info.wav';

var createWetherInfo = function(data) {
    var location_city       = data.location.city;
    var forecasts_dateLabel = data.forecasts[0].dateLabel;
    var forecasts_telop     = data.forecasts[0].telop;

    var forecasts_temp_max = '-';
    if (data.forecasts[0].temperature.max != null) {
        forecasts_temp_max  = data.forecasts[0].temperature.max.celsius;
    }

    var forecasts_temp_min = '-';
    if (data.forecasts[0].temperature.min != null) {
        forecasts_temp_min  = data.forecasts[0].temperature.min.celsius;
    }

    weather_info = location_city + "の"
                 + forecasts_dateLabel + "の天気は,"
                 + forecasts_telop + "でしょう.";
    if (forecasts_temp_max != '-') {
        weather_info += "最高気温は" + forecasts_temp_max + "度です.";
    }
    if (forecasts_temp_min != '-') {
        weather_info += "最低気温は" + forecasts_temp_min + "度です.";
    }
};

var createWaveFile = function() {
    var openjtalkShellCmd = '/home/root/openjtalk/openjtalk.sh';
    var cmd = openjtalkShellCmd + ' ' + weather_info + ' ' + waveFilePath + waveFileName;
    exec(cmd, function(err, stdout, stderr) {
        if (err) {
            console.log(err);
            console.log(err.code);
            console.log(err.signal);
        }
    });
};

var callback = function(data) {
    createWetherInfo(data);
    console.log(weather_info);

    createWaveFile();
};

var playWaveFile = function() {
    var cmd = 'aplay -D plughw:1 ' + waveFilePath + waveFileName;
    exec(cmd, function(err, stdout, stderr) {
        if (err) {
            console.log(err);
            console.log(err.code);
            console.log(err.signal);
        }
    });
};

x = new mraa.Gpio(14);
x.dir(mraa.DIR_IN);
x.mode(mraa.MODE_PULLUP);
x.isr(mraa.EDGE_FALLING, playWaveFile);

weatherInfo(callback);
setInterval(function() {
    weatherInfo(callback);
}, 10 * 60 * 1000);


function weatherInfo(callback) {
    http.get(url, function(res) {
        var body = '';
        res.setEncoding('utf8');

        res.on('data', function(chunk) {
            body += chunk;
        });

        res.on('end', function() {
            callback(JSON.parse(body));
        });

    }).on('error', function(e) {
        console.log(e.message);
    });
}


次に,package.json
{
  "name": "weather_info",
  "description": "",
  "version": "0.0.0",
  "main": "main.js",
  "engines": {
    "node": ">=0.10.0"
  },
  "dependencies": {
  }
}


この2つのファイルを,たとえばホームディレクトリ下にweather_infoディレクトリを作成して保存しておく.
なお,Open JTalkは前回のとおり,ホームディレクトリ下のopenjtalkディレクトリにインストールされてる前提で書かれているので,もし変更してるなら環境に合わせて変更が必要だ.

これで,10分おきにWeather Hacksから天気予報を取得してくる.上記のコードでは横浜の天気予報を取得するようになっている.main.js:5でvar city = '140010';としているが,これはWeather Hacksのcityパラメータそのものだ.なので地域を変更したければこの値を変更すればよい.定義はWeather Hacksのページに情報がある.

天気予報の合成音声は,取得した天気予報情報のうち,天気と最高気温と最低気温から,
「横浜の今日の天気は,XXXでしょう.最高気温はYY度です.最低気温はZZ度です.」
といった感じで生成され,/tmp/weather_info.wavとして保存されるようにしてある.最高気温と最低気温は(データが有効なときだけ)出力されるので,天気だけしかしゃべらないときもある.

Edisonにつなぐスイッチは,(回路図にするほどのこともないが)以下のように接続してやる.Edisonの内蔵プルアップを使用するので,単にスイッチをつなぐだけだ.
switch_回路図.png

スイッチが押されたかどうかは割り込みで監視していて,押されたらあらかじめ生成してあるweather_info.wavを再生するようになっている.

最初はスイッチが押されたら天気予報を取得して,wather_info.wavを生成して再生するようにしようと思ったのだが,情報取得と音声生成の処理があるのでスイッチを押しても若干待たされる.というわけで,あらかじめwather_info.wavの作成まで定期的に行っておいて,スイッチが押されたら単に生成済みのweather_info.wavを再生するだけにしてある.これならスイッチを押したらすぐに天気予報をしゃべるようになる.

そしたら最後に,Edison起動時に自動実行するようにしておく.
まず,weather_infoのディレクトリに,start_weather_info.shというスクリプトを用意しておく.
#!/bin/sh

/usr/bin/node /home/root/weather_info/main.js


で実行権限付与.
chmod 755 start_weather_info.sh


そしたら次に,/lib/systemd/system/下に,weather_info.serviceというファイルを作成してやる.
[Unit]
Description=Weather_Info
After=network.target

[Service]
Environment="NODE_PATH=/usr/lib/node_modules"
Environment="NODE_ENV=production"
Environment="HOME=/home/root"
ExecStart=/home/root/weather_info/start_weather_info.sh

[Install]
WantedBy=multi-user.target


そしたら自動起動ONにして起動させてみる.
systemctl enable weather_info.service
systemctl start weather_info.service


これでOK.

ただ,これで試してみると,Edisonが起動したときの実行1回目でエラーが出るようだ.どうやらWheather HacksにアクセスしようとするがDNSでエラーになっているっぽい.実行タイミングが早すぎる感じだ.weather_info.serviceのAfter=network.targetあたりを変更するといいような気がするのだが,具体的にどうすればよいのか分からない.
とりあえず,最初の1回はエラーになるが10分後の実行からは問題なく動作するので気にしないことにしておく.

というわけで,これで完了.
お試しあれ.

2015.05.02追記
SyntaxHighlighterを使ったらコードのvar url = の部分の表記がおかしくなったので修正.

nice!(0)  トラックバック(0) 
共通テーマ:日記・雑感

EdisonでOpen JTalkを使ってみる [edison]

前回,EdsionでUSB Audioを使えるようにしたので,今回はOpen JTalkを使ってEdisonにしゃべらせてみる.Open JTalkはフリーの日本語音声合成エンジンだ.

ではさっそくインストール.

まず,hts_engine APIをインストール.適当なディレクトリ(以下ではopenjtalk)を用意してダウンロード,展開してインストールしてやる.
cd ~/
mkdir openjtalk
cd openjtalk/
wget http://downloads.sourceforge.net/hts-engine/hts_engine_API-1.09.tar.gz
tar xzvf hts_engine_API-1.09.tar.gz
cd hts_engine_API-1.09/
./configure
make
make install

次に,OpenJTalkのインストール
cd ~/openjtalk/
wget http://downloads.sourceforge.net/open-jtalk/open_jtalk-1.08.tar.gz
wget http://downloads.sourceforge.net/open-jtalk/open_jtalk_dic_utf_8-1.08.tar.gz
wget http://downloads.sourceforge.net/open-jtalk/hts_voice_nitech_jp_atr503_m001-1.05.tar.gz

tar xzvf open_jtalk-1.08.tar.gz
cd open_jtalk-1.08/
./configure \
     --with-hts-engine-header-path=/usr/local/include \
     --with-hts-engine-library-path=/usr/local/lib \
     --with-charset=utf-8
make
make install

cd ~/openjtalk/
tar xzvf open_jtalk_dic_utf_8-1.08.tar.gz
tar xzvf hts_voice_nitech_jp_atr503_m001-1.05.tar.gz

MMDAgentのサイトから音声データをダウンロード
wget http://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/MMDAgent_Example-1.4/MMDAgent_Example-1.4.zip
unzip MMDAgent_Example-1.4.zip


Open JTalkの実行にはオプションが多いので,スクリプトを作成して実行する.
vi openjtalk.sh

#!/bin/sh

OPENJTALK_DIR=/home/root/openjtalk
VOICE=$OPENJTALK_DIR/MMDAgent_Example-1.4/Voice/mei/mei_normal.htsvoice
DIC=$OPENJTALK_DIR/open_jtalk_dic_utf_8-1.08
echo $1 | open_jtalk \
-m  $VOICE \
-x  $DIC \
-ow $2 \
-g 9

ちなみに,最後の-gはvolume(dB)を指定するオプションだ.
前回,EdisonにUSB Audioを接続したが,スピーカーが100均のパッシブスピーカーなので音がとても小さい.なので,Open JTalkの出力をあらかじめ上げておく.値を大きくすると出力の音量が大きくなる.あまり上げすぎると音が歪んでしまうので適当に調整してみてくださいな.

あとは作成したスクリプトに実行属性を設定して,
chmod 744 openjtalk.sh

しゃべらせてみる.とりあえず「テストです」としゃべってもらうには,
./openjtalk.sh "テストです" a.wav

これでa.wavファイルが作成される.

再生はうちの環境では
aplay -D plughw:1 a.wav

でOK.

お試しあれ.

タグ:openjtalk
nice!(1)  トラックバック(0) 
共通テーマ:日記・雑感

EdisonでUSB Audioを使ってみる [edison]

Intel Edisonから音を出すために,USB Audioアダプタをつないでみる.
使ったのは,PLANEXのPL-US35APだ.

PLANEX USB→3.5mmヘッドホン/マイク端子 USBオーディオ変換アダプタ PL-US35AP

PLANEX USB→3.5mmヘッドホン/マイク端子 USBオーディオ変換アダプタ PL-US35AP

  • 出版社/メーカー: プラネックス
  • メディア: Personal Computers

また,Edisonと接続する際,Intel Edison Breakout Board側のUSB端子はMicroBタイプ,USB AudioアダプタはAタイプなので,BUFFALOのBSMPC11C01BKを使ってつないでやる.

iBUFFALO USB(microB to A)変換アダプター ブラック BSMPC11C01BK

iBUFFALO USB(microB to A)変換アダプター ブラック BSMPC11C01BK

  • 出版社/メーカー: バッファロー
  • メディア: エレクトロニクス


なお,EdisonにUSB機器をつなぐとUSBポートから電源供給できなくなるので,別途ACアダプタを使って電源供給してやる.
使ったのは,秋月の,
ブレッドボード用DCジャックDIP化キット
超小型スイッチングACアダプター12V1A 100V~240V GF12-US1210
で,ジャンパー線でEdisonのJ21に接続してやる.

あとはスピーカーだが,今回は100均のSeriaで売っていた,ZY-76というのを買ってみた.
ZY-76.jpg

そしたら,あとは接続するだけだ.

以前はEdisonでUSB Audioを使うにはカーネルのビルドが必要だったが,最新のYoctoイメージでは必要なくなった.最新のYocto complete imageは,ここからダウンロードできる.現時点では,edison-image-ww05-15.zipが最新のようだ.

では,動作テスト.
以下のサイトを参考にしながら適当なwavファイルを再生してみる.
Intel Edisonを動かす(4) サウンド編 | IoT

すると,あっさりと動作した.
が,1点問題が...

ちょっとネットで調べれば分かるが,今回使った100均スピーカをアンプなしで使うと,音量がかなり小さい.USB Audioの出力を100%にしてなんとか聞こえる程度だ.
もう少し音量が得られるといいのだが...
とりあえず聞こえるので良しとしよう.

タグ:USB Audio
nice!(1)  トラックバック(0) 
共通テーマ:日記・雑感

EdisonでIoT Analyticsを使ってみる [edison]

前回,Intel XDK IoT Editionで温湿度センサAM2321を使ってみた.
今回は,その温湿度センサの値をIoT Analyticsへ飛ばしてみる.

IoT Analyticsがどんなものであるかとか,必要な設定は下記サイトが詳しい.
21: Intel Edison実践編 (1) 〜 センサーデータを受け取るSaaS「IoT Analytics」
22: Intel Edison実践編 (2) 〜 EdisonからIoT Analyticsにデータを送る
23: Intel Edison実践編 (3) 〜 XDKで開発したプログラムからiotkit-agentにデータを送る

というわけで,上記サイトを参考に,ほぼそのままやってみる.ただ,今回は温度と湿度をIoT Analyticsに送りたいので,以下のようにコマンドを入力してやる.
iotkit-admin register temperature temperature.v1.0
iotkit-admin register humidity humidity.v1.0


あとはコードだが,前回同様,適当なProjectを作って,package.jsonとmain.jsを以下のようにしてやる.

まず,package.json
{
  "name": "iot_analytics_test",
  "description": "",
  "version": "0.0.0",
  "main": "main.js",
  "engines": {
    "node": ">=0.10.0"
  },
  "dependencies": {
      "sleep": "*"
  }
}

次に,main.js
var dgram = require('dgram');
var client = dgram.createSocket('udp4');
var udpOptions = {
    host : '127.0.0.1',
    port : 41234
};
 
function sendObservation(name, value, on){
    var msg = JSON.stringify({
        n: name,
        v: value,
        on: on
    });
 
    var sentMsg = new Buffer(msg);
    console.log("Sending observation: " + sentMsg);
    client.send(sentMsg, 0, sentMsg.length, udpOptions.port, udpOptions.host);
}

var mraa = require('mraa');
console.log('MRAA Version: ' + mraa.getVersion());

var sleep = require('sleep');

function crc16(buf, length)
{
    var crc = 0xFFFF;
    for (var j = 0; j < length; j++) {
        crc ^= buf[j];
        for (var i = 0; i < 8; i++) {
            if (crc & 0x01) {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

function Am2321(bus, address, bufsize) {
    this.x = new mraa.I2c(bus);
    this.x.address(address);
    this.buff = new Buffer(bufsize);
    
    this.wakeupSensor = function() {
        this.x.writeReg(0, 0);
    }
    
    this.sendCommand = function() {
        get_command = new Buffer([0x03, 0x00, 0x04]);
        this.x.write(get_command);
        sleep.usleep(1500);
    }
    
    this.receiveData = function() {
        this.buff = this.x.read(8);
    }
    
    this.checkCrc = function() {
        var crc = this.buff[6] + this.buff[7] * 256;
        return crc == crc16(this.buff, 6);
    }
    
    this.checkRecieveData = function() {
        return (this.buff[0] == 0x03) && (this.buff[1] == 0x04);
    }

    this.getHumidity = function() {
        var high = this.buff[2];
        var low  = this.buff[3];
        return (high * 256 + low) / 10;
    }

    this.getTemperature = function() {
        var temperature = 0;
        var high = this.buff[4];
        var low  = this.buff[5];

        if (high & 0x80) {
            temperature = -1 * (high & 0x7F) * 256 + low;
        }
        else {
            temperature = high * 256 + low;
        }
        return temperature / 10;
    }
}

var sensor = new Am2321(6, 0x5C, 8);
periodicActivity();

function periodicActivity()
{
    sensor.wakeupSensor();
    sensor.sendCommand();
    sensor.receiveData(); 

    if (sensor.checkCrc() == true) {
        if (sensor.checkRecieveData() == true) {
            var humidity = sensor.getHumidity();
            var temperature = sensor.getTemperature();
            console.log("%d %%, %d C", humidity, temperature);
            
            var date = new Date();
            sendObservation('humidity',    humidity,    date.getTime());
            sendObservation('temperature', temperature, date.getTime());
        }
    }

    setTimeout(periodicActivity,10000);
}


これをビルドして実行すると,IoT Analyticsに10秒おきに温度と湿度を送信するようになる.

で,しばらく動かしてみたときの結果は,こんな感じ.
IoT Analytics Graph.png
送信したデータをグラフにしてくれる.あと,csvのエクスポートも可能だ.

非常にお手軽に温湿度を送ることができる.
お試しあれ.

nice!(0)  トラックバック(0) 
共通テーマ:日記・雑感

Intel XDK IoT Editionを使って温湿度センサを動かしてみる [edison]

前回,EdisonでArduino IDEから動かしてみた.
今回は,Intel XDK IoT Editionを使って温湿度センサを動かしてみる.

というわけで,まず,Intel XDK IoT Editionのインストール.
インストール手順とか,Intel XDK IoT Editionの使い方等は,詳しく書かれているサイトがいくつもあるので,そちらを参照下さいな.
たとえば...
Edisonを開封してからnode.jsでIOポート制御するまで - Qiita
Intel EdisonでIntel XDK for IoTを使う - Qiita
[Edison]Intel XDK IoT Edisonをつかってプログラムのビルドをしてみる | Developers.IO
あたりが参考になるかと.

で,温湿度センサを動かしてみる.温湿度センサは前回使った,AM2321だ.接続(回路図)等は前回から変わってない.

というわけで,早速コードを示そう.
適当なProjectを作って,package.jsonとmain.jsを以下のようにしてやる.

まず,package.json
{
  "name": "TemperatureHumiditySensor",
  "description": "",
  "version": "0.0.0",
  "main": "main.js",
  "engines": {
    "node": ">=0.10.0"
  },
  "dependencies": {
      "sleep": "*"
  }
}

次に,main.js
var mraa = require('mraa');
console.log('MRAA Version: ' + mraa.getVersion());

var sleep = require('sleep');

function crc16(buf, length)
{
    var crc = 0xFFFF;
    for (var j = 0; j < length; j++) {
        crc ^= buf[j];
        for (var i = 0; i < 8; i++) {
            if (crc & 0x01) {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

function Am2321(bus, address, bufsize) {
    this.x = new mraa.I2c(bus);
    this.x.address(address);
    this.buff = new Buffer(bufsize);
    
    this.wakeupSensor = function() {
        this.x.writeReg(0, 0);
    }
    
    this.sendCommand = function() {
        get_command = new Buffer([0x03, 0x00, 0x04]);
        this.x.write(get_command);
        sleep.usleep(1500);
    }
    
    this.receiveData = function() {
        this.buff = this.x.read(8);
    }
    
    this.checkCrc = function() {
        var crc = this.buff[6] + this.buff[7] * 256;
        return crc == crc16(this.buff, 6);
    }
    
    this.checkRecieveData = function() {
        return (this.buff[0] == 0x03) && (this.buff[1] == 0x04);
    }

    this.getHumidity = function() {
        var high = this.buff[2];
        var low  = this.buff[3];
        return (high * 256 + low) / 10;
    }

    this.getTemperature = function() {
        var temperature = 0;
        var high = this.buff[4];
        var low  = this.buff[5];

        if (high & 0x80) {
            temperature = -1 * (high & 0x7F) * 256 + low;
        }
        else {
            temperature = high * 256 + low;
        }
        return temperature / 10;
    }
}

var sensor = new Am2321(6, 0x5C, 8);
periodicActivity();

function periodicActivity()
{
    sensor.wakeupSensor();
    sensor.sendCommand();
    sensor.receiveData(); 

    if (sensor.checkCrc() == true) {
        if (sensor.checkRecieveData() == true) {
            var humidity = sensor.getHumidity();
            var temperature = sensor.getTemperature();
            console.log("%d %%, %d C", humidity, temperature);
        }
    }

    setTimeout(periodicActivity,5000);
}

そしたら,ビルドして,Edisonにアップロードして実行してやる.
そうすると,コンソールに温度と湿度が5秒おきに出力されるようになる.

AM2321はI2Cの通信シーケンスに癖があるのだが,とりあえず上記のコードで動作させることができるようだ.

MRAAライブラリがあるので,Arduinoで動かしたときと同じぐらい簡単.
お試しあれ.

タグ:XDK
nice!(0)  トラックバック(0) 
共通テーマ:日記・雑感

Edisonに温湿度センサをつないでみる [edison]

Edisonに温湿度センサをつないでみた.
使用したのは,秋月電子で以前購入した,温湿度センサモジュールAM2321だ.
このセンサは,当初は中国語のデータシートしかなかったらしいが,今は英語のデータシートを確認することができる.
また,デジタル 温度・湿度センサー AM2321 を制御 - Neにマニュアルを日本語訳された方の情報があって,とても助かりました.

というわけで,センサの詳細は上記を参照してもらうとして...
このセンサ,買って手元に届いてから気がついたんだけど,ピン間隔が1.27mmになっていて,そのままではブレッドボードに挿せない.なので,ピンをやや曲げて間隔を広げつつ,ピンヘッダに半田付けしてやる.
半田付けがちょっと汚いが,こんな感じ.
AM2321-1.jpg
これでブレッドボードに挿せる.

さて,ではEdisonとの接続だ.
AM2321は通信モードとしてI2Cか1-Wireが選べるんだけど,今回はI2Cを使うことにした.EdisonはIntel Edison Breakout Boardを使っているので,IOは1.8Vだ.なので以前の照度センサをつないでみたときと同様に,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続してやる.

回路図はこんな感じになる.I2Cのレベル変換モジュールはジャンパカットが必要なので注意.
当初はこんな感じで接続していたが,AE-PCA9306ではVref2側を高電圧側にするべきである.詳細は,ここのコメント欄を参照.
temperature_humidity_sensor_ng.png
なので,こちらの回路図のように接続すべきである.
temperature_humidity_sensor.png

で,接続するとこんな感じ.写真はAE-PCA9306のVref2側を低電圧側にしちゃったままのものだが,接続のイメージはつかめると思う.
AM2321-2.jpg

Arduinoで動作させてみる.スケッチは,いろんなサイトを参考にしつつ作成した.これでシリアルに温度と湿度が5秒おきに送られてくる.
#include <Wire.h>

#define I2C_AM2321_ADDRESS                0x5C
#define REGISTER_ADDRESS_HUMIDITY_HIGH    0x00
#define REGISTER_ADDRESS_HUMIDITY_LOW     0x01
#define REGISTER_ADDRESS_TEMPERATURE_HIGH 0x02
#define REGISTER_ADDRESS_TEMPERATURE_LOW  0x03
#define READ_REGISTER_LENGTH              0x04
#define FUNCTION_CODE_READ_REGISTER       0x03

enum BUFF_INDEX {
    INDEX_FUNCTION_CODE = 0,
    INDEX_RETURN_BYTE,
    INDEX_HUMIDITY_HIGH,
    INDEX_HUMIDITY_LOW,
    INDEX_TEMPERATURE_HIGH,
    INDEX_TEMPERATURE_LOW,
    INDEX_CRC_LOW,
    INDEX_CRC_HIGH,
    INDEX_MAX,
};
    
void wakeupSensor()
{
    Wire.beginTransmission(I2C_AM2321_ADDRESS);
    Wire.write(0x00);
    Wire.endTransmission();
}

void sendReadCommand()
{
    Wire.beginTransmission(I2C_AM2321_ADDRESS);
    Wire.write(FUNCTION_CODE_READ_REGISTER);
    Wire.write(REGISTER_ADDRESS_HUMIDITY_HIGH);
    Wire.write(READ_REGISTER_LENGTH);
    Wire.endTransmission();

    delayMicroseconds(1500);
}

void receiveData(byte (&buff)[INDEX_MAX])
{
    Wire.requestFrom(I2C_AM2321_ADDRESS, INDEX_MAX);
    int index = 0;
    while (Wire.available()) {
        buff[index++] = Wire.read();
    }
}

unsigned short crc16(unsigned char *ptr, int length)
{
    unsigned short crc = 0xFFFF;

    while (length--) {
        crc ^= *ptr++;
        for (int i = 0; i < 8; i++) {
            if (crc & 0x01) {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

bool checkCrc(byte (&buff)[INDEX_MAX])
{
    unsigned short crc = 0;
    crc  = buff[INDEX_CRC_LOW];
    crc |= buff[INDEX_CRC_HIGH] << 8;

    return (crc == crc16(buff, 2 + READ_REGISTER_LENGTH));
}

bool checkReceiveData(byte (&buff)[INDEX_MAX])
{
    return ( (buff[INDEX_FUNCTION_CODE] == FUNCTION_CODE_READ_REGISTER)
          && (buff[INDEX_RETURN_BYTE]   == READ_REGISTER_LENGTH) );
}

bool readAm2321(byte (&buff)[INDEX_MAX])
{
    wakeupSensor();
    sendReadCommand();
    receiveData(buff);
    if (!checkCrc(buff)) {
        return false;
    }
    return checkReceiveData(buff);
}

signed int convertHumidity(byte high, byte low)
{
    return high * 256 + low;
}

signed int convertTemperature(byte high, byte low)
{
    signed int temperature = (high & 0x7F) * 256 + low;
    temperature *= (high & 0x80) ? -1 : 1;
    return temperature;
}

void displayHumidityAndTemperature(signed int humidity, signed int temperature)
{
    Serial.print(temperature / 10);
    Serial.print(".");
    Serial.print(temperature % 10);
    Serial.print("C");
    Serial.print(", ");

    Serial.print(humidity / 10);
    Serial.print(".");
    Serial.print(humidity % 10);
    Serial.print("%");
    Serial.println();
}

void setup()
{
    Serial.begin(9600);
    Wire.begin();
}

void loop()
{
    byte buff[INDEX_MAX] = {0};
    bool result = readAm2321(buff);

    if (result == true) {
        signed int humidity = convertHumidity(buff[INDEX_HUMIDITY_HIGH],
                                              buff[INDEX_HUMIDITY_LOW]);
        signed int temperature = convertTemperature(buff[INDEX_TEMPERATURE_HIGH],
                                                    buff[INDEX_TEMPERATURE_LOW]);

        displayHumidityAndTemperature(humidity, temperature);
    }

    delay(5000);
}


このセンサはI2Cの通信シーケンスに癖があって,WakeUpが必要だったり,アドレス送信後にWaitが必要だったりする.なお、上のスケッチでは,アドレス送信後のWaitはArduinoのWireライブラリではできない(できるかもしれないがやり方が分からない)ので対応してない.

あと,ときどき,受信データByte数が0で返ってくることがある.エラーは返ってこないしCRCチェックも正常なのだが.なので,Arduino側で4Byte受信したかどうかのエラーチェックもやっている.

それから,ときどき湿度値が3%ぐらい落ち込むことがある.

センサーの湿度の値が: さとうしゅうの 日々平安 2.37
で書かれてる現象と同じっぽい.I2C通信するとき,AM2321仕様にある通信シーケンス(Wait等)を守っていないからなのかなとも思ったが,

Arduino/みんな試作機/温湿度計 - 講義のページ - MyDNS.JP
に書かれてる「動作確認-2-」の測定例を見ても湿度値が落ち込んでいるところがある.こちらはI2Cではなく1-Wireで通信した結果のようなので,通信シーケンスに問題があるのではなさそうだ.

AM2321側が何か問題があるのではないかと思うのだが,詳細はよくわからない.
まぁあまり気にしないことにする.

というわけで若干動作が怪しいところがある気がするが,お手軽に使えるのでお試しあれ.

あーでも,秋月にHDC1000使用 温湿度センサーモジュールってのがあって,こっちも試してみたい.AM2321を購入したときにはなかったんだよなぁ.こっちはピン間隔が2.54mmピッチだし,TI製だし.機会があれば試してみたいが,そんなにいくつも温湿度センサっていらないよなぁ...
nice!(2)  トラックバック(0) 
共通テーマ:日記・雑感

Edisonでmraaを使ってLチカをやってみる [edison]

以前は,Arduino IDEを使ってLチカをやってみたが,今回はmraaを使ってLチカをやってみる.
回路図は以前と同じ.

なお,Arduino IDEでいう13番ピンは,EdisonモジュールのGP40ピンだが,mraaでは別途ピン番号が管理されていて,mraa numberは37になる.ちなみに,情報は「mraa/edison.md at master · intel-iot-devkit/mraa · GitHub」にある.

今回はEclipseを使ってクロスビルドして試してみた.Eclipseでの開発はこんな感じ.
スクリーンショット 2014-11-29 20.21.49.png

参考にしたのは,公式の,「Getting Started for C/C++ (Eclipse) - Galileo & Edison」だ.

コードは,スクリーンショットをみれば分かるが,一応ここにも記載しておく.
#include "mraa.hpp"

static int iopin = 37;

int main(int argc, char **argv) {
    mraa::Gpio* gpio = new mraa::Gpio(iopin);
    if (gpio == NULL) {
        return MRAA_ERROR_UNSPECIFIED;
    }

    mraa_result_t response = gpio->dir(mraa::DIR_OUT);
    if (response != MRAA_SUCCESS) {
        mraa::printError(response);
        return 1;
    }

    while (true) {
        response = gpio->write(1);
        sleep(1);
        response = gpio->write(0);
        sleep(1);
    }
    delete gpio;
    return response;
}


Eclipseからはリモートデバッグも可能なようだ.

それにしてもArduino IDEからの制御も楽だが,mraaも楽だな...
お試しあれ.

タグ:Eclipse
nice!(1)  トラックバック(0) 
共通テーマ:日記・雑感

Edisonに照度センサをつないでみる [edison]

前回,Arduinoに照度センサをつないでみたが,今回はEdisonにつないでみる.
EdisonはIntel Edison Breakout Boardを使っているので,IOは1.8Vだ.arduinoのときは5Vだったが今回は1.8Vだ.だけど,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続するってのは変わらない.

接続はこんな感じ.
当初はこんな感じで接続していたが,Kさんからコメントいただいたように,AE-PCA9306ではVref2側を高電圧側にするべきである.
luminance_sensor_ng.png
なので,こちらの回路図のように接続すべきである.
luminance_sensor.png

今回もArduino IDEで動かしてみる.
スケッチは,前回Arduinoで動かしたときと全く一緒でOK.

が,動かしてみたらうまく動かなかった.

調べてみると,こんな記事が見つかった.
Edison のI2Cを試してみる — Edison-Note 1.3 documentation
Edison Breakout BoardでI2C通信テスト[1](C言語,mraaライブラリ,PCA9306,DRV8830を使用) - Qiita

どうやらEdisonのI2Cは内蔵プルアップが有効になっているようで,一方,秋月のレベル変換モジュールもデフォルトではプルアップが有効になっていて,これのせいでうまく通信できない.

最初はEdisonの内蔵プルアップを無効にしようと思ったんだけど,さんざんWeb上の情報を探したけど方法が見つからなかった.というわけで,秋月のレベル変換のプルアップを無効にすることにした.やりかたは,AE-PCA9306モジュール取扱説明書(927KB)に書かれている通り,ジャンパをカットすればいい.
今回は,Edison側だけレベル変換モジュールのプルアップを無効にして,照度センサ側は(センサ側でプルアップしてないので)レベル変換モジュールのプルアップは有効のままにしておく.

上記の回路図のように接続しているので,カットするジャンパは,J2とJ3 J4とJ5だ.

で,これで試したら無事通信できた.Arduinoで試したときと同じように動いたのでOKだ.
お試しあれ.
nice!(1)  トラックバック(0) 
共通テーマ:日記・雑感

EdisonでLチカを試してみる [edison]

Edisonで定番のLチカをやってみる.
IntelのGetting Started GuideではIntel Edison Arduino BoardでのLチカが説明されているが,うちはIntel Edison Breakout Boardなのでちょっと違うが,まぁ試してみる.

といっても,Arduino IDEをダウンロードして,SampleのBlinkを書き込んでやるだけだ.

ただ,LEDはArduino Boardの13番ピンにつながってる前提のサンプルなのだが,Breakout BoardにArduinoの13番ピンなんてないので,該当するピンに読み替えてやる必要がある.

で,回路図をみると,Arduino Boardの13番ピンは,EdisonモジュールのGP40ピンで,これはBreakout BoardでいうJ19-10番ピンにつながっているようだ.

というわけで,LEDをつないでテストしてみる.
ただ,Breakout BoardはIOが1.8Vで,かつIO出力も3mAしかないようなので,そのままLEDを点灯させるのはやめて,レベル変換ICを通して点灯させることにする.
レベル変換ICは先日購入しておいた,秋月電子の「8ビット双方向ロジックレベル変換モジュール」を使う.

で,こんな感じに接続.
Untitled.png

DSC_0131 のコピー.jpg

これで試したら,LEDの点滅が無事確認できた.

さて,次は何に手を出そうか...

nice!(2)  トラックバック(0) 
共通テーマ:日記・雑感

intel Edisonを入手してみる [edison]

intel Edisonを買ってみた.

「Edison Kit for Arduino」と,「Edison Breakout Board Kit」のどちらにするか迷ったが,せっかくEdisonが小さいんだからその小ささが生かされる「Edison Breakout Board Kit」にしてみた.

で,購入したのはこれ.
Intel Edison Breakout Board Kit
USBケーブル Aオス-マイクロBオス 1.5m A-microB 2本
スチロールケース SK-2

ケースは秋月のサイトで「びったとり入ります」と書かれていたので買ってみた.

あと,「Edison Breakout Board Kit」のIO電圧は1.8Vなので,
8ビット双方向ロジックレベル変換モジュール
も買った.

それから,Breakout Boardはピンホールがあるだけで,いろいろ試すとするとピンホールに線材を半田付けすることになると思うが,いきなり半田付けってのはやりたくないなぁと思ってたら,スルーホール用テストワイヤというのがあったのでそれも買ってみた.
テストワイヤ TTW-200
TTW-200_02.jpg

「スルーホールに挿し込むだけで信号の入力やチェックができます」とのことで,半田付けせずに試せる.ただ,Breakout Boardに思いっきり挿すとEdison本体のシールドに接触するかもしれないので,何らかの絶縁はした方が良さそうである.とりあえずうちでは紙を挟んである.

で,実は10月末には入手済みだったのだが,最近やっといじり始めている.
とりあえず,最新のFWにアップデートして,WiFi設定なんかまではやってみた.この辺の作業内容は本家含めネット上にたくさん情報があるのでそれを参考に.

それにしても小さい.以前,BeagleBoard-xMを入手したときにも「小さいなぁ」と感じたけど,これはもっと小さい.
Raspberry Piだって十分小さいけど,それよりも小さい.しかもパワフル.

さて,とりあえず次回はLチカやってみよう.
nice!(1)  トラックバック(0) 
共通テーマ:日記・雑感

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。