Make Controllerはじめました。
Posted by arms22 on 2009年10月28日

ひょんなことからMake:日本語版の中の人からMake Controllerをお借りすることができた。Make ControllerはArduinoと同じオープンソースハードウェアのプラットフォームだ。フィジカルコンピューティングやアート、教育、試作、電子工作向けにMakingThingsが開発を行っている。
Make Controllerはマイクロコントローラが載ったController Boardとそれを拡張する2つのボードから構成される。Controller BoardはAtmelのARMマイコンAT91SAM7X256を積んだボードで、2つの拡張ボードのベースとなるボードだ。
Interface BoardはArduinoのような黒いピンヘッダが実装されていて35のIO、4つのアナログ入力専用端子、2つのシリアルポート、SPIにTWI、それにEthernetとUSBを備えている。
(Interface Board via MakingThings)
Application Boardは何やら業務機器を思わせる特徴的なスクリューターミナルにバッファ付きADポートが8つ、ハイカレントデジタルポートが8つ、サーボコントローラが4つ、8 DIPスイッチにトリムポット、EathernetとUSBを備える。かなり豪華な仕様だけにその分すこし高い。けど、お手軽に大きな機器を制御できるボードだ。
(Application Board via MakingThings)
Arduino Duemilanove 328と比較してみた。
機能 | Arduino Duemilanove 328 | Make Controller w/Interface Board | Make Controller w/Application Board |
マイクロコントローラ | Atmega328 | AT91SAM7X256(ARM7) | ← |
動作電圧 | 5V | 3.3V | ← |
入力電圧 | 7~12V | 7~12V | ← |
デジタルI/O | 14本 | 35本 | 1A出力:8本、ステータスLED:4本、サーボモータ出力:4本 |
アナログ入力 | 6本 (10ビット) | 8本(10ビット) | ← |
PWM | 6本 | 4本 | 4本(1A出力ハーフブリッジ回路に接続) |
シリアルポート | 1本 | 2本 | 1本 |
USB | あり(仮想シリアルポート) | あり(仮想シリアルポート、HIDマウス・キーボード) | ← |
Ethernet | なし(イーサーネットシールドで追加可能) | 10/100Mビット(TCP/UDP/DHCP/DNSサポート) | ← |
通信 | SPI/TWI | SPI/TWI/CAN | ← |
フラッシュメモリ | 32K | 256K | ← |
SRAM | 2K | 64K | ← |
EEPROM | 1K | 32K | ← |
OS | なし | FreeRTOS | ← |
クロック周波数 | 16MHz | 55MHz(48MIPs) | ← |
ツール | Arduino IDE(Win,Mac,Linux) | mcbuilder(Win,Mac,Linux) | ← |
プログラム言語 | C/C++ライク | 標準C/C++ | ← |
プライス | 3,200円 | 85ドル | 109ドル |
Interface BoardはArduino MEGAにEthernet Shildを足した感じ。値段も+αの機能が付いてくると考えれば少しも高くない。Arduinoに限界を感じたらMake Controllerも視野に入れて考えても良さそう。ただ残念なことに日本で手に入るMake Controllerの情報は少ない。けど、手元にInterface Boardがあるから、これから少しずついろいろ試して情報を公開していくつもり。乞うご期待。。あ、うそ。あんまり期待しないで(笑)
MakingThings
http://www.makingthings.com/
MakingThings - Arduino Comparison
http://www.makingthings.com/arduino-comparison
Maker SHED - Make Controller 2.0 Interface Board Kit
http://www.makershed.com/ProductDetails.asp?ProductCode=MKMT2
Make Controller 2.0とInterface Boardのキットが登場
http://jp.makezine.com/blog/2009/05/make_controller_interface_board_kit.html
Make Controller v2.0ショートレビュー
http://jp.makezine.com/blog/2009/09/make_controller_2.html
Make Controller Kit 入門(チュートリアル)
http://r-dimension.xsrv.jp/classes_j/make_controller/
オライリージャパン
売り上げランキング: 5211
MTM04ワークショップ準備中。。
Posted by arms22 on 2009年10月26日

