2015年2月21日土曜日

負け続ける週末>故BBB、24GHzレーダー、LTSpice IV

FRDM-KL46につないだ24Ghz、10Ghz、24Ghz勢揃い

昨夜、Beagleboneさんを壊してしまいました…端子に過電圧がかかって、いや掛けてしまい、あっという間でした。電源入らず、3.3v-GND間がほぼ短絡状態になっているので、私の手には終えません。私の電子工作史上、自分で壊したもののとしてはもっとも高価なデバイスです…。ごめんなさい>beaglebone

これが生前最後の姿でした…
ということで、死蔵してたもう一台のBBBを箱から出してきましたが、これは悪名高きsshで入れないバージョン。BBB-FlusherをSD Cardに組み込むところからはじめて約2時間かかって何とかBBB警備?システムをリカバリしました。

その後は秋月から届いた24Ghzドップラーレーダーで遊びます。

これは出力が-300mV 〜 +300mVとのことなので、ADCで読むには 0-1800mVぐらいに変換してやる必要があります。

オペアンプで減算回路というものを組めばうまく行きそうなのですが、算数のできないワタシには抵抗値を決められませんw しばらくGoogle Spreadsheetで数字をいじったのですが、ぴったりの数字が出てこないし、そもそもそれで正しく動くのかも不明。

というわけで、LTSpice IVに初挑戦してみました。いつの間にかMac版があるのですね。

しかし起動しても、よく見るような画面ではなく、ボタンが3つ並んだだけのシンプルというより殺風景なウィンドウ。ツールバーっぽいものは無く、どうやらファンクションキーやコンテキストメニューで操作していかなければならない様子。

いやー…EagleのGUIが素晴らしく見えるレベルで、面倒くさい操作でした。それでも折角MacにやってきてくれたLTSpiceさん、ちゃんとシミュレーションができればそれで十分、今後に期待します。ただ、Windows版ではパラメータをGUIから設定すればドットコマンドというのを生成してくれるようですが、mac版では手動です。手動で入力している例があまりなくて探すのに苦労しましたが、とりあえず「.tran 1s」と入力してやれば、10秒間の任意の箇所の電流電圧をグラフ化してもらえます。ここまで約2時間でした。いやはや。


一度抵抗値を決めたものの、手持ちのパーツに100kを越える抵抗がなかったので、また計算し直してLM358でブレッドボードに回路を組みます。



で、ドップラーレーダーをつない電圧を見る…のですが、レーダーの前で手をひらひらさせても、想定していたような電圧は出てくれません。だいたい±30mVぐらいで、動きと一致しているようなしていないような微妙な値です。大きなものがもっと高速移動しないとダメなのかもしれませんが、これ室内用なんですよね。

日本無線の24GHzドップラーレーダーよりも安いし、アナログ出力でいろいろ遊べそうだったのですが…。

あと、アマゾンで「サンハヤト ジャンプワイヤキット SKS-100 単線タイプでよく使用する短めジャンプワイヤのセット品」ってのを売ってたので買ってみました。495円。



ブレッドボードのセットによく付属してくる固いジャンパ線は、長いのばかりがやたら余ってしまいますが、これはまさに不足しがちがな短いものの詰め合わせです。いつも抵抗などのリード線の切れ端を曲げて作っていたのですが、ラクをしたいのが人間というものです。で、使ってみたのですが…いやー、品質の酷さに大笑いできます。平気で45度ぐらいねじれていて、挿す前にちゃんと修正しないと刺さらないw こういうのは機械でさくさく作っちゃうと思っていたんですが、手作業というか中国あたりで内職で作っているんじゃないだろか。

2015年2月18日水曜日

BBBにI2CでLCDつないでみた

BBBも混雑しはじめてきたw

いやー、嫌ですね、技術屋って略号ばっかりで…と言われそうなタイトルですが。とりあえず、いろいろググっていたら、シェルスクリプトだけでI2C液晶が時計になってしまう記事を見かけたので、さっそく試してみました。


