Arduinoでモーションセンサを使ってみる [Arduino]
Arduinoでモーションセンサを使ってみる.
使ったのは,Panasonicの焦電型赤外線センサのうち,NaPiOn (ナピオン) シリーズのAMN31112だ.
このセンサは,電源とGNDと出力ピンしかないので,接続も簡単だ.
Arduinoとの接続はこんな感じ.
出力ピンをプルダウンしなければいけないというのが唯一の注意点.
Arduinoのスケッチはこんな感じ.
これでモーションセンサが人体検出したら,Arduino上のLEDが点灯する.
モーションセンサ側がいろいろやってくれるので,Arduino側からは単に出力を見るだけでOK.
とても簡単だ.
お試しあれ.
使ったのは,Panasonicの焦電型赤外線センサのうち,NaPiOn (ナピオン) シリーズのAMN31112だ.
このセンサは,電源とGNDと出力ピンしかないので,接続も簡単だ.
Arduinoとの接続はこんな感じ.
出力ピンをプルダウンしなければいけないというのが唯一の注意点.
Arduinoのスケッチはこんな感じ.
const int LED = 13; const int PIR = 2; void setup() { pinMode(LED, OUTPUT); pinMode(PIR, INPUT); } void loop() { if (digitalRead(PIR) == HIGH) { digitalWrite(LED, HIGH); } else { digitalWrite(LED, LOW); } delay(200); }
これでモーションセンサが人体検出したら,Arduino上のLEDが点灯する.
モーションセンサ側がいろいろやってくれるので,Arduino側からは単に出力を見るだけでOK.
とても簡単だ.
お試しあれ.
タグ:モーションセンサ
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での開発はこんな感じ.
参考にしたのは,公式の,「Getting Started for C/C++ (Eclipse) - Galileo & Edison」だ.
コードは,スクリーンショットをみれば分かるが,一応ここにも記載しておく.
Eclipseからはリモートデバッグも可能なようだ.
それにしてもArduino IDEからの制御も楽だが,mraaも楽だな...
お試しあれ.
回路図は以前と同じ.
なお,Arduino IDEでいう13番ピンは,EdisonモジュールのGP40ピンだが,mraaでは別途ピン番号が管理されていて,mraa numberは37になる.ちなみに,情報は「mraa/edison.md at master · intel-iot-devkit/mraa · GitHub」にある.
今回はEclipseを使ってクロスビルドして試してみた.Eclipseでの開発はこんな感じ.
参考にしたのは,公式の,「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
Edisonに照度センサをつないでみる [edison]
前回,Arduinoに照度センサをつないでみたが,今回はEdisonにつないでみる.
EdisonはIntel Edison Breakout Boardを使っているので,IOは1.8Vだ.arduinoのときは5Vだったが今回は1.8Vだ.だけど,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続するってのは変わらない.
接続はこんな感じ.
当初はこんな感じで接続していたが,Kさんからコメントいただいたように,AE-PCA9306ではVref2側を高電圧側にするべきである.
なので,こちらの回路図のように接続すべきである.
今回も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だ.
お試しあれ.
EdisonはIntel Edison Breakout Boardを使っているので,IOは1.8Vだ.arduinoのときは5Vだったが今回は1.8Vだ.だけど,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続するってのは変わらない.
接続はこんな感じ.
当初はこんな感じで接続していたが,Kさんからコメントいただいたように,AE-PCA9306ではVref2側を高電圧側にするべきである.
なので,こちらの回路図のように接続すべきである.
今回も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側だけレベル変換モジュールのプルアップを無効にして,照度センサ側は(センサ側でプルアップしてないので)レベル変換モジュールのプルアップは有効のままにしておく.
上記の回路図のように接続しているので,カットするジャンパは,
で,これで試したら無事通信できた.Arduinoで試したときと同じように動いたのでOKだ.
お試しあれ.
タグ:内蔵プルアップ
Arduinoに照度センサをつないでみる [Arduino]
手元のジャンクにI2C接続の照度センサがあったのでArduinoにつないでみた.
照度センサは,ROHMのBH1751FVI.I2Cで制御するタイプだ.
で,ArduinoとはIOの電圧が違うので直結できない.なので,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続してやる.
こんな感じ.
間にI2Cのレベル変換を挟んでいるだけで,基本的には素直に接続なので悩むことはないと思う.
で,Arduino側のスケッチはこんな感じ.
簡単すぎる.これでシリアルに照度値が出力されるようになる.
Arduinoってなにかちょっと試すのにホント便利だなぁ.
照度センサは,ROHMのBH1751FVI.I2Cで制御するタイプだ.
で,ArduinoとはIOの電圧が違うので直結できない.なので,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続してやる.
こんな感じ.
間にI2Cのレベル変換を挟んでいるだけで,基本的には素直に接続なので悩むことはないと思う.
で,Arduino側のスケッチはこんな感じ.
#include <Wire.h> const int SensorAddress = 0x23; const int CommandHResolutionSingle = 0x20; const int ReadDataNum = 2; void setup() { Wire.begin(); Serial.begin(9600); } void loop() { Wire.beginTransmission(SensorAddress); Wire.write(CommandHResolutionSingle); Wire.endTransmission(); Wire.requestFrom(SensorAddress, ReadDataNum); while (Wire.available() < ReadDataNum); unsigned int h = Wire.read(); unsigned int l = Wire.read(); double lx = convertSensorDataToLx(h, l); Serial.println(lx); delay(500); } double convertSensorDataToLx(unsigned int high, unsigned int lo) { double result = (high * 256u + lo) / 1.2; return result; }
簡単すぎる.これでシリアルに照度値が出力されるようになる.
Arduinoってなにかちょっと試すのにホント便利だなぁ.
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ビット双方向ロジックレベル変換モジュール」を使う.
で,こんな感じに接続.
これで試したら,LEDの点滅が無事確認できた.
さて,次は何に手を出そうか...
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ビット双方向ロジックレベル変換モジュール」を使う.
で,こんな感じに接続.
これで試したら,LEDの点滅が無事確認できた.
さて,次は何に手を出そうか...
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
「スルーホールに挿し込むだけで信号の入力やチェックができます」とのことで,半田付けせずに試せる.ただ,Breakout Boardに思いっきり挿すとEdison本体のシールドに接触するかもしれないので,何らかの絶縁はした方が良さそうである.とりあえずうちでは紙を挟んである.
で,実は10月末には入手済みだったのだが,最近やっといじり始めている.
とりあえず,最新のFWにアップデートして,WiFi設定なんかまではやってみた.この辺の作業内容は本家含めネット上にたくさん情報があるのでそれを参考に.
それにしても小さい.以前,BeagleBoard-xMを入手したときにも「小さいなぁ」と感じたけど,これはもっと小さい.
Raspberry Piだって十分小さいけど,それよりも小さい.しかもパワフル.
さて,とりあえず次回はLチカやってみよう.
「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
「スルーホールに挿し込むだけで信号の入力やチェックができます」とのことで,半田付けせずに試せる.ただ,Breakout Boardに思いっきり挿すとEdison本体のシールドに接触するかもしれないので,何らかの絶縁はした方が良さそうである.とりあえずうちでは紙を挟んである.
で,実は10月末には入手済みだったのだが,最近やっといじり始めている.
とりあえず,最新のFWにアップデートして,WiFi設定なんかまではやってみた.この辺の作業内容は本家含めネット上にたくさん情報があるのでそれを参考に.
それにしても小さい.以前,BeagleBoard-xMを入手したときにも「小さいなぁ」と感じたけど,これはもっと小さい.
Raspberry Piだって十分小さいけど,それよりも小さい.しかもパワフル.
さて,とりあえず次回はLチカやってみよう.
秋月電子のATmega168/328マイコンボードキットを組み立ててみる [Arduino]
Arduino 互換ボードになるATmega168/328マイコンボードキットを組み立ててみた.AE-ATmegaというやつだ.
組み立ては難しくなくて,説明書の順番通り半田付けしていけばOK.
ただ,USBシリアル変換モジュール(AE-UM232R)は使い回したいので直接半田付けはしなかった.本当はICソケットを使うのがいいんだろうけど,手元になかったのでやむなくピンソケットをつけてみた.
なので,USBシリアル変換のところだけやたら高さが高くなってしまった.
で,組み立てが終わったらArduino化するためにブートローダーを書き込む.
ネットで調べると,ブートローダーの書き込みはいくつかの方法があるようだが,手元にあるArduino UNOを使って書き込むことができるようなので,それを試してみた.ArduinoISPと呼ぶようである.
方法は,本家「Arduino - ArduinoISP」,もしくはその日本語訳サイト「Arduino を AVR プログラマ(ISP: In-System Programmer)として使う」に情報がある.
で,接続はこんな感じでOK.
あとは書き込み手順通りに進める.
ターゲットボードは,AE-Atmegaはないので,「Arduino Diecimila or Duemilanove w/ ATmega168」を選択する.
で,書き込むのだが,残念ながらこの方法では書き込めない.
こんなエラーが出る.
調べてみると,どうやら「Arduino Diecimila or Duemilanove w/ ATmega168」はATmega168なのだが,AE-ATmegaに載っているのはATmega168Pなので,チェックで引っかかるようだ.
というわけで,このままではブートローダーを書き込めないので,なんとかATmega168として認識されるようにごまかしてみた.
以下のやり方はMac環境化での話になるが,ほかの環境でも同様のことができると思う.
では,方法だが,とても簡単.
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/下にある,avrdude.confを編集する.
で,編集する部分を一部抜粋したのが以下.
このうち,
つまり,
これで書き込める.
書き込みが終わったら変更を元に戻しておくことを忘れずに.
ここまできたら,もう普通にArduinoとして使える.
サンプルスケッチを書き込んでみて,動作を確認してみたが,問題なく動作した.
お試しあれ.
組み立ては難しくなくて,説明書の順番通り半田付けしていけばOK.
ただ,USBシリアル変換モジュール(AE-UM232R)は使い回したいので直接半田付けはしなかった.本当はICソケットを使うのがいいんだろうけど,手元になかったのでやむなくピンソケットをつけてみた.
なので,USBシリアル変換のところだけやたら高さが高くなってしまった.
で,組み立てが終わったらArduino化するためにブートローダーを書き込む.
ネットで調べると,ブートローダーの書き込みはいくつかの方法があるようだが,手元にあるArduino UNOを使って書き込むことができるようなので,それを試してみた.ArduinoISPと呼ぶようである.
方法は,本家「Arduino - ArduinoISP」,もしくはその日本語訳サイト「Arduino を AVR プログラマ(ISP: In-System Programmer)として使う」に情報がある.
で,接続はこんな感じでOK.
あとは書き込み手順通りに進める.
ターゲットボードは,AE-Atmegaはないので,「Arduino Diecimila or Duemilanove w/ ATmega168」を選択する.
で,書き込むのだが,残念ながらこの方法では書き込めない.
こんなエラーが出る.
avrdude: Expected signature for ATMEGA168 is 1E 94 06 Double check chip, or use -F to override this check.
調べてみると,どうやら「Arduino Diecimila or Duemilanove w/ ATmega168」はATmega168なのだが,AE-ATmegaに載っているのはATmega168Pなので,チェックで引っかかるようだ.
というわけで,このままではブートローダーを書き込めないので,なんとかATmega168として認識されるようにごまかしてみた.
以下のやり方はMac環境化での話になるが,ほかの環境でも同様のことができると思う.
では,方法だが,とても簡単.
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/下にある,avrdude.confを編集する.
で,編集する部分を一部抜粋したのが以下.
#------------------------------------------------------------ # ATmega168 #------------------------------------------------------------ part id = "m168"; desc = "ATMEGA168"; has_debugwire = yes; flash_instr = 0xB6, 0x01, 0x11; eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, 0x99, 0xF9, 0xBB, 0xAF; stk500_devcode = 0x86; # avr910_devcode = 0x; signature = 0x1e 0x94 0x06;
このうち,
を168P用に一時的に変更する.signature = 0x1e 0x94 0x06;
つまり,
にしてやる.signature = 0x1e 0x94 0x0b;
これで書き込める.
書き込みが終わったら変更を元に戻しておくことを忘れずに.
ここまできたら,もう普通にArduinoとして使える.
サンプルスケッチを書き込んでみて,動作を確認してみたが,問題なく動作した.
お試しあれ.
タグ:AE-ATmega
ov7670+Arduino+ProcessingでTimelapseをやってみる [Arduino]
長らく放置していたCMOSカメラのov7670だが,とりあえず,秋月電子通商のArduino用ユニバーサル基板に組んでみた.
こんな感じ.
で,Arduino側は前はQQVGAだったけど,VGAで画像取得できるようにして,あとProcessingで画像表示用にこんなの作ってみた.
これで画像を保存できるようにしたので,画像を撮りまくってTimelapseをやってみた.
その動画がこれ.同じような動画ばっかりだけど...
かなり簡単にできた.Processingが画像を動画にしてくれるので楽だ.
ArduinoとProcessingのコードはかなり適当な作りなので,もし要望があったら公開しようと思う.
2015.05.30追記
ArduinoとProcessingのコードはこちら.
久しぶりにov7670+Arduino+Processingを動かしてみる
お試しあれ.
こんな感じ.
で,Arduino側は前はQQVGAだったけど,VGAで画像取得できるようにして,あとProcessingで画像表示用にこんなの作ってみた.
これで画像を保存できるようにしたので,画像を撮りまくってTimelapseをやってみた.
その動画がこれ.同じような動画ばっかりだけど...
かなり簡単にできた.Processingが画像を動画にしてくれるので楽だ.
ArduinoとProcessingのコードはかなり適当な作りなので,もし要望があったら公開しようと思う.
2015.05.30追記
ArduinoとProcessingのコードはこちら.
久しぶりにov7670+Arduino+Processingを動かしてみる
お試しあれ.
タグ:TIMELAPSE
RaspbmcにFMトランスミッターをつないでみる [Raspberry Pi]
普段,音楽を聴くときはRaspberry PiにインストールしたXBMC(Raspbmc)を使っていて,TVとはHDMIでつないでいる.
普段はそれでいいんだけど,うちではたまにベランダでご飯を食べるときがあって,そのときにも音楽が聞きたい.だけどTVからの音声をベランダで聞くのは難しい.
ということで,Raspbmcの音をFMトランスミッターで飛ばして,ベランダではFMラジオを通して音楽を聴くというのを試してみた.
で,まずはFMトランスミッター.
秋月のFMステレオ・トランスミッタキットを買ってみた.通販コード K-00086のやつで,NJM2035Dが載っている.1000円.秋月には4800円の新潟精密製FM送信モジュールNS73Mが載ったやつもあるのだが,とりあえず安い方を買ってみた.
組み立てはそんなに難しくない.説明書の通りに半田付けしていけばいい.小型コンデンサマイクが付属してくるけど,うちではまず使いそうもないので取り付けなかった.
3.5mmのステレオプラグと電源ON/OFF用のスイッチを取り付けて,無事完成.
こんな感じ.
アンテナには,先がBNCになってるケーブルをつないだ.そこからアンテナをつなごうと思ったんだけど,つないでもつながなくても電波の飛びがあまり変わらなかったので,BNCケーブルを引き出しただけで終わってる.
ま,そもそもRaspberry Piがある場所からベランダまで電波が飛べば十分なのと,使ってるFMラジオがソニーの手回しラジオICF-B03というやつなので,音質は気にしてない.聴ければいいというレベル.ちゃんと聴く人はアンテナとか気にした方がいいと思うけど,そもそもそういう人はこの1000円のじゃなくて4800円の方を買った方がいいかもしれない.
しかも,ネットで調べると,全然電波が飛ばないという人と,10mぐらい飛ぶって人といろいろ情報があるみたい.旧バージョンはよく飛んだけど今のはそれなりとかいう情報もあるし,よくわからない.
うちでは,確かに設置場所とかちょっとしたケーブルの取り回しで様子が変わったりしたので,かなりデリケートなのかもしれない.
で,Raspbmc側.
通常は,システム -> 設定 -> システム -> オーディオハードウェアでオーディオ出力デバイスをHDMIかAnalogueを選択するようになっているのだが,Raspbmcの設定画面で設定レベルを変更すると「Dual audio output」を選択できるようになる.なので,この「Dual audio output」を選択する.
が,しかし,これを選択してもHDMIとアナログの両方から出力はされない.
で,調べてみると,どうやら,Raspbmcではaudio playerとしてデフォルトはPAPlayerというのが使われているらしいのだが,これは「Dual audio output」に対応しておらず,OMXPlayerを使う必要があるらしい.
というわけでデフォルトのaudio playerをOMXPlayerに変更してみる.
変更するには,raspbmc上の/home/pi/.xbmc/userdata/下にadvancedsettings.xmlファイルを作ってやる.そしてadvancedsettings.xmlファイルに以下のように記述してやる.
これでOK.HDMIとアナログの両方から出力されるはずだ.
お試しあれ.
普段はそれでいいんだけど,うちではたまにベランダでご飯を食べるときがあって,そのときにも音楽が聞きたい.だけどTVからの音声をベランダで聞くのは難しい.
ということで,Raspbmcの音をFMトランスミッターで飛ばして,ベランダではFMラジオを通して音楽を聴くというのを試してみた.
で,まずはFMトランスミッター.
秋月のFMステレオ・トランスミッタキットを買ってみた.通販コード K-00086のやつで,NJM2035Dが載っている.1000円.秋月には4800円の新潟精密製FM送信モジュールNS73Mが載ったやつもあるのだが,とりあえず安い方を買ってみた.
組み立てはそんなに難しくない.説明書の通りに半田付けしていけばいい.小型コンデンサマイクが付属してくるけど,うちではまず使いそうもないので取り付けなかった.
3.5mmのステレオプラグと電源ON/OFF用のスイッチを取り付けて,無事完成.
こんな感じ.
アンテナには,先がBNCになってるケーブルをつないだ.そこからアンテナをつなごうと思ったんだけど,つないでもつながなくても電波の飛びがあまり変わらなかったので,BNCケーブルを引き出しただけで終わってる.
ま,そもそもRaspberry Piがある場所からベランダまで電波が飛べば十分なのと,使ってるFMラジオがソニーの手回しラジオICF-B03というやつなので,音質は気にしてない.聴ければいいというレベル.ちゃんと聴く人はアンテナとか気にした方がいいと思うけど,そもそもそういう人はこの1000円のじゃなくて4800円の方を買った方がいいかもしれない.
しかも,ネットで調べると,全然電波が飛ばないという人と,10mぐらい飛ぶって人といろいろ情報があるみたい.旧バージョンはよく飛んだけど今のはそれなりとかいう情報もあるし,よくわからない.
うちでは,確かに設置場所とかちょっとしたケーブルの取り回しで様子が変わったりしたので,かなりデリケートなのかもしれない.
で,Raspbmc側.
通常は,システム -> 設定 -> システム -> オーディオハードウェアでオーディオ出力デバイスをHDMIかAnalogueを選択するようになっているのだが,Raspbmcの設定画面で設定レベルを変更すると「Dual audio output」を選択できるようになる.なので,この「Dual audio output」を選択する.
が,しかし,これを選択してもHDMIとアナログの両方から出力はされない.
で,調べてみると,どうやら,Raspbmcではaudio playerとしてデフォルトはPAPlayerというのが使われているらしいのだが,これは「Dual audio output」に対応しておらず,OMXPlayerを使う必要があるらしい.
というわけでデフォルトのaudio playerをOMXPlayerに変更してみる.
変更するには,raspbmc上の/home/pi/.xbmc/userdata/下にadvancedsettings.xmlファイルを作ってやる.そしてadvancedsettings.xmlファイルに以下のように記述してやる.
<advancedsettings> <audio> <defaultplayer>omxplayer</defaultplayer> </audio> </advancedsettings>
これでOK.HDMIとアナログの両方から出力されるはずだ.
お試しあれ.
タグ:FMトランスミッター
ArduinoでCMOSカメラの画像を取得してみる [Arduino]
先日,ArduinoとCMOSカメラを接続して動かしてみたので,いよいよ画像を取得してみる.
というわけで,早速だがArduinoのスケッチを示そう.
ファイルは2つあって,ov7670.inoとov7670reg.hだ.
まずはov7670.ino
次にov7670reg.h
これをArduinoに書き込めばOK.
いろいろwebで調べて,とりあえずQQVGAのRGB444で画像取得する例がいくつか見つかったので,それで試してる.
使い方は,シリアルモニタを開いて,
sを入力すると撮影,dで画像データのダンプが行われる.hで簡単なヘルプ(というほどのものでもないが)が表示される.なので,まぁスケッチを見ながらいろいろ試してみてくださいな.
画像データは,QQVGAのRGB444で動かしているので,ダンプすると160x120=19200画素のデータが,1画素あたり2バイト出力される.なので,トータルとしては38400バイトになる.
データの並びは,xBGRで出力される.なお,160画素ごとに改行を入れて出力される.改行を除去すると,1バイトあたり2文字でダンプされるので,結果として,76800文字のデータが得られることになる.
さて,データだけあってもつまらないので,Processingで画像を表示してみる.
Processingのコードは,こんな感じ.
ダンプしたデータは,captureData.txtとしてProcessingのコードと同じディレクトリに保存してくださいな.
で,表示されるサンプル画像はこんな感じ.
ま,QQVGなのと,RGB各色4ビットしかないので,画質はそれなりですな.
あと,水平方向の位相がちょっとずれてるようなのと,電源投入一発目の画像がおかしいことがあるんだけど...
ま,お試しあれ.
参考サイト
いっぱいあって,いっぱい参考にした.特に以下の2つを参考にしたけど,ほかにもGoogleでov7670で検索してヒットするサイトは軒並みチェックした.先人に感謝.
トラ技 頒布カメラB(OV7670 FIFO AL422B)の動作確認 | mbed
HR2_blog: mbedでトラ技3月号の頒布カメラBを使う
2014.12.15追記
サンプル画像の元データ(captureData.txt)はこんな感じ.captureData.txt.zip.jpg
So-netのブログはテキストファイルのアップロードができないので,ZIP圧縮して,拡張子に.jpgをつけて無理矢理アップロードしてる.なので,ダウンロードしたら.jpgを消してZIPファイルとして展開してくださいな.
というわけで,早速だがArduinoのスケッチを示そう.
ファイルは2つあって,ov7670.inoとov7670reg.hだ.
まずはov7670.ino
#include <Wire.h> #include "ov7670reg.h" // Pin const int WEN = 14; // PC0 const int RRST = 15; // PC1 const int OE = 16; // PC2 const int RCLK = 17; // PC3 const int VSYNC = 2; // PD2 INT0 const int D0 = 8; // PB0 const int D1 = 9; // PB1 const int D2 = 10; // PB2 const int D3 = 11; // PB3 const int D4 = 4; // PD4 const int D5 = 5; // PD5 const int D6 = 6; // PD6 const int D7 = 7; // PD7 boolean isWriteEnable = false; void setPinMode() { pinMode(WEN, OUTPUT); pinMode(RRST, OUTPUT); pinMode(OE, OUTPUT); pinMode(RCLK, OUTPUT); pinMode(D0, INPUT ); pinMode(D1, INPUT ); pinMode(D2, INPUT ); pinMode(D3, INPUT ); pinMode(D4, INPUT ); pinMode(D5, INPUT ); pinMode(D6, INPUT ); pinMode(D7, INPUT ); attachInterrupt(0, setWriteEnable, FALLING); digitalWrite(WEN, LOW); digitalWrite(RRST, HIGH); digitalWrite(OE, HIGH); digitalWrite(RCLK, HIGH); } void setWriteEnable() { if (isWriteEnable) { digitalWrite(WEN, HIGH); isWriteEnable = false; } else { digitalWrite(WEN, LOW); } } void initFifo() { digitalWrite(RCLK, HIGH); digitalWrite(RRST, HIGH); digitalWrite(OE, HIGH); digitalWrite(RCLK, HIGH); digitalWrite(RRST, LOW ); digitalWrite(OE, HIGH); digitalWrite(RCLK, LOW ); digitalWrite(RRST, LOW ); digitalWrite(OE, HIGH); digitalWrite(RCLK, HIGH); digitalWrite(RRST, LOW ); digitalWrite(OE, HIGH); digitalWrite(RCLK, LOW ); digitalWrite(RRST, LOW ); digitalWrite(OE, HIGH); digitalWrite(RCLK, LOW ); digitalWrite(RRST, HIGH); digitalWrite(OE, HIGH); digitalWrite(RCLK, HIGH); digitalWrite(RRST, HIGH); digitalWrite(OE, HIGH); digitalWrite(RCLK, HIGH); digitalWrite(RRST, HIGH); digitalWrite(OE, LOW ); digitalWrite(RCLK, LOW ); digitalWrite(RRST, HIGH); digitalWrite(OE, LOW ); digitalWrite(RCLK, HIGH); digitalWrite(RRST, HIGH); digitalWrite(OE, LOW ); } void readFifo() { const int HSIZE = 160; const int VSIZE = 120; const int DATABYTE = 2; int d0, d1, d2, d3, d4, d5, d6, d7; byte data; for (int v = 0; v < VSIZE; v++) { for (int h = 0; h < HSIZE; h++) { for (int d = 0; d < DATABYTE; d++) { digitalWrite(RCLK, HIGH); d0 = digitalRead(D0); d1 = digitalRead(D1); d2 = digitalRead(D2); d3 = digitalRead(D3); d4 = digitalRead(D4); d5 = digitalRead(D5); d6 = digitalRead(D6); d7 = digitalRead(D7); data = pinLevel2Byte(d0, 0) + pinLevel2Byte(d1, 1) + pinLevel2Byte(d2, 2) + pinLevel2Byte(d3, 3) + pinLevel2Byte(d4, 4) + pinLevel2Byte(d5, 5) + pinLevel2Byte(d6, 6) + pinLevel2Byte(d7, 7); digitalWrite(RCLK, LOW); char temp[3]; snprintf(temp, sizeof(temp), "%02X", data); Serial.print(temp); } } Serial.println(""); } // read end digitalWrite(RCLK, LOW ); digitalWrite(OE, HIGH); digitalWrite(RCLK, HIGH); digitalWrite(OE, HIGH); } byte pinLevel2Byte(int level, int shift) { byte result = (level == HIGH) ? 1 : 0; return result << shift; } void writeRegister(int address, int data) { const int I2C_WRITE_ADDR = 0x42; Wire.beginTransmission(I2C_WRITE_ADDR >> 1); Wire.write(address); Wire.write(data); Wire.endTransmission(); } int readRegister(int address) { const int I2C_READ_ADDR = 0x43; Wire.beginTransmission(I2C_READ_ADDR >> 1); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(I2C_READ_ADDR >> 1, 1); return Wire.read(); } void resetCamera() { writeRegister(0x12, 0x80); delay(200); } void initRegister() { // QQVGA, RGB444 writeRegister(REG_CLKRC, 0x80); writeRegister(REG_COM11, 0x0A); writeRegister(REG_TSLB, 0x04); writeRegister(REG_COM7, 0x04); writeRegister(REG_RGB444, 0x02); writeRegister(REG_COM15, 0xD0); writeRegister(REG_HSTART, 0x16); writeRegister(REG_HSTOP, 0x04); writeRegister(REG_HREF, 0x24); writeRegister(REG_VSTART, 0x02); writeRegister(REG_VSTOP, 0x7A); writeRegister(REG_VREF, 0x0A); writeRegister(REG_COM10, 0x02); writeRegister(REG_COM3, 0x04); writeRegister(REG_COM14, 0x1A); writeRegister(0x72, 0x22); writeRegister(0x73, 0xF2); // COLOR SETTING writeRegister(0x4F, 0x80); writeRegister(0x50, 0x80); writeRegister(0x51, 0x00); writeRegister(0x52, 0x22); writeRegister(0x53, 0x5E); writeRegister(0x54, 0x80); writeRegister(0x56, 0x40); writeRegister(0x58, 0x9E); writeRegister(0x59, 0x88); writeRegister(0x5A, 0x88); writeRegister(0x5B, 0x44); writeRegister(0x5C, 0x67); writeRegister(0x5D, 0x49); writeRegister(0x5E, 0x0E); writeRegister(0x69, 0x00); writeRegister(0x6A, 0x40); writeRegister(0x6B, 0x0A); writeRegister(0x6C, 0x0A); writeRegister(0x6D, 0x55); writeRegister(0x6E, 0x11); writeRegister(0x6F, 0x9F); writeRegister(0xB0, 0x84); } void printData(int address, int data) { char temp[16]; snprintf(temp, sizeof(temp), "addr=%02X data=%02X", address, data); Serial.println(temp); } void receiveCommand(char *buff) { char c = '\0'; while (c != '\r' ) { if (Serial.available() > 0) { c = Serial.read(); Serial.print(c); *buff++ = c; } } *buff = '\0'; Serial.println(""); } void setup() { Serial.begin(115200); Wire.begin(); printMenu(); setPinMode(); resetCamera(); initRegister(); } void loop() { int address = 0; int data = 0; char buff[256]; char *buff_ptr; char *cmd_ptr; char *arg1_ptr; char *arg2_ptr; const char DELIMITTER[] = " \t"; Serial.print("> "); receiveCommand(buff); // trim white space buff_ptr = buff; while ( (*buff_ptr == ' ') || (*buff_ptr == '\t') || (*buff_ptr == '\n') ) { buff_ptr++; } cmd_ptr = strtok(buff_ptr, DELIMITTER); switch (tolower(*cmd_ptr)) { case 'w': arg1_ptr = strtok(NULL, DELIMITTER); arg2_ptr = strtok(NULL, DELIMITTER); if ( (arg1_ptr != NULL) && (arg2_ptr != NULL) ) { address = hex2dec(arg1_ptr); data = hex2dec(arg2_ptr); printData(address, data); writeRegister(address, data); delay(10); } else { Serial.println("Syntax Error"); } break; case 'r': arg1_ptr = strtok(NULL, DELIMITTER); if (arg1_ptr != NULL) { address = hex2dec(arg1_ptr); data = readRegister(address); printData(address, data); delay(50); } else { Serial.println("Syntax Error"); } break; case 'd': Serial.println("Dump"); initFifo(); readFifo(); break; case 's': Serial.println("Start"); isWriteEnable = true; break; case 'h': printHelp(); break; default: Serial.println("Syntax Error"); break; } Serial.println(""); } void printMenu() { Serial.println("------------------------------"); Serial.println(" OV7670 Camera Debugger"); Serial.println("------------------------------"); Serial.println(""); } void printHelp() { Serial.println("WRITE :w [address] [data]"); Serial.println("READ :r [address]"); Serial.println("START :s"); Serial.println("DUMP :d"); Serial.println("HELP :h"); } int hex2dec(char *str) { return strtol(str, NULL, 16); }
次にov7670reg.h
#define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ #define REG_BLUE 0x01 /* blue gain */ #define REG_RED 0x02 /* red gain */ #define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ #define REG_COM1 0x04 /* Control 1 */ #define COM1_CCIR656 0x40 /* CCIR656 enable */ #define REG_BAVE 0x05 /* U/B Average level */ #define REG_GbAVE 0x06 /* Y/Gb Average level */ #define REG_AECHH 0x07 /* AEC MS 5 bits */ #define REG_RAVE 0x08 /* V/R Average level */ #define REG_COM2 0x09 /* Control 2 */ #define COM2_SSLEEP 0x10 /* Soft sleep mode */ #define REG_PID 0x0a /* Product ID MSB */ #define REG_VER 0x0b /* Product ID LSB */ #define REG_COM3 0x0c /* Control 3 */ #define COM3_SWAP 0x40 /* Byte swap */ #define COM3_SCALEEN 0x08 /* Enable scaling */ #define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ #define REG_COM4 0x0d /* Control 4 */ #define REG_COM5 0x0e /* All "reserved" */ #define REG_COM6 0x0f /* Control 6 */ #define REG_AECH 0x10 /* More bits of AEC value */ #define REG_CLKRC 0x11 /* Clocl control */ #define CLK_EXT 0x40 /* Use external clock directly */ #define CLK_SCALE 0x3f /* Mask for internal clock scale */ #define REG_COM7 0x12 /* Control 7 */ #define COM7_RESET 0x80 /* Register reset */ #define COM7_FMT_MASK 0x38 #define COM7_FMT_VGA 0x00 #define COM7_FMT_CIF 0x20 /* CIF format */ #define COM7_FMT_QVGA 0x10 /* QVGA format */ #define COM7_FMT_QCIF 0x08 /* QCIF format */ #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ #define COM7_YUV 0x00 /* YUV */ #define COM7_BAYER 0x01 /* Bayer format */ #define COM7_PBAYER 0x05 /* "Processed bayer" */ #define REG_COM8 0x13 /* Control 8 */ #define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ #define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ #define COM8_BFILT 0x20 /* Band filter enable */ #define COM8_AGC 0x04 /* Auto gain enable */ #define COM8_AWB 0x02 /* White balance enable */ #define COM8_AEC 0x01 /* Auto exposure enable */ #define REG_COM9 0x14 /* Control 9 - gain ceiling */ #define REG_COM10 0x15 /* Control 10 */ #define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ #define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ #define COM10_HREF_REV 0x08 /* Reverse HREF */ #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ #define COM10_VS_NEG 0x02 /* VSYNC negative */ #define COM10_HS_NEG 0x01 /* HSYNC negative */ #define REG_HSTART 0x17 /* Horiz start high bits */ #define REG_HSTOP 0x18 /* Horiz stop high bits */ #define REG_VSTART 0x19 /* Vert start high bits */ #define REG_VSTOP 0x1a /* Vert stop high bits */ #define REG_PSHFT 0x1b /* Pixel delay after HREF */ #define REG_MIDH 0x1c /* Manuf. ID high */ #define REG_MIDL 0x1d /* Manuf. ID low */ #define REG_MVFP 0x1e /* Mirror / vflip */ #define MVFP_MIRROR 0x20 /* Mirror image */ #define MVFP_FLIP 0x10 /* Vertical flip */ #define REG_AEW 0x24 /* AGC upper limit */ #define REG_AEB 0x25 /* AGC lower limit */ #define REG_VPT 0x26 /* AGC/AEC fast mode op region */ #define REG_HSYST 0x30 /* HSYNC rising edge delay */ #define REG_HSYEN 0x31 /* HSYNC falling edge delay */ #define REG_HREF 0x32 /* HREF pieces */ #define REG_TSLB 0x3a /* lots of stuff */ #define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ #define REG_COM11 0x3b /* Control 11 */ #define COM11_NIGHT 0x80 /* NIght mode enable */ #define COM11_NMFR 0x60 /* Two bit NM frame rate */ #define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ #define COM11_50HZ 0x08 /* Manual 50Hz select */ #define COM11_EXP 0x02 #define REG_COM12 0x3c /* Control 12 */ #define COM12_HREF 0x80 /* HREF always */ #define REG_COM13 0x3d /* Control 13 */ #define COM13_GAMMA 0x80 /* Gamma enable */ #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ #define REG_COM14 0x3e /* Control 14 */ #define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ #define REG_EDGE 0x3f /* Edge enhancement factor */ #define REG_COM15 0x40 /* Control 15 */ #define COM15_R10F0 0x00 /* Data range 10 to F0 */ #define COM15_R01FE 0x80 /* 01 to FE */ #define COM15_R00FF 0xc0 /* 00 to FF */ #define COM15_RGB565 0x10 /* RGB565 output */ #define COM15_RGB555 0x30 /* RGB555 output */ #define REG_COM16 0x41 /* Control 16 */ #define COM16_AWBGAIN 0x08 /* AWB gain enable */ #define REG_COM17 0x42 /* Control 17 */ #define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ #define COM17_CBAR 0x08 /* DSP Color bar */ #define REG_CMATRIX_BASE 0x4f #define CMATRIX_LEN 6 #define REG_CMATRIX_SIGN 0x58 #define REG_BRIGHT 0x55 /* Brightness */ #define REG_CONTRAS 0x56 /* Contrast control */ #define REG_GFIX 0x69 /* Fix gain control */ #define REG_REG76 0x76 /* OV's name */ #define R76_BLKPCOR 0x80 /* Black pixel correction enable */ #define R76_WHTPCOR 0x40 /* White pixel correction enable */ #define REG_RGB444 0x8c /* RGB 444 control */ #define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ #define R444_RGBX 0x01 /* Empty nibble at end */ #define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ #define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ #define REG_BD50MAX 0xa5 /* 50hz banding step limit */ #define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ #define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ #define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ #define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ #define REG_BD60MAX 0xab /* 60hz banding step limit */
これをArduinoに書き込めばOK.
いろいろwebで調べて,とりあえずQQVGAのRGB444で画像取得する例がいくつか見つかったので,それで試してる.
使い方は,シリアルモニタを開いて,
sを入力すると撮影,dで画像データのダンプが行われる.hで簡単なヘルプ(というほどのものでもないが)が表示される.なので,まぁスケッチを見ながらいろいろ試してみてくださいな.
画像データは,QQVGAのRGB444で動かしているので,ダンプすると160x120=19200画素のデータが,1画素あたり2バイト出力される.なので,トータルとしては38400バイトになる.
データの並びは,xBGRで出力される.なお,160画素ごとに改行を入れて出力される.改行を除去すると,1バイトあたり2文字でダンプされるので,結果として,76800文字のデータが得られることになる.
さて,データだけあってもつまらないので,Processingで画像を表示してみる.
Processingのコードは,こんな感じ.
int width = 160; int height = 120; String[] pixeldata; void setup() { frameRate(1); size(width, height); noStroke(); pixeldata = loadStrings("captureData.txt"); } void draw() { for (int i = 0; i < width * height; i++) { int x = i % width; int y = i / width; fill( unhex(String.valueOf(pixeldata[0].charAt(4*i+3))) *16, unhex(String.valueOf(pixeldata[0].charAt(4*i+2))) *16, unhex(String.valueOf(pixeldata[0].charAt(4*i+1))) *16 ); rect(x, y, 1, 1); } }
ダンプしたデータは,captureData.txtとしてProcessingのコードと同じディレクトリに保存してくださいな.
で,表示されるサンプル画像はこんな感じ.
ま,QQVGなのと,RGB各色4ビットしかないので,画質はそれなりですな.
あと,水平方向の位相がちょっとずれてるようなのと,電源投入一発目の画像がおかしいことがあるんだけど...
ま,お試しあれ.
参考サイト
いっぱいあって,いっぱい参考にした.特に以下の2つを参考にしたけど,ほかにもGoogleでov7670で検索してヒットするサイトは軒並みチェックした.先人に感謝.
トラ技 頒布カメラB(OV7670 FIFO AL422B)の動作確認 | mbed
HR2_blog: mbedでトラ技3月号の頒布カメラBを使う
2014.12.15追記
サンプル画像の元データ(captureData.txt)はこんな感じ.captureData.txt.zip.jpg
So-netのブログはテキストファイルのアップロードができないので,ZIP圧縮して,拡張子に.jpgをつけて無理矢理アップロードしてる.なので,ダウンロードしたら.jpgを消してZIPファイルとして展開してくださいな.