スピーカユニットとフォンジャックにワイヤを半田づけ。なかなか終らない。
これが終ったら説明書を書いて、部品を小分けして袋詰めだ。
Arduinoで遊ぼう - 大容量EEPROMに毎日の温度変化を保存する
Posted by arms22 on 2009年10月24日

Arduinoに搭載されているマイコン(AVR)には電源を切ってもデータが消えないメモリ「EEPROM」が内蔵されている。Duemilanove 168は512バイト、Duemilanove 328は1024バイト、MEGAは4096バイトのEEPROMを内蔵している。
少しだけ情報を保存する場合には内蔵のEEPROMで十分だけど、温度センサの値を数ヶ月に渡って保存したり、インターネットからダウンロードしたファイルを保存するには容量が足りない。そんな時は大容量のEEPROMをArduinoに接続してもりもりデータを保存しよう!今回、I2CインターフェースのEEPROMとCOMS温度センサ「S8100B」を使った簡単な温度ロガーの作り方を紹介するよ。
EEPROMを選ぶ
秋月電子でいろいろなサイズのEEPROMが買える。用途に合わせて最適なEEPROMを選択しよう。今回は512Kbit(64Kbytes)の24LC512を選んだ。
- マイクロチップ 24LC64 64Kbit( 8Kbytes) 60円
- マイクロチップ 24LC256 256Kbit( 32Kbytes) 120円
- マイクロチップ 24LC512 512Kbit( 64Kbytes) 200円
- マイクロチップ 24LC1025 1Mbit(128Kbytes) 450円
温度センサ
温度センサには秋月で買ったS8100Bを使った。S8100Bは-20℃から+80℃までの温度を測定できる温度センサICだ。トランジスタみたいな形をしていて、ラベルを正面にして左からVOUT、GND、VDDとなっている。VDDに5Vを接続してやれば、VOUTから温度に応じた電圧が出力される。1℃温度が上がると約-8mV電圧が下がる、右肩下がりの特性になっている。S8100Bの温度と出力電圧の特性をグラフ化した。

(S8100B 温度-出力電圧 特性)
Arduinoと接続する

(図の555はIC2 EEPROM、NはS8100B)
ArduinoとEEPROMの接続にはアナログ端子の4番と5番を使う。4番にEEPROMのSDAを接続、5番にEEPROMのSCLを接続する。SDA、SCLは1KΩの抵抗でプルアップする。温度センサS8100BのVOUTをアナログ端子の0番に接続する。VOUTは1MΩの抵抗でプルアップする。
ライブラリをダウンロードする
サンプルスケッチを動かすには次の3つのライブラリが必要です。ライブラリをダウンロードしてSKETCHBOOK/librariesフォルダにコピーしてください。
TwEEPROM - I2CEEPROM読み書き用ライブラリ
http://arms22.googlecode.com/files/TwEEPROM001.zip
S8100B - 温度センサ用ライブラリ
http://arms22.googlecode.com/files/S8100B002.zip
Sleep - AVRスリープ用ライブラリ
http://arms22.googlecode.com/files/Sleep003.zip
サンプルスケッチ
スケッチは1秒間隔で温度センサから温度を読み取ってEEPROMに書き込みます。EEPROMに書き込まれた温度データはArduino IDEのシリアルモニタから読み出せます。スケッチは次のコマンドに対応しています。
'd' EEPROMに書き込まれた全温度データを出力します。
'r' EEPROMの内容をクリアします。
'm' モニタ機能をオン・オフします。
'g' Google Chart APIでグラフ表示可能なURLを出力します。