まず、i2cの初期化をします。初期化について参考にさせていただいたのはこちらです。
記事はRev.A5AでうちのはRev.Cなのが原因かどうか、少しパラメータなどが違っていました。

まず、P8-17/18ピンのi2c端子I2C1を有効にしますが、その前にポートの状態を調べておきます。

root@beaglebone:~# ls -al /sys/bus/i2c/devices/i2c-*
lrwxrwxrwx 1 root root 0 6月 22 2014 /sys/bus/i2c/devices/i2c-0 -> ../../../devices/ocp.3/44e0b000.i2c/i2c-0
lrwxrwxrwx 1 root root 0 6月 22 2014 /sys/bus/i2c/devices/i2c-1 -> ../../../devices/ocp.3/4819c000.i2c/i2c-1
root@beaglebone:~#
view raw gistfile1.txt hosted with ❤ by GitHub

つぎに、ポートを初期化します。
echo BB-I2C1 > /sys/devices/bone_capemgr.9/slots
もう一度ポートの状態を確認します。

root@beaglebone:~# ls -al /sys/bus/i2c/devices/i2c-*
lrwxrwxrwx 1 root root 0 6月 24 2014 /sys/bus/i2c/devices/i2c-0 -> ../../../devices/ocp.3/44e0b000.i2c/i2c-0
lrwxrwxrwx 1 root root 0 6月 24 2014 /sys/bus/i2c/devices/i2c-1 -> ../../../devices/ocp.3/4819c000.i2c/i2c-1
lrwxrwxrwx 1 root root 0 2月 18 23:00 /sys/bus/i2c/devices/i2c-2 -> ../../../devices/ocp.3/4802a000.i2c/i2c-2
root@beaglebone:~#
view raw gistfile1.txt hosted with ❤ by GitHub

良いようです。はい。ここで注意。配線したのはI2C1ですが、今設定して変化したのはi2c-2って書いてある行です。上の記事によれば、1と2の番号とデバイスが入れ替わっているのだとか。よーわからんのですが、Beagleboneにはこういう要素が多いような気がします。ともかく、先人のおかげでハマらないですみました。ありがとうございます。

というわけで、秋月の液晶「 I2C接続小型LCDモジュールピッチ変換キット」をBeagleboneと接続します。GND, 3.3V、あとは10kΩでプルアップしたSDAとSCL。基本これだけでいいのですが、RESET端子を3.3Vにつないでおきます。オープンにしたままだとリセットされないことがあるので。

接続したら、確認します。

root@beaglebone:~# i2cdetect -y -r 2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3e --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@beaglebone:~#
view raw gistfile1.txt hosted with ❤ by GitHub

液晶のデバイス番号3eが見えますね。秋月の資料には「スレーブアドレスは、0x7Cです」と書いてありますが、これはread/writeビットを最下位に置いて読んでいるためです。これ、メーカーなどによって読み方 / 指定の仕方が違うので悩むんですよね…。ともかくBBBでは3eです。

では、今度はBeagleBone Black のハードウェアハック(5)を参考にしてデジタル時計を動かしてみます。viでコードをコピペするのですが、記事とはi2csetのパス(i2cset=/usr/sbin/i2ctest)と接続しているポート(bus=2)が異なるのでそこは書き換えたのですが…記事の通りでは真っ黒い四角が並ぶだけでした。上記秋月の資料と比較してみると、コントラスト設定値として0x3fが指定されてて液晶が真っ黒になってしまうのと、意味はわからないですがICONってのがOFFになっていること、が原因のようでした。秋月の資料と同じデータ順にして、ばっちり動きました。

