cvl-robot's diary

研究ノート メモメモ https://github.com/dotchang/

raspberryPi2/3に(オーディオ用では無い)複数の普通のDAコンバータmcp4725を接続して5V出力を得る方法

電子工作の基本としてAD/DAコンバータは直ぐに使えるようにしておきたいですね。
ちょっとした試作で便利に使えるRaspberryPiを使ってアナログ出力を取り出そうとしたら、意外にもDA出力が備わっていませんでした。
外付けして対応しようと調べてもオーディオ用DACの情報ばかりで欲しい情報が直ぐに手に入らなかったので、汎用DAコンバータの接続方法をまとめておきたいと思います。
(PWM出力をRCフィルタに掛けてDA代わりにするのがよく使われているようですが、このページでは普通にDA出力を取ります。)

回路図

f:id:cvl-robot:20160714140331p:plain
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素材を使った羽毛布団に魅かれました。

openFrameworksの教科書

無料で公開されているそうです。ありがたいですね。
http://download.bnn.co.jp/download/beyond_interaction/BNN_BeyondInteraction.pdf

今日のイヤホン

小米のPistonの復刻版が、1moreというところからPiston Classicという名前で出ていてAmazonで3000円ぐらいで買えるそうです。

カメラ画像をofxVideoGrabberで取得してofxTurboJpegでエンコードして、ofxZMQを通してネットワーク配信するプログラムサンプル

OpenCVを使わずに、openFrameworksのアドオンだけで動くように変更しました。
ofxZmq
GitHub - satoruhiga/ofxZmq

ofxTurboJpeg
GitHub - armadillu/ofxTurboJpeg: Rough OF addon that uses turbo-jpeg lib to read and write jpegs. 2-3 times faster than OF's freeImage based jpeg en/decoder

の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色ありますが、ヤマハは黒に限ります。

ヤマハ 壁寄せ金具 (1台) ブラック YTS-V1200(B)

ヤマハ 壁寄せ金具 (1台) ブラック YTS-V1200(B)

まず、こんな良いやつが置ける部屋が欲しいです。

ofxFaceTrackerで遊んでみる

(メモ)

オリジナルソース
github.com

FaceTrackerのオリジナル論文の解説
d.hatena.ne.jp

Visual Studioでのインストール時の修正
C/C++->OUTPUT Objects: $(IntDir)/%(RelativeDir)/
forum.openframeworks.cc

顔の置き換え
github.com

マルチフェイストラッキング
github.com

笑い男
monitorgazer.blogspot.jp

顔パーツのモデル
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でのインストール例
qiita.com

MacOSXでの修正点
ryotakatoh.hatenablog.com

Twitterのハッシュ宅ofxtracker
twitter.com

動画集

vimeo.com

www.youtube.com

vimeo.com

www.youtube.com

これと組み合わせると、面白いかも。
Video Magnification
github.com



固有値の説明
qiita.com


ちまたでは、OpenFaceなるライブラリが注目を集めています。
OpenFace

今日の睡眠

シングルベッドに最低限必要な3点セットで6万円.ただのスポンジのくせに高いよなー.

[asin:B00JH8ATRU:detail]

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をインストール

http://cvl-robot.hateblo.jp/entry/2013/10/07/211346

pyzmqのインストール

pip install --upgrade pip
pip install pyzmq-static

今日のバスマット

ソイルが欲しいのですが、その前にきれいな浴室のある部屋が欲しいです。

soil 珪藻土 バスマット ライト

soil 珪藻土 バスマット ライト