(カップヌードルの上において温度を測定した結果)
#include <Sleep.h>
#include <Wire.h>
#include <TwEEPROM.h>
#include <S8100B.h>
#define LOG_STR_ADDR (0x500000) // device addr + memory addr
#define LOG_MEM_SIZE (0x10000)
#define LOG_ENT_SIZE (2)
#define LOG_SIG_ADDR (LOG_STR_ADDR+LOG_MEM_SIZE-4)
#define LOG_READ_PEROPD (1000)
Temperature myTemp(0);
void setup()
{
Wire.begin();
Serial.begin(115200);
#define LED_PIN 13
pinMode(LED_PIN,OUTPUT);
Logger_init();
}
void loop()
{
static bool moni = false;
static uint32_t last = 0;
uint32_t now;
if(Serial.available()){
int c = Serial.read();
if(c == 'd'){
Logger_printAllTemp();
}
else if(c == 'r'){
Logger_clear();
}
else if(c == 'g'){
Logger_printGoogleChartURL();
}
else if(c == 'm'){
moni = !moni;
if(moni){
Serial.println("moni on");
}
else{
Serial.println("moni off");
}
}
}
Sleep.idle();
now = millis();
if((now - last) > LOG_READ_PEROPD){
digitalWrite(LED_PIN,HIGH);
int temp = myTemp.read() * 10;
Logger_writeTemp(temp);
if(moni){
print_temp(temp);
Serial.println();
}
digitalWrite(LED_PIN,LOW);
last = now;
}
}
void print_temp(int temp)
{
Serial.print(temp/10,DEC);
Serial.print(".");
Serial.print(abs(temp%10),DEC);
}
uint32_t Logger_wtptr;
void Logger_init(void)
{
uint8_t sig[4];
Serial.print("setup...");
sig[0] = TwEEPROM.read(LOG_SIG_ADDR+0);
sig[1] = TwEEPROM.read(LOG_SIG_ADDR+1);
sig[2] = TwEEPROM.read(LOG_SIG_ADDR+2);
sig[3] = TwEEPROM.read(LOG_SIG_ADDR+3);
if(sig[0] == 't' && sig[1] == 'e' && sig[2] == 'm' && sig[3] == 'p' ){
Logger_wtptr = LOG_STR_ADDR;
for(uint32_t rdptr = LOG_STR_ADDR;rdptr<LOG_SIG_ADDR;rdptr+=LOG_ENT_SIZE){
int temp;
temp = TwEEPROM.read(rdptr+0) << 8;
temp |= TwEEPROM.read(rdptr+1);
if(temp == 0x7fff){
Logger_wtptr = rdptr;
break;
}
}
}
else{
Logger_clear();
}
Serial.println("done");
}
void Logger_writeTemp(int temp)
{
uint32_t next = Logger_wtptr + LOG_ENT_SIZE;
if(next >= LOG_SIG_ADDR){
next = LOG_STR_ADDR;
}
TwEEPROM.write(next+0, 0x7f);
TwEEPROM.write(next+1, 0xff);
TwEEPROM.write(Logger_wtptr+0, temp >> 8);
TwEEPROM.write(Logger_wtptr+1, temp & 0xff);
Logger_wtptr = next;
}
void Logger_printAllTemp(void)
{
Serial.println("print log begin");
uint32_t rdptr = Logger_wtptr - LOG_ENT_SIZE;
do {
if(rdptr < LOG_STR_ADDR) {
rdptr = LOG_SIG_ADDR - LOG_ENT_SIZE;
}
int temp;
temp = TwEEPROM.read(rdptr+0) << 8;
temp |= TwEEPROM.read(rdptr+1);
if(temp == 0x7fff)
break;
print_temp(temp);
Serial.println();
rdptr -= LOG_ENT_SIZE;
}
while(1);
Serial.println("print log end");
}
void Logger_printGoogleChartURL(void)
{
Serial.println("---- Google Chart URL ----");
Serial.print("http://chart.apis.google.com/chart?"
"cht=lc&"
"chds=-10,40&"
"chs=720x360&"
"chxt=y&"
"chxl=0:|-10|0|10|20|30|40|&"
"chxp=0,-10,0,10,20,30,40&"
"chxr=0,-10,40&"
"chg=5,5,1,5&"
"chd=t:");
#define NUMBER_OF_TEMP 360
#define TEMP_STEP 1
uint32_t rdptr = (Logger_wtptr - LOG_ENT_SIZE) - (NUMBER_OF_TEMP * (LOG_ENT_SIZE * TEMP_STEP));
if(rdptr < LOG_STR_ADDR){
rdptr = LOG_SIG_ADDR - (LOG_STR_ADDR - rdptr);
}
int count = 0;
do{
int temp;
temp = TwEEPROM.read(rdptr+0) << 8;
temp |= TwEEPROM.read(rdptr+1);
print_temp(temp);
rdptr += LOG_ENT_SIZE * TEMP_STEP;
if(rdptr >= LOG_SIG_ADDR)
rdptr = LOG_STR_ADDR + (rdptr - LOG_SIG_ADDR);
if(count < NUMBER_OF_TEMP){
Serial.print(",");
count++;
}
else{
break;
}
}
while(1);
Serial.println();
}
void Logger_clear(void)
{
Serial.print("clear eeprom...");
TwEEPROM.write(LOG_SIG_ADDR+0,'t');
TwEEPROM.write(LOG_SIG_ADDR+1,'e');
TwEEPROM.write(LOG_SIG_ADDR+2,'m');
TwEEPROM.write(LOG_SIG_ADDR+3,'p');
TwEEPROM.write(LOG_STR_ADDR+0,0x7f); // end mark1
TwEEPROM.write(LOG_STR_ADDR+1,0xff); // end mark2
TwEEPROM.write(LOG_SIG_ADDR-2,0x7f); // end mark dammy1
TwEEPROM.write(LOG_SIG_ADDR-1,0xff); // end mark dammy2
Logger_wtptr = LOG_STR_ADDR;
Serial.println("done");
}
オライリージャパン
売り上げランキング: 3641
Arduinoで遊ぼう - JPEGカメラモジュールで写真を撮る
Posted by arms22 on 2009年10月13日