#!/bin/bash
i2cset=/usr/sbin/i2cset
bus=2
chip=0x3e
LANG=C
# initialize LCD display
$i2cset -y $bus $chip 0 0x38 0x39 0x14 0x70 0x56 0x6c i
sleep 0.5
$i2cset -y $bus $chip 0 0x38 0x0c 0x01 i
sleep 0.5
while true ; do
MSG=`date +"%X" | perl -pe '$_=join" ",map{ord }split//'`
$i2cset -y $bus $chip 0 0x01
$i2cset -y $bus $chip 0x40 $MSG i
sleep 1
done
view raw gistfile1.txt hosted with ❤ by GitHub

スクリプトでこんなことできちゃうんですね。すげー。

改めて、初期化とスクリプト時計の執筆者の方々に感謝申し上げます。おかげさまで今夜はすっきりぐっすり眠れそうです。

ありがとうございました。

Emberjs:定数のロードはload/loadManyじゃなくてpush/pushMany

最近のマイブームはドップラーレーダーw

Ember.jsのFixturesを使えばRESTサーバが動いていなくてもRESTで取ってくるのと同じ形式のデータを予め用意することができるので、Webデザイナとサーバサイドがいい感じで同時並行して作業ができます。

が。

Fixture AdapterはREST Adapterと共存することができません。例えば、「他の処理/データはすべてRESTで取ってくるけど都道府県を定数配列として置いておきたい」というような場合に「都道府県だけFixtureであとはREST」というワザは使えません。

そういう場合には、REST Adaptetを指定しておいてDS.Storeに定数配列を置きます。困ったときのStackOverflowさんにも出ています。
ってか、あちこちググっても、みんなload/loadManyを使えって書いてあります。

でも、使えませんorz 最初、Ember.jsの公式ページ(Ember.js - DS.Store)の一番下にあるリストで「Deprecated」をチェックしてみたのですが、load/loadManyのことは出てきません。それから迷走しまくり探しまくりだったのですが…結局、push / pushManyを使えば同じことができると判明しました。

App.Store = DS.Store.extend({
init: function() {
this._super();
this.pushMany(App.Post, [{
id: 1,
text: 'Initial post.'
},{
id: 2,
text: 'Second post.'
}]);
}
});
App.Post = DS.Model.extend({
text: DS.attr('string')
});
view raw gistfile1.js hosted with ❤ by GitHub

なお、こうやっておいといたデータは、コントローラの中で this.store.all('model名');って書けば取り出すことができます。これで良くある「都道府県プルダウンメニュー」が作れますw こんなものまでRESTで取ってたらキリないし。

Ember.js本体は最近落ち着いてきたんですが、Ember-Data.jsについては、まだβだといえばそれまでなんですが、こういうundocumented(いや、どこかに書いてあるのかもしれませんが)な変更が多くて困ります。どこかの「俺様がEmberを使わない理由」っていうページにも書いてあったんですが、ドキュメントが古かったり矛盾してたりするんですよね。

せめてわかったことだけでも貢献したいけど英語力がないので、とりあえず自分のブログに書いておきます。

2015年2月11日水曜日

Beaglebone black(bonescript)からメールを送る

サランラップ+お湯で柔らかくなるプラスチックによる雑な仕事w

まず、SMTPサーバを入れてその設定、次にBoneScriptを書く。

SMTPサーバの入れ方はこちら。とても参考になりました、ありがとうございます。
記事との相違点はMacではなくBeagleboneなので「brew/aptitudeの替わりに apt-get を使う」ことと、設定ファイルの中身です。蛇足ですが、fromとuserは同じでOKです。設定したら記事にあるように、テストしてみてください。

で、BoneScriptで書いてみます。Node.jsから直接SMTPを呼び出せるmailなどのモジュールも試してみたのですが、エラーの山を解決することができなかったので、child processとして呼び出す方式にしました。

var b = require('bonescript');
var exec = require('child_process').exec, child;
var fs = require('fs');
var filename = '/root/test.msg';
function sendMessage(to, subject, message) {
// create message file
var msg = 'To: ' + to + '\n' + 'Subject: ' + subject + '\n' + message + '\n';
fs.writeFileSync(filename, msg);
// send it
child = exec('msmtp -t < ' + filename, function(error, stdout, stderr) {
if (stdout != null) console.log('stdout:' + stdout);
if (error != null) {
if (stderr != null) console.log('stderr:' + stderr);
console.log(error);
}
});
}
sendMessage('mail@example.com', 'this is subject', 'たれぱんだはとてつもなくかわいい');
view raw gistfile1.js hosted with ❤ by GitHub



