たまたまAliexpressを見ていたらフルカラーシリアルLEDが12個乗ったLEDリングが1.25ドルで売っていたのでついポチってしまった。
端子などの付属品も一切ついてなかった。しかし安いぞ…2021年4月30日金曜日
WS2812BなLEDリングを買ってみた
2021年4月17日土曜日
MJPG-Streamerの代替としてµStreamerを試してみた。
前にMJPG-StreamerでWiFiなFPVカメラにすると遅延がどのぐらい出るのかを試してみたんだけど、そのときは解像度320x240の15FPSで行けそうなぐらいだった。
µStreamerを使うとカメラのハードウェアエンコード機能を使えたりするらしいので、この機能でどのぐらい低遅延になるのかを試してみた。
µStreamerはラズパイに最適化されていてラズパイカメラでもMJPG-Streamerより性能が出るらしいんだけど今回は前回試したときと同じBeagleBone BlueとUVC対応Webカメラで試してみた。
まずはBBBlueのOSのアップデート。だいぶ放置していたので今回はeMMCのOSをまるごとアップデートすることに。OSはこちらからダウンロードした。
今回はeMMCのOSをまるごと入れ替えたかったので、consoleフォルダの中のbone-eMMC-flasherから始まるイメージファイルを使用した。ダウンロード後に解凍するとimgファイルができるのでラズパイ用の書込ツールでimgファイルを適当なSDカードに書き込んだ。
あとはBeagleBone Blueに差し込んでSDボタンを押しながら電源を入れるだけ。LEDが5分ぐらい流れたあとに全点灯して少しするとLEDが消えるので、LEDが全部消えたら(ACアダプタ使用時は緑色だけついた状態)電源を抜いてmicroSDカードを抜いて完成。
電源を入れるとeMMCから新しいOSが起動する。
次に本題のμStreamerをビルドする。MJPG-Streamerのようにapt-getだけでは入れられなかったのでGithubの手順通りにビルドした。手順と一緒にMJPG-streamerとの比較が乗ってるので置き換えを狙っていそうな感じ?確かにMJPG-streamerはラズパイではよく使用例があるんだけどあんまり更新されてなさそうだし…
まずは必要なパッケージをインストール
sudo apt-get update sudo apt-get install build-essential libevent-dev libjpeg-dev libbsd-dev make usbutils
ustreamer本体をダウンロードしてビルド
git clone --depth=1 https://github.com/pikvm/ustreamer cd ustreamer make
ビルドに2分ぐらいかかった。
Webカメラを繋げて起動してみる。BeagleBone BlueにACアダプタ接続するの忘れずに(ACアダプタかバッテリがないとUSBポートの電圧が不安定でカメラがうまく起動できない)
今回は前回と同じくC270を使用した。これも一応MJPEGのハードウェアエンコード対応しているらしい。
./ustreamer -m MJPEG -c HW -f 15 -s 0.0.0.0 -p 8080
これでUSBとBeagleBoneをPCに繋いでる場合はhttp://192.168.7.2:8080にアクセスするとµStreamerのページが表示されるはず。
/streamをクリックすると映像が見れる。
デフォルトの640x480でも結構レスポンスが良さそうなので前回同様測定してみた。
H264のハードウェアエンコード対応のカメラだったら帯域を食わなくていいのかなぁ
ちなみにSJ4000をUSBカメラモードで使うと遅延が0.31秒ぐらいの遅延だったのでカメラによっても遅延が変わるっぽい。
2021年4月10日土曜日
Arduinoでi2cスレーブデバイスを作ってみる
Arduino同士でI2Cのマスタとスレーブとして通信するとき、よくシリアル通信みたいな使い方を見かけるんだけど、I2C接続のセンサとかみたいにI2Cのレジスタを指定して読み書きできないか試してみた。
いろんなサンプルを見ているとI2C通信って一番最初にレジスタのアドレスを送って、その後に書き込みたいデータを送っているような感じ。読み込みの際も最初は読み込みたい先頭のアドレスを送っている感じ?
というわけでレジスタの範囲を指定して読み書きできるようなスケッチを作ってみた。
#include <Arduino.h> #include <Wire.h> #define SLAVE_ADDRESS 0x38 #define DEBUG //#define DISABLE_INTERNAL_PULLUP //使用するレジスタ範囲指定 #define I2C_REG_ROW 3 #define I2C_REG_COL 4 uint8_t I2C_REG[I2C_REG_ROW][I2C_REG_COL]; //読み書きするレジスタアドレス uint8_t REG_SELECTED; //i2c受信イベント void receiveEvent(int _length) { //1byte目を読み込む(レジスタアドレス指定) REG_SELECTED = Wire.read(); uint8_t startRow = REG_SELECTED >> 4; uint8_t startCol = (REG_SELECTED & 0x0F); #ifdef DEBUG Serial.print("REG:"); Serial.println(REG_SELECTED, HEX); #endif while (Wire.available() > 0) { if(startRow < I2C_REG_ROW && startCol < I2C_REG_COL){ I2C_REG[startRow][startCol] = Wire.read(); #ifdef DEBUG Serial.print("Write:"); Serial.println(I2C_REG[startRow][startCol], HEX); #endif }else{ Wire.read(); } ++startCol; } } void requestEvent() { uint8_t startRow = REG_SELECTED >> 4; uint8_t startCol = (REG_SELECTED & 0x0F); if(startRow < I2C_REG_ROW && startCol < I2C_REG_COL){ Wire.write(&I2C_REG[startRow][startCol], I2C_REG_COL - startCol); } } void setup() { //SlaveでWireライブラリを初期化 Wire.begin(SLAVE_ADDRESS); //イベント設定 Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent); //内蔵プルアップ無効にする場合 #ifdef DISABLE_INTERNAL_PULLUP pinMode(SDA, INPUT); pinMode(SCL, INPUT); #endif #ifdef DEBUG Serial.begin(115200); #endif } void loop() { }
とりあえずArduino UNOとかのAtmega 328pデバイスで動くはず。
全部のレジスタ使いたいわけじゃなかったので使用できるレジスタの範囲を2次元配列でI2C_REG_ROWとI2C_REG_COLで指定する形にしてみた。もっときれいな実装方法あるかもしれないけど…
レジスタの範囲指定は0x00起点で何行、何列みたいな指定。
素人プログラムなのでおかしいところとか上手く動かないかもしれないところがあるかもしれない。
動作確認はRaspberry Pi 3BとArduino Microで行った。
ラズパイは3.3V、Arduinoは5Vなのでレベル変換するか、Arduino側の内蔵プルアップを無効にして(#define DISABLE_INTERNAL_PULLUPのコメントアウトを外す)Raspberry PiのI2Cに直結しても行けるかも?(無保証)
今回はレベルコンバータのLVCNV-I2Cを使用してテストを行った。A側にArduino、B側にラズパイをつなぐ。
ラズパイで"i2cdetect -y 1"をしてみる。
これでI2C接続のモータドライバとか作ってラズパイで遊んだりできるかも。センサとかつければセンサの値を処理してからラズパイに渡したりもできるし。