SparkFunで取り扱っているJPEGカメラモジュール(C328-7640)は解像度640x480のカラー静止画をJPEG圧縮して出力するモジュールだ。マイコンとの接続はシリアルでたった4本のワイヤでArduinoと接続、制御することができる。スナップショットコマンドを送ると撮影した画像をJPEGで圧縮してシリアルで送信する。日本だとスイッチサイエンスさん、ストロベリーリナックスさんで買える。今回はこのJPEGカメラモジュールを使って静止画を撮影し、Processingの画面に撮影した画像を表示してみよう。
※夜に撮影したのでちょっと画像が荒い感じ。昼に撮ればもう少し綺麗になると思う。
SparkFun Electronics - JPEG Color Camera - UART Interface
http://www.sparkfun.com/commerce/product_info.php?products_id=9334
スイッチサイエンス - シリアル接続JPEGカラーカメラ
http://www.switch-science.com/products/detail.php?product_id=219
Strawberry Linux - シリアル出力JPEGカラーカメラ(640x480)
http://strawberry-linux.com/catalog/items?code=18104
このモジュールの仕様は次の通り。
- サイズ:20x28mm
- 解像度:640x480, 320x240, 160x128, 80x60
- 電源:3.3V, 60mA
- 通信速度:115.2Kbps(自動速度検出付)
Arduinoと接続する