メール系のテストをするとこうなるよねw

さて。

この度、玄関にもPIRセンサーを取り付けました。恐ろしいことに15mのワイヤ(余ってた6芯の電話線)による有線接続ですw センサーをほどよくナナメに固定するのは結構難しいのですが、玩具として売られているお湯で柔らかくなるプラスチックを使いました。80度のお湯に3分ほどつけておくと練り消しゴム状態になり、好きな形に成型してから冷します。プラスチックというよりもスーパーゴムのような素材なので、パッキングがわりに使ったり、断線しやすいiPhoneコネクタの補強、壊れた自転車用パーツの補修などに使えると思います。これでまた3Dプリンタの購入が遠ざかってしまいました(笑)。

これだけ入って1080円

なお、お湯を保温性のあるカップにいれて作業場所まで持っていくのがコツです。PIRセンサーを覆うように形を作っておき、反対側を冷たいドアに押し付けると丁度いい角度に調整することができます。私は面倒くさいので養生テープで止めちゃいましたが、プラスチックの中に磁石埋め込めばそのまま固定できると思います。電子工作において、「ナナメ固定」は結構鬼門ですが、これはホントに便利です。安いし。

養生テーブが泣かせます
先日の「自室での人間の動きを記録するアプリ」をちょっと改造して、来客を検知したらメールを送るようにしてみました。

これで留守番中に間違ってドアチェーンをかけてしまって外出中のヨメを締め出してしまっても大丈夫だ(ごめん)。

