raspberryPi2/3に(オーディオ用では無い)複数の普通のDAコンバータmcp4725を接続して5V出力を得る方法
電子工作の基本としてAD/DAコンバータは直ぐに使えるようにしておきたいですね。
ちょっとした試作で便利に使えるRaspberryPiを使ってアナログ出力を取り出そうとしたら、意外にもDA出力が備わっていませんでした。
外付けして対応しようと調べてもオーディオ用DACの情報ばかりで欲しい情報が直ぐに手に入らなかったので、汎用DAコンバータの接続方法をまとめておきたいと思います。
(PWM出力をRCフィルタに掛けてDA代わりにするのがよく使われているようですが、このページでは普通にDA出力を取ります。)
回路図
RaspberryPiのGPIOのI2Cピン3,5は、内部でpullupされているそうなので、2.7kΩの抵抗二つは取り除いた方が良いようです。
今は、汎用DAコンバータで入手しやすいチップがすごく少ないようです。
インターフェースとしては、SPI接続(MCP4922-E/P等)またはI2C接続(MCP4725,MCP4726等)が一般的です。
入手のしやすさから、秋月のmcp4725モジュールを使うことにしました。
RaspberryPi2/3のGPIO出力からDAコンバータを接続します。
RaspberryPiのGPIO出力は3.3Vなのでmcp4725を直付けすると、出力も最大3.3Vまでしかとることができません。
mcp4725は電源電圧までレールトゥレールで出力電圧をとれるので、2.7-5.5Vまで電源電圧を調整することで最大出力電圧を変更できます。
出力電圧を5Vとして設計します。
そのため、I2Cの信号レベルも3.3Vから5Vに変換してやる必要があります。
mcp4725のEEPROMにwiringPiを通して書き込む方法 - cvl-robot's diary
に続く。
[1] 電子部品使い方:マイコンのD/A変換
[2] MCP4725搭載D/Aコンバータモジュール(I2C通信)
[3] Adafruit MCP4725 Breakout Board - 12-Bit DAC w/I2C Interface [ADA935] by Adafruit [並行輸入品]
[4] MCP4725 EEPROM搭載12ビットD/Aコンバータモジュール: 半導体 秋月電子通商 電子部品 ネット通販
ofxRobotArm
openFrameworksでUniversalRobotsのロボットを動かすAddonが発表されました。
www.creativeapplications.net
github.com
github.com
installAddon.bat
cd ../../addons git clone http://github.com/CreativeInquiry/ofxTiming git clone http://github.com/CreativeInquiry/ofxCV git clone http://github.com/CreativeInquiry/ofxNatNet git clone http://github.com/CreativeInquiry/ofxGML git clone http://github.com/CreativeInquiry/ofxGizmo git clone http://github.com/CreativeInquiry/ofxTimeline git clone http://github.com/CreativeInquiry/ofxURDriver git clone http://github.com/CreativeInquiry/ofxPtf cd ../addons/ofxRobotArm
カスタマイズされたアドオンをいっぱいインストールしなければなりません。手で入れるのは面倒なので、installAddon.shが用意されています。
シンプルでよくできていますね。でも、このブログで紹介してきたのとほとんど同じアイデアです。
勝手にライバル視しています。こっちの方が歴史が深いぞ。
cvl-robot.hateblo.jp
今日のストレス解消
良く寝るのが一番。敷マットに西川AiRを購入したら、良い掛布団が欲しくなりました。
いろいろ調べた結果、GORE素材を使った羽毛布団に魅かれました。
西川リビング 羽毛ふとん ゴア GORE ロイヤルスター エンジ シングル 日本製 (エンジ)
- 出版社/メーカー: 西川リビング
- メディア:
- この商品を含むブログを見る
openFrameworksの教科書
無料で公開されているそうです。ありがたいですね。
http://download.bnn.co.jp/download/beyond_interaction/BNN_BeyondInteraction.pdf
今日のイヤホン
小米のPistonの復刻版が、1moreというところからPiston Classicという名前で出ていてAmazonで3000円ぐらいで買えるそうです。
1MORE Piston Classic 【Xiaomi Mi Piston2 が1MOREブランドで復活】 (グレー(Gray))
- 出版社/メーカー: 1MORE
- メディア: エレクトロニクス
- この商品を含むブログを見る
ZhengNan®Shop 復刻版グレードアップバージョン Piston インナーイヤホン重低音 BASS 遮音 正規品保証 (グレイ)
- 出版社/メーカー: zhengnan
- メディア: エレクトロニクス
- この商品を含むブログを見る
カメラ画像をofxVideoGrabberで取得してofxTurboJpegでエンコードして、ofxZMQを通してネットワーク配信するプログラムサンプル
OpenCVを使わずに、openFrameworksのアドオンだけで動くように変更しました。
ofxZmq
GitHub - satoruhiga/ofxZmq
の2つのアドオンを使用しています。
今回はopenCV版とは違いofxZmqの改造は不要ですが、ofxTurboJpegのsave関数がprivateで定義されているのをpublicに変更してやる必要があります。(なんでprivateにされてるんだろう??)
ofApp.h
#pragma once #include "ofMain.h" #include "ofxTurboJpeg.h" class ofxZmqSubscriber; class ofxZmqPublisher; class ofApp : public ofBaseApp { public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); ofxZmqSubscriber* subscriber; ofxZmqPublisher* publisher; ofVideoGrabber cap; ofxTurboJpeg turbo; ofImage frame; ofBuffer send_buf; int params; ofImage image; ofBuffer recv_buf; };
ofApp.cpp
#include "ofApp.h" #include "ofxZmq.h" //-------------------------------------------------------------- void ofApp::setup() { ofSetFrameRate(30); cap.setVerbose(true); cap.setDeviceID(1); if (cap.initGrabber(640, 480)) { //frame.allocate(cap.getWidth(), cap.getHeight(), OF_IMAGE_COLOR); params = 90; // quality // start server publisher = new ofxZmqPublisher(); publisher->setHighWaterMark(1); publisher->bind("tcp://*:9999"); } // start client subscriber = new ofxZmqSubscriber(); subscriber->setHighWaterMark(1); subscriber->connect("tcp://localhost:9999"); } //-------------------------------------------------------------- void ofApp::update() { while (subscriber->hasWaitingMessage()) { subscriber->getNextMessage(recv_buf); turbo.load(image, recv_buf); // turbo.load(recv_buf, image); 2022/08/27 updated cout << "received data: " << recv_buf.size() << endl; } cap.update(); if (cap.isFrameNew()) { //frame = cap.getPixels(); turbo.save(send_buf, cap.getPixelsRef(), 90); publisher->send(send_buf); } } //-------------------------------------------------------------- void ofApp::draw() { cap.draw(0, 0); image.draw(cap.getWidth(), 0); } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ } //-------------------------------------------------------------- void ofApp::keyReleased(int key){ } //-------------------------------------------------------------- void ofApp::mouseMoved(int x, int y ){ } //-------------------------------------------------------------- void ofApp::mouseDragged(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::mousePressed(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::mouseReleased(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::windowResized(int w, int h){ } //-------------------------------------------------------------- void ofApp::gotMessage(ofMessage msg){ } //-------------------------------------------------------------- void ofApp::dragEvent(ofDragInfo dragInfo){ }
その受信をofThread版。lock()しないで落ちないから書いてないけど、大丈夫かな。。。
ofApp.h
#pragma once #include "ofMain.h" #include "ofxTurboJpeg.h" class ofxZmqSubscriber; class ofxZmqPublisher; class ThreadedSubscriber : public ofThread { public: ThreadedSubscriber(ofxZmqSubscriber* ptr) : subscriber(ptr) { image.setUseTexture(true); } void threadedFunction(); ofImage& getImage(); protected: ofxZmqSubscriber* subscriber; ofxTurboJpeg turbo; ofBuffer recv_buf; ofImage image; }; class ofApp : public ofBaseApp { public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); ofxZmqSubscriber* subscriber; ofxZmqPublisher* publisher; ofVideoGrabber cap; ofxTurboJpeg turbo; ofImage frame; ofBuffer send_buf; int params; ThreadedSubscriber* threadedSubscriber; ofImage image; };
ofApp.cpp
#include "ofApp.h" #include "ofxZmq.h" void ThreadedSubscriber::threadedFunction() { while (isThreadRunning()) { while (subscriber->hasWaitingMessage()) { do { subscriber->getNextMessage(recv_buf); } while (subscriber->hasWaitingMessage()); turbo.load(recv_buf, image); image.update(); //image.saveImage("test.jpg"); cout << "received data: " << recv_buf.size() << "\r"; } } } ofImage& ThreadedSubscriber::getImage() { return image; } //-------------------------------------------------------------- void ofApp::setup() { ofSetFrameRate(30); cap.setVerbose(true); cap.setDeviceID(1); if (cap.initGrabber(640, 480)) { params = 90; // quality // start server publisher = new ofxZmqPublisher(); publisher->setHighWaterMark(1); publisher->bind("tcp://*:9999"); } // start client subscriber = new ofxZmqSubscriber(); subscriber->setHighWaterMark(1); subscriber->connect("tcp://localhost:9999"); threadedSubscriber = new ThreadedSubscriber(subscriber); threadedSubscriber->startThread(false); } //-------------------------------------------------------------- void ofApp::update() { cap.update(); if (cap.isFrameNew()) { //frame = cap.getPixels(); turbo.save(send_buf, cap.getPixelsRef(), 100); publisher->send(send_buf); } } //-------------------------------------------------------------- void ofApp::draw() { cap.draw(0, 0); image = threadedSubscriber->getImage(); image.draw(cap.getWidth(), 0); } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ } //-------------------------------------------------------------- void ofApp::keyReleased(int key){ } //-------------------------------------------------------------- void ofApp::mouseMoved(int x, int y ){ } //-------------------------------------------------------------- void ofApp::mouseDragged(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::mousePressed(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::mouseReleased(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::windowResized(int w, int h){ } //-------------------------------------------------------------- void ofApp::gotMessage(ofMessage msg){ } //-------------------------------------------------------------- void ofApp::dragEvent(ofDragInfo dragInfo){ }
ofxZmq作者の方のサンプルの方が勉強になりそうです。
github.com
今日のハイスピードカメラ
CASIO EX-100Proが一台あると、実験に便利そうです。でも流通が限定していて入手しづらいうえに高い。一般向けのこれで妥協するかどうか。
とか、思っていたら断然こっちの方がいいですね。新しいハイスピードカメラもっと調べてみよう。
カメラ画像をOpenCVで取得してJpegエンコードして、ZeroMQを通してネットワーク配信するプログラムサンプル(その2.受信をマルチスレッド化)
testApp.h
#pragma once #include "ofMain.h" #include "opencv2/opencv.hpp" class ofxZmqSubscriber; class ofxZmqPublisher; class ThreadedSubscriber : public ofThread { public: ThreadedSubscriber(ofxZmqSubscriber* ptr) : subscriber(ptr) {}; void threadedFunction(); void draw(); protected: ofxZmqSubscriber* subscriber; cv::Mat image; std::vector<unsigned char> recv_buf; }; class testApp : public ofBaseApp{ public: ~testApp(); void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); ofxZmqSubscriber* subscriber; ofxZmqPublisher* publisher; cv::VideoCapture cap; cv::Mat frame; std::vector<unsigned char> send_buf; std::vector<int> params; string type; ThreadedSubscriber* threadedSubscriber; };
testApp.cpp
#include "testApp.h" #include "ofxZmq.h" #include "opencv2/opencv.hpp" #pragma comment(lib, "opencv_calib3d310.lib") #pragma comment(lib, "opencv_core310.lib") #pragma comment(lib, "opencv_features2d310.lib") #pragma comment(lib, "opencv_flann310.lib") #pragma comment(lib, "opencv_highgui310.lib") #pragma comment(lib, "opencv_imgcodecs310.lib") #pragma comment(lib, "opencv_imgproc310.lib") #pragma comment(lib, "opencv_ml310.lib") #pragma comment(lib, "opencv_objdetect310.lib") #pragma comment(lib, "opencv_photo310.lib") #pragma comment(lib, "opencv_shape310.lib") #pragma comment(lib, "opencv_stitching310.lib") #pragma comment(lib, "opencv_superres310.lib") #pragma comment(lib, "opencv_ts310.lib") #pragma comment(lib, "opencv_video310.lib") #pragma comment(lib, "opencv_videoio310.lib") #pragma comment(lib, "opencv_videostab310.lib") void ThreadedSubscriber::threadedFunction() { while (isThreadRunning()) { while (subscriber->hasWaitingMessage()) { do { subscriber->getNextMessage(recv_buf); } while (subscriber->hasWaitingMessage()); lock(); image = cv::imdecode(recv_buf, CV_LOAD_IMAGE_COLOR); //image = buf.clone(); unlock(); cout << "received data: " << recv_buf.size() << endl; //sleep(1); } } } void ThreadedSubscriber::draw() { lock(); if (!image.empty()) { cv::imshow("received", image); } unlock(); } testApp::~testApp() { if (threadedSubscriber->isThreadRunning()) { threadedSubscriber->stopThread(); } subscriber->disconnect("tcp://localhost:9999"); cap.release(); } //-------------------------------------------------------------- void testApp::setup() { ofSetFrameRate(30); bool ret = cap.open(0); if (cap.isOpened()) { cout << "Camera is ready!" << endl; cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280); cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720); cap.set(cv::CAP_PROP_FPS, 30); //type = ".jpg"; type = ".webp"; if (type == ".jpg") { params.push_back(CV_IMWRITE_JPEG_QUALITY); params.push_back(100); params.push_back(CV_IMWRITE_JPEG_OPTIMIZE); params.push_back(0); params.push_back(CV_IMWRITE_JPEG_PROGRESSIVE); params.push_back(0); } else if (type == ".webp") { params.push_back(CV_IMWRITE_WEBP_QUALITY); params.push_back(70); } // start server publisher = new ofxZmqPublisher(); publisher->setHighWaterMark(1); publisher->bind("tcp://*:9999"); } // start client subscriber = new ofxZmqSubscriber(); subscriber->setHighWaterMark(0); subscriber->connect("tcp://localhost:9999"); //subscriber->connect("tcp://10.254.20.46:9999"); threadedSubscriber = new ThreadedSubscriber(subscriber); threadedSubscriber->startThread(true, false); } //-------------------------------------------------------------- void testApp::update() { if (!cap.isOpened()) return; if (cap.grab()) { bool res = cap.read(frame); if (res) { int msec_start = ofGetElapsedTimeMillis(); bool ret = cv::imencode(type, frame, send_buf, params); int msec_stop = ofGetElapsedTimeMillis(); if (ret) { publisher->send(send_buf); int lap = msec_stop - msec_start; int fps = (lap) ? 1000.0 / lap : ofGetFrameRate(); cout << "encoded size(" << type << ") : " << send_buf.size() << ", time : " << lap << ", fps : " << fps << endl; } } } } //-------------------------------------------------------------- void testApp::draw() { threadedSubscriber->draw(); } //-------------------------------------------------------------- void testApp::keyPressed(int key) { if (threadedSubscriber->isThreadRunning()) { threadedSubscriber->stopThread(); subscriber->disconnect("tcp://localhost:9999"); subscriber->connect("tcp://localhost:9999"); threadedSubscriber->startThread(true, false); } } //-------------------------------------------------------------- void testApp::keyReleased(int key) { } //-------------------------------------------------------------- void testApp::mouseMoved(int x, int y) { } //-------------------------------------------------------------- void testApp::mouseDragged(int x, int y, int button) { } //-------------------------------------------------------------- void testApp::mousePressed(int x, int y, int button) { } //-------------------------------------------------------------- void testApp::mouseReleased(int x, int y, int button) { } //-------------------------------------------------------------- void testApp::windowResized(int w, int h) { } //-------------------------------------------------------------- void testApp::gotMessage(ofMessage msg) { } //-------------------------------------------------------------- void testApp::dragEvent(ofDragInfo dragInfo) { }
今日の理想のリビングアイテム
テレビは、4Kなど映像のクオリティはうなぎのぼりで良くなっていますが、音響がついて行っていません。音と映像は、クオリティの均衡がとれてないとお互いの足を引っ張ってしまいますので、良い映像には良い音響が必要です。ヤマハのテレビ台型サラウンドスピーカーはかなり良いです。台の間が狭いので、高さのある機器を置けないのは減点ですが。色は黒と茶の2色ありますが、ヤマハは黒に限ります。
ヤマハ シアターラック50型まで対応YAMAHA YRS-1500-B
- 出版社/メーカー: ヤマハ
- メディア: エレクトロニクス
- この商品を含むブログを見る
ヤマハ 壁寄せ金具 (1台) ブラック YTS-V1200(B)
- 出版社/メーカー: ヤマハ
- 発売日: 2010/10/31
- メディア: エレクトロニクス
- この商品を含むブログを見る
ソニー 地上・BS・110度CSデジタルハイビジョン液晶テレビ BRAVIA X8500C 55V型 KJ-55X8500C
- 出版社/メーカー: ソニー
- 発売日: 2015/07/04
- メディア: エレクトロニクス
- この商品を含むブログを見る
ofxFaceTrackerで遊んでみる
(メモ)
オリジナルソース
github.com
FaceTrackerのオリジナル論文の解説
d.hatena.ne.jp
Visual Studioでのインストール時の修正
C/C++->OUTPUT Objects: $(IntDir)/%(RelativeDir)/
forum.openframeworks.cc
顔の置き換え
github.com
マルチフェイストラッキング
github.com
顔パーツのモデル
blog.kidapu.com
サンプル解説楽しいことをしたい: 【openframeworks】ofxFaceTrackerで遊んでみた。サンプル解説
応用例1:顔で制御、応用例2:顔を交換
yoppa.org
ライオンマスク
www.honeycomb-lab.co.jp
マンガの吹き出し
http://hackist.jp/?p=2979hackist.jp
インタラクティブアート
http://nickhardeman.com/tag/ofxfacetracker/nickhardeman.com
顔を楽器
http://golancourses.net/2014/haris/02/06/face-wah-wah-using-ofxfacetracker-and-ofxmidi/golancourses.net
講義資料
http://nakayasu.com/lecture/openframeworks-facetracker/6770nakayasu.com
SMILE to SMILE
www.bbmedia.co.jp
口から煙
http://ryujiyoshida.com/blog/category/studyryujiyoshida.com
顔のモーフィング
labs.1-10.com
カラオケ顔変換
http://www.kazushi.info/wp-content/uploads/2015/09/433149.pdf
MacOSXでの修正点
ryotakatoh.hatenablog.com
Twitterのハッシュ宅ofxtracker
twitter.com
AAM関連
AAMのモデル生成
qiita.com
http://www.mega.t-kougei.ac.jp/media/moriyama/projects/esa-aam.htmwww.mega.t-kougei.ac.jp
顔認識技術動向
d.hatena.ne.jp
今日の睡眠
シングルベッドに最低限必要な3点セットで6万円.ただのスポンジのくせに高いよなー.
東京西川 [エアー01] マットレス シングル ベーシック グレー
- 出版社/メーカー: AIR
- メディア: ホーム&キッチン
- クリック: 18回
- この商品を含むブログを見る
東京西川 枕 [エアー3D] コンディショニングピロー 高め スウィート グレー
- 出版社/メーカー: AIR
- メディア: ホーム&キッチン
- この商品を含むブログを見る
hiro_handleをpyzmq経由で呼び出せるようにする
(作業メモ)
まずOpenRTM-aistをPython2.7.10環境で構築しなおします。
python2.6はサポートが終了してしまうようで、pipを使ってpyzmqをすんなりインストールすることができません。
http://www.openrtm.org/openrtm/node/5768
32bit用 Windows用インストーラ OpenRTM-aist-Python_1.1.0-RELEASE_x86.msi
Python-2.7 python-2.7.10.msi
をダウンロードしてインストールします。Python2.7.11では駄目だそうです。
JointDataTypes.idlの追加
この節は使わないので、すっ飛ばしてもかまいません。
OpenRTM-aist-Python_1.1.0.zipを解凍して,setup.pyを編集します。
C:\workspace\OpenRTM-aist-Python-1.1.0\OpenRTM_aist\RTM_IDLの下にJointDataTypes.idlをコピーして追加します。
JointDataTypes.idlは,HIROのgrx/share/hpsys/idlにある。
.. baseidl_files = [ "BasicDataType.idl", "DataPort.idl", "ExtendedDataTypes.idl", "InterfaceDataTypes.idl", "Manager.idl", "OpenRTM.idl", "RTC.idl", "SDOPackage.idl", "JointDataTypes.idl" # added ] ..
そのあと、
python setup.py build
python setup.py install
をする。
cd OpenRTM_aist\RTM_IDL
してから、
omniidl -bpython JointDataTypes.idl
あとは普通にhiro_handleをインストール
pyzmqのインストール
pip install --upgrade pip
pip install pyzmq-static