このモジュールの電源は3.3Vなので5VのArduinoと直結してしまうとポートが壊れてしまう。その為、ArduinoのTxD信号を5Vから3Vに抵抗で分圧(100K/200K)してモジュールに入力する。またArduinoのハードウェアシリアル(0番と1番)はPCとの通信に利用するのでモジュールとの通信にはソフトウェアシリアル(2番と3番)を使う。
ライブラリをダウンロードする
次のサイトでJPEGカメラモジュール(C328-7640)用のライブラリが公開されている。
gizmologi.st - Taking Pictures with Arduino
http://gizmologi.st/2009/04/taking-pictures-with-arduino/
しかし、上記ライブラリはモジュールとの通信にハードウェアシリアルを使っている。ハードウェアシリアルはPCとの通信に利用したいので、ソフトウェアシリアルを使うようにライブラリを変更した。
ソフトウェアシリアルを使うように改造したライブラリ(CameraC328R)
http://arms22.googlecode.com/files/CameraC328R.zip
ソフトウェアシリアルはNewSoftSerialというライブラリを使う。Arduino IDEにはソフトウェアシリアルライブラリ(SoftwareSerial)が標準で付属しているがavailable関数が使えない。NewSoftSerialは次のサイトからダウンロードできる。
Arduiniana - NewSoftSerial
http://arduiniana.org/libraries/newsoftserial/
ダウンロードしたライブラリはSKETCHBOOK/librariesにコピーする。
スケッチ
最初のスケッチはArduino。ハードウェアシリアル、ソフトウェアシリアルの初期化を行って(setup)、PCから1byte、データが送られてくるのを待つ(loop)。データを受信(撮影のトリガー)したらJPEGカメラモジュールとの通信を開始し、スナップショットコマンド(snapshot)を送る。そして撮影した画像をJPEGカメラモジュールから受け取りPCに送信する(getJPEGPicture_callback)。
#include <CameraC328R.h>
#include <NewSoftSerial.h>
#define LED_PIN 13
#define PAGE_SIZE 64
#define USB_BAUD 115200
#define CAMERA_BAUD 14400
NewSoftSerial mySerial(2, 3);
CameraC328R camera(&mySerial);
uint16_t pictureSizeCount = 0;
/**
* This callback is called EVERY time a JPEG data packet is received.
*/
void getJPEGPicture_callback( uint16_t pictureSize, uint16_t packageSize, uint16_t packageCount, byte* package )
{
// packageSize is the size of the picture part of the package
pictureSizeCount += packageSize;
Serial.write(package,packageSize);
if( pictureSizeCount >= pictureSize )
{
digitalWrite( LED_PIN, LOW );
Serial.flush();
}
}
void setup()
{
Serial.begin( USB_BAUD );
mySerial.begin(CAMERA_BAUD);
pinMode( LED_PIN, OUTPUT );
digitalWrite( LED_PIN, LOW );
}
void loop()
{
if( Serial.available() ){
while(Serial.read() != -1);
digitalWrite( LED_PIN, HIGH );
if( !camera.sync() )
{
Serial.println( "Sync failed." );
return;
}
if( !camera.initial( CameraC328R::CT_JPEG, CameraC328R::PR_160x120, CameraC328R::JR_640x480 ) )
{
Serial.println( "Initial failed." );
return;
}
if( !camera.setPackageSize( 64 ) )
{
Serial.println( "Package size failed." );
return;
}
if( !camera.setLightFrequency( CameraC328R::FT_50Hz ) )
{
Serial.println( "Light frequency failed." );
return;
}
if( !camera.snapshot( CameraC328R::ST_COMPRESSED, 0 ) )
{
Serial.println( "Snapshot failed." );
return;
}
pictureSizeCount = 0;
if( !camera.getJPEGPicture( CameraC328R::PT_JPEG, PROCESS_DELAY, &getJPEGPicture_callback ) )
{
Serial.println( "Get JPEG failed." );
return;
}
}
}
次のスケッチはProcessing。Arduino IDEのシリアルモニタを閉じ、アプリを起動する。画面が開いたら適当なキーを押すと撮影が開始され、Arduinoから撮影された画像が送られてくる。データの転送中、ArduinoのLEDが点灯している。このLEDが消えたら再度、適当なキーを押すと画面に撮影した画像が表示される。撮影された画像はスケッチと同じフォルダに保存される。
import processing.serial.*;
Serial myPort;
String filename = "photo.jpg";
byte[] photo = {
};
Boolean readData = false;
PImage captureImage;
void setup()
{
size(640,480);
println( Serial.list() );
myPort = new Serial( this, Serial.list()[3], 115200 ); //Serial.list()[3]は環境に合わせて変更すること。
}
void draw()
{
byte[] buffer = new byte[64];
if( readData )
{
while( myPort.available() > 0 )
{
int readBytes = myPort.readBytes( buffer );
print( "Read " );
print( readBytes );
println( " bytes ..." );
for( int i = 0; i < readBytes; i++ )
{
photo = append( photo, buffer[i] );
}
}
}
else
{
while( myPort.available() > 0 )
{
print( "COM Data: " );
println( myPort.readString() );
}
}
}
void keyPressed()
{
if( photo.length > 0 ) {
readData = false;
print( "Writing to disk " );
print( photo.length );
println( " bytes ..." );
saveBytes( filename, photo );
println( "DONE!" );
photo = new byte[0];
captureImage = loadImage(filename);
image(captureImage, 0, 0);
}
else {
readData = true;
myPort.write(0);
println( "Waiting for data ..." );
}
}
MTM04ワークショップ準備。
Posted by arms22 on 2009年10月12日