うちは宅配便ぐらいしか来ない&廊下の端で他の住民が通らないから通知ごとに送るようにしていますが、人通りの多いところでは一度送ったら数分間は検出しても送らない、などの工夫が必要かもしれないですね。
// Read PIR, Write csv, Push to ShowSensor
//
// 2015-02-11 : add function : send email when out door sensor detect a visitor
//
var b = require('bonescript');
var fs = require('fs');
var http = require('http');
var exec = require('child_process').exec, child; // for mail
var mailfile = '/root/sendmail.msg'; // for mail
var useLED = true;
var LED = 'USR3';
var pirInRoom = 'P8_19';
var pirOutDoor = 'P8_18';
b.pinMode(pirInRoom, b.INPUT);
b.pinMode(pirOutDoor, b.INPUT);
setInterval(readStatus, 100); // Checks the Sensor Every 0.1 Seconds
var limitCurrentHour = 12;
var limitPrevHour = limitCurrentHour -1;
var filename = null;
var isStart = false;
var countInRoom = 0;
var countOutDoow = 0;
var prevMinute = 99;
var prevHour = 99;
function readStatus() {
var outDoor = b.digitalRead(pirOutDoor);
var inRoom = b.digitalRead(pirInRoom);
var tokei = new Date();
var sec = tokei.getSeconds();
var min = tokei.getMinutes();
var hour = tokei.getHours();
var day = tokei.getHours();
if (min != prevMinute) {
if (prevHour == 99) prevHour = hour;
if (prevMinute == 99) {
if (sec == 0) {
prevMinute = min;
}
} else {
if (filename == null) {
var tempTokei = tokei;
if (hour <= limitPrevHour) {
tempTokei.setTime(tokei.getTime() - 24*3600*1000);
}
filename = getStrFilename(tempTokei);
// filename = '/root/' + formatDate(tempTokei, "YYYY-MM-DD") + '.txt';
// console.log("filename=" + filename);
}
if (prevHour == limitCurrentHour-1 && hour == limitCurrentHour) {
filename = getStrFilename(tokei);
// filename = '/root/' + formatDate(tokei, "YYYY-MM-DD") + '.txt';
// console.log("filename=" + filename);
}
var sDate = formatDate(tokei, "YYYY-MM-DD hh:mm");
var sInRoom = Math.round(countInRoom /10);
var sOutDoor = Math.round(countOutDoor/10);
var s = sDate + "," + sInRoom + "," + sOutDoor;
fs.appendFile(filename, s + "\n", function(err) {
if (err) console.log(err);
});
// http://stackoverflow.com/questions/4505809/how-to-post-to-a-request-using-node-js
var body = JSON.stringify({
date: sDate,
count: sInRoom,
outdoor: sOutDoor,
email: "mail@example.com"
});
console.log(body);
try {
pushData(body);
if (sOutDoor > 10) {
sendMessage('mail@example.com', '来客?', 'カウント=' + sOutDoor);
}
} catch(e) {
console.log(body);
}
prevMinute = min;
}
prevHour = hour;
countInRoom = countOutDoor = 0;
}
if (inRoom == 0) { // detected
countInRoom ++;
}
if (outDoor == 1) {
countOutDoor ++;
}
if (useLED) b.digitalWrite(LED, outDoor);
}
function pushData(inBody) {
var request = new http.ClientRequest({
// hostname: "192.168.0.70",
hostname: "infinite-reaches-8771.herokuapp.com",
port: 80,
path: "/receive",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(inBody)
}
});
request.on('response', function (response) {
response.on('data', function (chunk) {
});
response.on('error', function (chunk) {
console.log('BODY: ' + chunk);
});
});
request.write(inBody);
request.end();
}
function getStrFilename(x) {
var str = '/root/' + formatDate(x, "YYYY-MM-DD") + '.txt';
console.log("filename=" + str);
return str;
}
function sendMessage(to, subject, message) {
// create message file
var msg = 'To: ' + to + '\n' + 'Subject: ' + subject + '\n' + message + '\n';
fs.writeFileSync(mailfile, msg);
// send it
child = exec('msmtp -t < ' + mailfile, function(error, stdout, stderr) {
if (stdout != null) console.log('stdout:' + stdout);
if (error != null) {
if (stderr != null) console.log('stderr:' + stderr);
console.log(error);
}
});
}
// http://qiita.com/osakanafish/items/c64fe8a34e7221e811d0
/**
* 日付をフォーマットする
* @param {Date} date 日付
* @param {String} [format] フォーマット
* @return {String} フォーマット済み日付
*/
var formatDate = function (date, format) {
if (!format) format = 'YYYY-MM-DD hh:mm:ss.SSS';
format = format.replace(/YYYY/g, date.getFullYear());
format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2));
format = format.replace(/DD/g, ('0' + date.getDate()).slice(-2));
format = format.replace(/hh/g, ('0' + date.getHours()).slice(-2));
format = format.replace(/mm/g, ('0' + date.getMinutes()).slice(-2));
format = format.replace(/ss/g, ('0' + date.getSeconds()).slice(-2));
if (format.match(/S/g)) {
var milliSeconds = ('00' + date.getMilliseconds()).slice(-3);
var length = format.match(/S/g).length;
for (var i = 0; i < length; i++) format = format.replace(/S/, milliSeconds.substring(i, i + 1));
}
return format;
};
view raw gistfile1.js hosted with ❤ by GitHub


2015年2月1日日曜日

自家製キット?


買ってきた部品、特にICは一度試しておきたいものです。今回、TO92パッケージで外付け部品4つで簡単に0.9vから5vまで昇圧できるHT7750Aを使って赤外線リモコン受光器を動かしてみました。

もろもろの事情によりバラすことになったのですが、こういう場合、捨てるのは論外としても元の新品部品沼に戻すのも気が引けます。

そこで、こういう汎用性のあるパーツは秋月のチャック袋に入れてメモを添えておくと部品のピックアップが楽になります。

…なんかおバアチャンの知恵、みたいなネタだな。