なんでも作っちゃう、かも。

Arduino/Make/フィジカルコンピューティング/電子工作あたりで活動しています。スタバの空きカップを使ったスタバカップアンプなど製作。最近はもっぱらArduinoと3Dプリンタの自作に興味があります。

Make Controllerはじめました。

Posted by arms22 on 2009年10月28日 0  0

ひょんなことから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を備えている。
ctrl_interface_side.jpg
(Interface Board via MakingThings)


Application Boardは何やら業務機器を思わせる特徴的なスクリューターミナルにバッファ付きADポートが8つ、ハイカレントデジタルポートが8つ、サーボコントローラが4つ、8 DIPスイッチにトリムポット、EathernetとUSBを備える。かなり豪華な仕様だけにその分すこし高い。けど、お手軽に大きな機器を制御できるボードだ。
kit20_askew.jpg
(Application Board via MakingThings)


Arduino Duemilanove 328と比較してみた。

機能Arduino Duemilanove 328Make Controller w/Interface BoardMake Controller w/Application Board
マイクロコントローラAtmega328AT91SAM7X256(ARM7)
動作電圧5V3.3V
入力電圧7~12V7~12V
デジタルI/O14本35本1A出力:8本、ステータスLED:4本、サーボモータ出力:4本
アナログ入力6本 (10ビット)8本(10ビット)
PWM6本4本4本(1A出力ハーフブリッジ回路に接続)
シリアルポート1本2本1本
USBあり(仮想シリアルポート)あり(仮想シリアルポート、HIDマウス・キーボード)
Ethernetなし(イーサーネットシールドで追加可能)10/100Mビット(TCP/UDP/DHCP/DNSサポート)
通信SPI/TWISPI/TWI/CAN
フラッシュメモリ32K256K
SRAM2K64K
EEPROM1K32K
OSなしFreeRTOS
クロック周波数16MHz55MHz(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/



Make: Technology on Your Time Volume 08

オライリージャパン
売り上げランキング: 5211




Arduinoで遊ぼう - 大容量EEPROMに毎日の温度変化を保存する

Posted by arms22 on 2009年10月24日 4  1

Arduinoと大容量EEPROMとCOMS温度センサS8100B

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を選んだ。
EEPROMを選ぶときは動作電圧とマイコンとのインターフェースに気をつけよう。Arduinoと接続する場合は5V動作、I2CインターフェースのEEPROMがおすすめ。



温度センサ


温度センサには秋月で買ったS8100Bを使った。S8100Bは-20℃から+80℃までの温度を測定できる温度センサICだ。トランジスタみたいな形をしていて、ラベルを正面にして左からVOUT、GND、VDDとなっている。VDDに5Vを接続してやれば、VOUTから温度に応じた電圧が出力される。1℃温度が上がると約-8mV電圧が下がる、右肩下がりの特性になっている。S8100Bの温度と出力電圧の特性をグラフ化した。
s8100b_temp_vout_chart.png
(S8100B 温度-出力電圧 特性)



Arduinoと接続する


I2C EEPROMと温度センサS8100B接続図
(図の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");
}



Arduinoをはじめよう
Arduinoをはじめよう
posted with amazlet at 09.10.27
Massimo Banzi
オライリージャパン
売り上げランキング: 3641



Arduinoで遊ぼう - JPEGカメラモジュールで写真を撮る

Posted by arms22 on 2009年10月13日 56  0

JPEGカメラモジュールとArduino

SparkFunで取り扱っているJPEGカメラモジュール(C328-7640)は解像度640x480のカラー静止画をJPEG圧縮して出力するモジュールだ。マイコンとの接続はシリアルでたった4本のワイヤでArduinoと接続、制御することができる。スナップショットコマンドを送ると撮影した画像をJPEGで圧縮してシリアルで送信する。日本だとスイッチサイエンスさん、ストロベリーリナックスさんで買える。今回はこのJPEGカメラモジュールを使って静止画を撮影し、Processingの画面に撮影した画像を表示してみよう。

jpeg_camera_snapshot_sample.jpg
※夜に撮影したのでちょっと画像が荒い感じ。昼に撮ればもう少し綺麗になると思う。

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と接続する


JPEGカメラモジュール接続図
このモジュールの電源は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 ..." );
  }
}



Arduino Uno SMD
Arduino Uno SMD
posted with amazlet at 11.02.02
スイッチサイエンス
売り上げランキング: 23827



Arduinoをはじめようキット
スイッチサイエンス
売り上げランキング: 1910



MTM04ワークショップ準備。

Posted by arms22 on 2009年10月12日 0  0

スタバカップアンプ部品
俺史上初、部品数約300、部品代で2万超え。トレーいっぱいに部品を盛ったときのこの優越感はいったい何だろう。。

MUSEのキラキラした緑色のコンデンサはとっても綺麗だ。赤とか青とかオレンジとか何色かあれば色々混ぜて購入するんだけどな。

あ、そうそう。積層メタライズドポリエステルコンデンサの水色は、タチコマブルーと勝手にそう読んでいます。

ブレッドボードミニ!

Posted by arms22 on 2009年10月04日 0  0

3976533684_357e288d70_b.jpg

ストロベリーリラックマリナックスからブレッドボードミニが届いた。ICとか抵抗とかコンデンサとかも発注しないと。。それほど数はでないから部品代は高くなってしまう。あともっとカラフルな部品がほしいよなぁ。ピンクや赤のコンデンサとかさ。



Arduinoをはじめよう
Arduinoをはじめよう
posted with amazlet at 09.10.03
Massimo Banzi
オライリージャパン
売り上げランキング: 5648




PENTAX K100D用外付けバッテリーパック

Posted by arms22 on 2009年10月03日 0  0

external battery pack for pentax k100d 1

external battery pack for pentax k100d 2
PENTAX K100D用の外付けバッテリーパックを作った。電池の横の小さな回路はレギュレータで単3形電池6本=約9Vを降圧して6.5Vを作る。これをACアダプタとしてカメラに繋げる。レギュレータは秋月で買った可変型低ドロップ1A出力のPQ20RX11。

シャッターを切るとカメラがハングアップするという問題が発生したのでコンデンサを徐々に追加していった。連続してシャッターを切るとハングアップするという厄介な問題に気づいたのは、基板のスペースを全て使い切った後だった。最初から低ESRの大容量コンデンサを盛っておけばよかったと思う。ニチコンのコンデンサが秋月で取り扱いが開始されてる。沢山使うひとはまとめて購入するといいだろう。


PENTAX K100Dはデジタル一眼レフカメラでは珍しく電源に、専用電池ではなく単3形電池4本を採用している。アルカリ電池はもちろん、ニッケル水素充電池(エネループ)やCR-V3リチウム電池も使える。普段はエネループを使用している。

単3形電池の利点は2つ。代替の電池がすぐ手に入ることと、他の機器に電池を使いまわせること。ただ弱点もあって寒くなると電圧が下がり、容量すべてを使いきる前にカメラの電源がオフしてしまうことがある。ニッケル水素電池はもともと電圧が低い為、特に寒さの影響を受けやすい。真冬の屋外で撮影しようとしても容量不足で撮影できないことがしばしばあった。

該当の記事は見つかりませんでした。