俺史上初、部品数約300、部品代で2万超え。トレーいっぱいに部品を盛ったときのこの優越感はいったい何だろう。。
MUSEのキラキラした緑色のコンデンサはとっても綺麗だ。赤とか青とかオレンジとか何色かあれば色々混ぜて購入するんだけどな。
あ、そうそう。積層メタライズドポリエステルコンデンサの水色は、タチコマブルーと勝手にそう読んでいます。
ブレッドボードミニ!
Posted by arms22 on 2009年10月04日

ストロベリーリラックマリナックスからブレッドボードミニが届いた。ICとか抵抗とかコンデンサとかも発注しないと。。それほど数はでないから部品代は高くなってしまう。あともっとカラフルな部品がほしいよなぁ。ピンクや赤のコンデンサとかさ。
オライリージャパン
売り上げランキング: 5648
PENTAX K100D用外付けバッテリーパック
Posted by arms22 on 2009年10月03日

PENTAX K100D用の外付けバッテリーパックを作った。電池の横の小さな回路はレギュレータで単3形電池6本=約9Vを降圧して6.5Vを作る。これをACアダプタとしてカメラに繋げる。レギュレータは秋月で買った可変型低ドロップ1A出力のPQ20RX11。
シャッターを切るとカメラがハングアップするという問題が発生したのでコンデンサを徐々に追加していった。連続してシャッターを切るとハングアップするという厄介な問題に気づいたのは、基板のスペースを全て使い切った後だった。最初から低ESRの大容量コンデンサを盛っておけばよかったと思う。ニチコンのコンデンサが秋月で取り扱いが開始されてる。沢山使うひとはまとめて購入するといいだろう。
PENTAX K100Dはデジタル一眼レフカメラでは珍しく電源に、専用電池ではなく単3形電池4本を採用している。アルカリ電池はもちろん、ニッケル水素充電池(エネループ)やCR-V3リチウム電池も使える。普段はエネループを使用している。
単3形電池の利点は2つ。代替の電池がすぐ手に入ることと、他の機器に電池を使いまわせること。ただ弱点もあって寒くなると電圧が下がり、容量すべてを使いきる前にカメラの電源がオフしてしまうことがある。ニッケル水素電池はもともと電圧が低い為、特に寒さの影響を受けやすい。真冬の屋外で撮影しようとしても容量不足で撮影できないことがしばしばあった。