Arduino
一つ上に移動はじめてのArduino

今ギョーカイで話題の(何の業界だよ(゚o゚)\バキ) Arduino( http://www.arduino.cc/ ) を遅ばせながらワタクシも組んでみました、ブレッドボードで♪
ここ1,2年ずっとArduinoの存在は知っていて、Make:Blog で盛り上がってるのを見て使ってみようとは思っていたのですが、毎度のことのようにワタシの怠惰な性格が災いして、部品を用意しただけで完成した気になって半年?1年?ほど放置プレイしていたのですが、沖縄からオシゴトで横浜に滞在している友人(とワタシは信じている(゚o゚)\バキ)鴨澤氏が「呑み屋で酒呑みながら Arduino を組たーい」と突然言いだし、部品以外は何も準備していないワタシも居酒屋で電子工作なんてシュールでオモロイと軽い気持ちで承諾したのをきっかけにプロジェクトが始動しました(わらい
そんなワケで、Mac とブレッドボード以外、必要なブツを何も持っていない鴨澤氏をナビゲートし部品を揃えるところからスタート。たまたま印刷してあった Arduino Diecimila の回路図( http://www.arduino.cc/en/uploads/Main/Arduino-Diecimila-schematic.pdf )を元にパーツを揃えることに。と言っても全部揃えても組むのが面倒なので必要最低限に押さえていきます。
| ATmega168 | 1 | マルツパーツ |
| USB - シリアル変換(AE-UM232R) | 1 | 秋月電子 |
| 16MHz セラロック | 1 | 同上 |
| 1kΩ抵抗 | 3 | 千石電商’ |
| 10kΩ抵抗 | 2 | 同上 |
| LED(赤) | 1 | 秋月電子 |
| タクトスイッチ | 1 | 同上 |
結局、鴨澤氏の友人のケータイが電波が入ると言うことでネットで調べたりしたものの、その前にワタシが酔っぱらってきて使い物にならなくなったため、その日は失敗に終わってしまいました(゚o゚)\バキ
とまーヒジョーに情けない結果に終わってしまったので、家に帰りちゃんと(?)調べ直しました。
上の写真のように USB-シリアル(TTL)変換アダプタによる ISP 接続に挑戦してみました(RS232 側の端子の数字は D-Sub 9pin の場合のpin番号)...
んー、どうにもこうにも AVR が ISP モードに切り替わってくれません(泣)。もっとも、パラレルポートを使った STK-200 モドキを使えば簡単かつ速く(書き込み速度)できるのですが、いかんせん Mac にはパラレルポートは無いため繋ぐことすら不可能(USB - パラレル変換って手もありそうだけど、ワタシが調べた限りでは Mac OS 以外を含めても事例が見付からなかったです。)。

ということで、USB - シリアル(TTL)変換基板から手持ちの USB - RS-232 変換ケーブル挑戦することにしました。ちなみに今回は、手持ちのツェナーダイオードが 3.0V のモノと 3.6V のモノしかなかったので電源電圧を USB から失敬していた 5V から 独立電源の 3.3V に変更してますが、もしこれからヤル場合は 5V のツェナーダイオードにして電源も USB から取った方がラクにできます。
接続が完了したところで、avrdude で接続実験...今度は上手く繋がったようです。どーも、USB - シリアル(TTL)変換基板の制御信号出力を反転させればいいような気がしますが、その辺の設定は Windows 用設定ソフトでやるようで、Mac や Linux などからは出来ないみたい。
つーことで、接続の確認が出来たところで、Arduino Bootloader と一緒に落としてきた Makefile を書き換えてから、make してみました。
Makefile 変更前
# enter the parameters for the avrdude isp tool
ISPTOOL = stk500v2
ISPPORT = usb
ISPSPEED = -b 115200
Makefile 変更後
# enter the parameters for the avrdude isp tool
ISPTOOL = dasa
ISPPORT = /dev/cu.PL2303-0000103D #USB-シリアル変換アダプタのデバイスファイル名
ISPSPEED = -b 115200
Bootloader の書き込みコマンド(Arduino Diecimila の場合)
hoge:Bootloader isi$ make TARGET=diecimila isp
これで、一応書き込み出来るのですが...それにしても遅せぇーーーー!(゚o゚)\バキ
Bootloader のデータ量は 15kB 程なのですが、1時間経っても2%位しか進んでいないです(ぉぃ
このままでは全部書き込みが終わるのに1日仕事になりそーだし、そんなに待ってられん、つーことでシリアルでの書き込みは中断して、Makefile を書き換え、以前作った USBasp で書き込むことにします。
Makefile を USBasp 用に書き換えたところ。
# enter the parameters for the avrdude isp tool
ISPTOOL = usbasp
ISPPORT = usb
ISPSPEED =
今度は4,5分で無事書き込みが終了♪早速ブレッドボードに USB-シリアル(TTL)変換基板と ATmega168 を載せ簡易版 Arduino を組み立てて動かしてみました。
ところが、プログラム書き込みに失敗。つーか、↓回路図写真中央の赤丸部分(右下の赤丸ぢゃないよん)は何なんだろう?
R2,R3 ってことは抵抗だろうなー、と思いテキトーに(1k,4.7k,10k とかそんな感じ)抵抗を入れていたのですが、よく分からず。つーか、Arduino Software が通信タイムアウトエラー出すまでずっとリセット状態のままぢゃない?つまり、ブートローダーが起動してない状態のままですから当然通信なんてしてくれないワケでして、ならばいっそのこと R2,R3 のことは無視しして何も繋がずに、Arduino Software の Upload ボタンをクリックしたらソッコーでリセットボタンを押す作戦に変更し、再挑戦...
おっ、今度は上手く行ったぞ♪
どーやら、予想的中したみたいっす♪ということで何も繋がないで正解みたい。つーか、マニュアルにはそー書いてあるのかしらねー(ちゃんと読めよ<ヲレ)?
それにしても、この方法は面倒くさいし、ちょっとダサ過ぎやしないか?なんかこーもうちょっとスマートにしたいところ。R2,R3 はUSB-シリアル変換(TTL)の RTS,DTR に繋がっていて、それらの端子はシリアル通信を開始すると H→L になるので、これを上手いこと使えば書き込み時にリセットボタンを押す必要もなくなるのではないか?
つーことで、R2 のところに抵抗ではなく、0.1uF のコンデンサを入れてやることにして、0.1uF のコンデンサが充電される間の短い時間だけリセットが掛かるようにしたところ上手く行きました♪
成功して気をよくしたワタシは「ああ、ヲレってスーパーハッカーぢゃねー?」なんて調子に乗ってたら、Arduino のサイトにある Hacking コーナーに同じネタがあってガッカリしました(ばき

そんなワケで、回路を理解できたところで、コイツをユニバーサル基板に組み上げて、isiduino (ぉぃ)にしてみました。ATmega168が乗った親基板に 秋月 USB-シリアル(TTL)変換基板が乗った親子亀構成で、ケチなワタシは変換基板を外せるようにしています。
と、一応完成したのですが、各端子に信号名がないので使いにくいです。まー調べれば良いんだけど、それでは何のために基板にしたのかワカランしねー。でも、変換基板を外せるってのはいいよねー(誰に言ってるんだ?)。変換基板は Gainer とかでも使い回しできそうだしね♪
2008.04.01 訂正
2枚目の手描き回路図にあるツェナーダイオードの表記が間違ってました。正解はコチラ。
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
Arduinoで液晶遊び

前回のエントリーで作った isiduino でナニしようかとあれこれ考えていたところ、秋月で買ってきた液晶モジュール(SC1602BS-B)を発見したのでコイツを動かしてみようとゆーことにしました。そこで、まずはモジュールに付いてきたマニュアルを見ながらテキトーに isiduino に接続。あとは、初期化コードを送ったり表示データを送ったりして表示させるんだけど、マニュアル見てたら面倒になってきた(ぉぃ
そんなワケで、Arduino のサイト にサンプルコードでも無いかと探り入れたらやっぱりありました♪
サンプルコードと言うか、ライブラリ化されてました♪
Arduino Liquid Crystal Library LCD Interface
http://www.arduino.cc/en/Tutorial/LCDLibrary
サイトの指示に従い結線をやり直した後、ダウンロードしたファイルを” /<インストールしたディレクトリ>/arduino-xxxx/lib\targets/libraries/ ”にコピー・・・んっ?そんなディレクトリねーぞ(わらい)。どーも後のバージョン( arduino-0010 )でディレクトリ構成が変わってしまったよーです。つーことで、イロイロいじってみたところ、” /<インストールしたディレクトリ>/arduino-xxxx/hardware/libraries/ ”にコピーするとヨロシイよーなので、そこにコピー。

コピーした後、Arduino Software を起動し、[Sketch → Import Library]の順でクリックすると、 上のスクリーンショットのように ”LiquidCrystal” と表示されるようになり、これで使えるようになるハズ・・・
あれれ、メッセージウィンドウに何かエラーが出てるし(゚o゚)\バキ
#インデントが入っている行は前の行の続き
LiquidCrystal.cpp:8: error: declaration of C function 'void pinMode(int, int)' conflicts with
/arduino-0010/hardware/cores/arduino/wiring.h:74: error:
previous declaration 'void pinMode(uint8_t, uint8_t)' here
LiquidCrystal.cpp:9: error: declaration of C function 'void digitalWrite(int, int)' conflicts with
/arduino-0010/hardware/cores/arduino/wiring.h:75: error:
previous declaration 'void digitalWrite(uint8_t, uint8_t)' here
LiquidCrystal.cpp:10: error: declaration of C function 'int digitalRead(int)' conflicts with
/arduino-0010/hardware/cores/arduino/wiring.h:76: error:
previous declaration 'int digitalRead(uint8_t)' here
エラー内容を見てみると、どーも呼び出している関数の引数の型があってないよーです。バージョンが新しくなって、型を変えたよーで、具体的には、pinMode,digitalWrite,digitalRead 関数の引数が int 型(確か16bit...だっけ?)から uint8_t 型(8bit)に変わってました。
ということで、Liquid Crystal ライブラリのソース(LiquidCrystal.cpp)を変更します。
変更前extern void pinMode(int, int);変更後
extern void digitalWrite(int, int);
extern int digitalRead(int);
extern void pinMode(uint8_t, uint8_t);
extern void digitalWrite(uint8_t, uint8_t);
extern int digitalRead(uint8_t);
これで、エラーもなくArduino Software が起動できるようになり、Liquid Crystal ライブラリが使えるようになりました♪
と言うことで、早速以下のよーなコードを書いて(実際にはライブラリに付いてきたサンプルコードを改造)動作実験♪
#include <LiquidCrystal.h> //include LiquidCrystal library
LiquidCrystal lcd = LiquidCrystal(); //create a LiquidCrystal object to control an LCD
char string1[] = "Hello World!"; //variable to store the string "Hello World!"
void setup(void){
lcd.init(); //initialize the LCD
lcd.printIn(string1); //send the string to the LCD
}
void loop(void){
}
・・・ありり?フンともスンとも言わないぞ(゚o゚)\バキ
そもそも、端子に信号名書いてないから、どこにナニが繋がってるのよく分からず、ちゃんと繋がってるのかすらアヤシイです(ぉぃ
とゆーことで、どこにナニが繋がってるのかを確かめるべくマルチメーターでチェケラしてみると・・・
1カ所イモハンダになってました(ぉぃ
問題の箇所をハンダし直して、もう一度挑戦すると、今度はちゃんと表示しました♪
でも、何か1行しか出てません。件の LCD Library のページ見ても1行しか出てないし、試しに1行分(16文字)以上の文字を出してみても、入りきれない分がちょん切れるだけで2行目にはナニも出ません。そんなワケで、液晶に付いてきたデータシートで確認してみると、初期化の時に2行表示にするか、1行表示にするか決めるよーで、ライブラリの初期化コードでは 1行表示モードに設定されているよーなので、LiquidCrystal.cpp のソースにある初期化コードを変更してみることにしました。
ちなみに、ライブラリのソースをいじった後は、Arduino Software を再起動するか、ライブラリのオブジェクトファイルを消してやってからぢゃないと変更内容は反映されないよーです(ワタシは後者で対応。make みたいに、ファイルの変更を検査してコンパイルしてくれればいいんだけど...)。
変更前(22行目)
#define init1 0x30
変更後
#define init1 0x38
すると、今度はちゃんと2行表示モードになりました♪
でも、この液晶には改行とゆー概念はないよーで(普通無いモノなの?)、行の途中で改行したいときは行の終わりまでスペースを入れなきゃならんの?などと思ったのですが、マニュアルで表示開始位置を決められるよーで、改行したくなったら表示開始位置を決めるコマンドを送ってやることで改行することが出来るようになるようです。
表示開始設定コマンド(2進数)
1xxxxxxx # x=開始位置アドレス7bit(先頭の1bitがコマンド)
今回買った液晶では 01000000b(16進では 40h)が2行目の先頭のアドレス(位置)になりますので、Arduino Software のコードでは以下のよーになります。
<オブジェクト>.commandWrite(0xC0);
そんなワケで先のコードを使って今度は2行表示のプログラムを作ってみました。
#include <LiquidCrystal.h> //include LiquidCrystal library
LiquidCrystal lcd = LiquidCrystal(); //create a LiquidCrystal object to control an LCD
char string0[] = "Hello World!"; //variable to store the string "Hello!"
char string1[] = "Hoge Hoge";
void setup(void){
lcd.init(); //initialize the LCD
lcd.printIn(string0);
lcd.commandWrite(0xC0);
lcd.printIn(string1); //send the string to the LCD
}
void loop(void){
}
上のコードを実行するとこんな感じに♪

とゆーことで、成功しました♪
それにしても、改行するだけのために、いちいちコード書くのはイヤだ。普通のプログラム言語みたいに、文字列中に ”¥n" があったら改行して欲しいっす。ライブラリのソースいじれば出来るんだけど(もちろんプログラム本体のソースいじっても良いんだけど、ライブラリに有った方が使い回し効くし)、でも今回はもう面倒なのでパス(ぉぃ
その代わりと言うか何というか、この液晶は一応、JIS X0201 に準拠しているので SJISの文字コードを送ってやればニホン語も表示可能です。と言っても2バイト文字は扱えないので、半角カタカナだけですが(゚o゚)\バキ
ということで、早速ニホン語のメッセージを書き込んで・・・と、行きたいところですが、どーも、Arduino Software は IM に対応してないらしくて(ATOK がダメなだけ?)、日本語を入力しようとしても受け付けてくれません。そこで、Arduino Software を一旦終了して、ソースファイルをテキストエディタで編集してからもう一度 Arduino Software で開くということをやって何とか入力(表示はちゃんと出来ました)(゚o゚)\バキ
#include <LiquidCrystal.h> //include LiquidCrystal library
LiquidCrystal lcd = LiquidCrystal(); //create a LiquidCrystal object to control an LCD
char string0[] = "コンニチハ セカイ";
char string1[] = "Hello World!"; //variable to store the string "Hello!"
void setup(void){
lcd.init(); //initialize the LCD
lcd.printIn(string0);
lcd.commandWrite(0xC0);
lcd.printIn(string1); //send the string to the LCD
}
void loop(void){
}
見事に文字化けしてますね♪
そしてこの様子を見て、「あっ、これ UTF-8 ぢゃねーかーっ!」とやっと気付きました(ぉぃ
そこでもう一度テキストエディタで開いて SJIS に変換した後にもう一度 Arduino Software で開くと、今度は IDE の方で文字化け♪まぁ、これは当然なんですが、文字化けした状態でコンパイルしようとするとエラー出まくり、問題の文字列をコメントアウトにしてもコンパイルエラーで、問題の文字列を消さないとダメでした。結局、今のところ一文字一文字チマチマと JIS コードに変換して書き込んでいくしか無さそうです。
JIS コードに変換したところ
char string0[] = {0xBA,0xDD,0xC6,0xC1,0xCA,0xA0,0xBE,0xB6,0xB2}; //"コンニチハ セカイ" JIS X0201 charactor code
すると、一番最初の写真のよーになります。
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/arduino-lcd/tbping
ArduinoでDACのじっけん
Arduino に使われている AT mega168 には DAC が無い。analogWrite という関数があるからてっきり DAC を内蔵しているのかと思ったら、PWM 出力だったのね(http://www.arduino.cc/en/Reference/AnalogWrite)(゚o゚)\バキ
LED とかモーターとか動かすには良いんですけど、490Hz までしか出ないので、ちょっと音声とか扱うにはちょっと遅すぎるので DAC を繋いでみようというオハナシ。
早速秋月電子と言う名の部品箱から DAC を取り出し(買ってくるとも言う(゚o゚)\バキ)接続。とりあえず、こんな感じで繋いでみました。0 〜 7 がデータ、9 で DAC 内部のラッチを制御して出力したデータをアナログに変換。
そしてアナログ出力のキホンと言えばやはりサイン波。ということで sin() 関数を使ってサイン波を生成して、DAC から出力してみたのが左の写真。なんかすげー遅いんですけど...ウェイトを一切入れずに出してみたのですが、5.2Hz しか出てません(゚o゚)\バキ
しかもどっかで間違っているみたいで、今回使った DAC は 2.56V がフルスケールなので、2.56Vp-p なハズが、1.7V 位しか出て無いし(゚o゚)\バキ しかも360°で1サイクル終わるはずがなんか途中でチョン切れてるし(ぉぃ
つーことで、余りにもハズカシイことになりそうなので、今回はソース無しってことで(ぉぃ
でもよくよく考えると、8bit 程度の精度で、しかもデータラインを他の周辺機器と共有しないのであれば、抵抗ラダー式の簡易DACで十分ですわねー。
MAKE:It - Proto-DAC shield for Arduino
http://blog.makezine.com/archive/2008/05/makeit_protodac_shield_fo.html
大体、パラレル接続だとピン数を大量に使ってしまうので DAC を繋ぐんだったらシリアル接続がいいですね。
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/arduino-dac/tbping
フルカラーPOVその5
あれから(前回のエントリから)、沖縄旅行したり、自宅サーバーぶっ壊しちゃったり、シゴトでテンパってみたり、ダラダラしてみたり(ぉぃ)と、忙しくてちっとも進んでませんが、細々としたものを時系列無視して(どれが何時やったのかもー覚えてないんですもの(゚o゚)\バキ)、書いておきます。

回転板の固定
今まで、お試し版つーことで、両面テープで固定していましたが、スゲー外しにくくて回転板が割れそうなので、ネジで固定できるよう、プーリと回転板(透明アクリル円盤)に穴を開けて回転板を取り付けました。
写真の各ネジ穴に番号が振ってあるのは、番号を合わせないと穴の位置がズレるからでし(゚o゚)\バキ
プーリ中心部は窪んでいて、ネジで固定する際、回転板とプーリの間に隙間が出来てしまい完全にネジ止めすることが出来ないので、蛍光緑色のアクリル板を丸く切り抜いたものを2枚重ねてスペーサーにしました。色はたまたま在庫していたモノを使っただけで、色に意味は無いのですが、ワタシの工作精度の悪さが凄く目立ってイヤンな感じ(ぉぃ

Full Color POV 回転板に固定
Full Color POV 基板に塩ビ製「足」を接着し、回転板に固定。モノは試しと、この状態でモーターを回してみましたが、机の上で大暴れ。それこそ、飛び上がらんとばかりにバタバタしてました(゚o゚)\バキ
やっぱ重量バランスが悪いとダメだったみたい(当たり前)。流石にいくら手抜きでもバランス用ウェイトを入れないとシャレにならないよーです。

バランスウェイト製作
重量バランスを取るため、モノは試しと手元にある魚釣り用のオモリを Full Color POV 基板の取り付け位置の反対側にガムテで貼り付けてみたのですが、こりゃまたエラいことに・・・
最初は踏ん張るものの、回転が乗ってきた瞬間「スパーンッ!」とどっかに飛んでいってしまいました(゚o゚)\バキ
遠心力ってのはスゴいねぇー(ぉぃ
遠心力のチカラを知りすぎて小便チビりそーになったところで(゚o゚)\バキ、ちゃんと取り付けることにしました。
石膏と整髪料のキャップを使って型を作り、その中に前出のオモリ(と言っても同型品。先に使ったのは行方不明(゚o゚)\バキ)を入れて型の中でヒートガンを使ってオモリを熔かそうとしましたが、一応熔けるものの熱量が足りないみたいで、熔けきらないうちに固まってしまい上手く行かず、カセットコンロと、使い古しのお玉でオモリを熔かしてから型に流し込んで作りました。せっかく、Full Color POV の方は鉛フリーで作ったのに、こんなに鉛を大量投入しちゃったら、鉛 Fully になっちゃうねー(寒

型から抜いた鉛 Fully (もーええっちゅーの)なウェイトにタップでネジを切り、ウェイトの位置を調整できるように回転板にスリット状の穴を開けて取り付けました。
そして、この状態で回してみると、先ほどのように飛んでいきそうな振動は無くなりましたが、回転を止めてみると、どんなにネジを締めてもウェイトは一番外周に移動してしまうようです。
うーむ、スリット状に穴を開けたのは失敗だったかな?
またもや遠心力のパワーに負けてしまいました(゚o゚)\バキ
そんなワケで、ウェイトを入れて回したときのムービーでし(入れる前のも欲しかったけど、それどころぢゃ無かった(゚o゚)\バキ)。
ウェイトがずれて、静止状態でバランスとっても意味がなかったりしますが、無いよりはマシになりました...
が、それにしても、勢いが随分弱くなったなー。可変電源のボリュームを全開にしても絞り切っても回転の仕方が変わらないし、コールドスタートも時々失敗するわと何かヘン。
負荷が増えてるのはよく分かるんだけど...と電圧計で、電源の出力電圧を調べてみると2.5V 位しか出てない。しかもボリュームの位置が何処にあろうが電圧は一定(定格が、4〜9V なので低すぎ)。どーも、可変電源の定格オーバーの電流が必要みたいです。要は電源のパワー不足。プーリ比を変えて低回転で少ないトルクで駆動すればいいんでしょうけど、売られていたプーリで一番デカいのと小さいものの組み合わせで組んでるので、ちょっとそれもムリっぽい...さぁどーしよ?
PWM コントローラーの製作
電源の容量不足ということで、ATX 電源の 12V を PWM でスイッチングしてモーターをブン回そうということで、左図のような回路を考えてみました。
ボリュームで PWM の制御量を設定したのをPWM出力でパワーFETを駆動するだけなんですが、それだけではちょっとマイコンも宝の持ち腐れ状態ですので、オマケとして、7セグLEDとフォトインタラプタを使って回転数(rpm)を表示するようにしようかなと思った次第。
AT 互換機のマザーボードから抜き取ったパワーFETのフィン(ヒートシンク)を生基板にベタっと半田付け。こうすることで、電極とヒートシンクの2つの役割を果たしてもらおうって作戦。続いてリード端子側は、手持ちのストライプパターンのユニバーサル基板を小さく切って、写真のように生基板に接着した上にリード端子を半田付け。こうすることで、リードが不用意に曲がって下の生基板とショートしないようにしました。
その他、電源や GND 端子も生基板の切れ端を下の大きな生基板に接着してから半田付けします。こういう実装方法はよく超高周波回路で使われていましたけど(島基板なんて言い方してたっけ?)、最近見なくなりましたねぇ。
最後にマイコン基板です。と言うかブレッドボードですが。
左の黒いコネクタが刺さっている基板は、ワタシが以前製作した Arduino 互換機の isiduino です。
もう少し余裕が出来るかと思ったのですが、isiduino の I/O 端子の数が足りなくなるということで外付けICの数が増えてしまい、ギリギリのサイズになってしまいました。まー、もっとも設計にあったチップを買ってきて使えばもう少しマシになるんでしょうが、手持ちのパーツで何とかしようとしたのでこんなもんかな?
あと、ブレッドボードが小さいため、LED に必要な電流制限用の抵抗が入って無いので、LED がすげー眩しい...ってそんな呑気な話ではなく(゚o゚)\バキ
消費電力がバカデカくなって居るようで、LED を点灯した状態だとプログラムの書き込みに失敗します(゚o゚)\バキ(゚o゚)\バキ
あと、LED も定格オーバーで動作させていますので、よい子の皆さんはマネしないようにお願いします(ぉ
そーゆーことで、一応それっぽいのがほぼ完成しました。まだ、フォトインタラプタや先に作った FET 回路(島基板)とも繋いでませんが、ブレッドボードが動作するかどうか確認するために以下のコードを動かしてみました。
char X = 0;
char SegmentFont[11] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x67, 0x00};
char DispValue[4];
char digit10 = 0;
char digit100 = 0;
char digit1000 = 0;
int n,m;
int Value = 0;
void setup(){
DDRD=0xFF; //7セグLEDのセグメント出力端子(ポート)の設定:出力
DDRB=0xFF; //7セグLEDのケタ出力端子(ポート)の設定:出力
pinMode(11,INPUT); //フォトインタラプタの入力端子設定:入力
}
void loop(){
delay(1);
Value = analogRead(0); //ボリューム入力端子からアナログ値を入力
//入力値をバイナリからBCDに変換し、LED のセグメントに変換
n = Value;
m = n % 1000;
digit1000 = (n - m) / 1000;
if (digit1000 == 0) digit1000 = 10; //0の場合、ブランク
DispValue[3] = SegmentFont[digit1000];
n = m % 100;
digit100 = (m - n) / 100;
if ((digit1000 == 10) && (digit100 == 0)) digit100 = 10; //上位のケタが0の場合、ブランク
DispValue[2] = SegmentFont[digit100];
m = n % 10;
digit10 = (n - m) / 10;
if ((digit100 == 10) && (digit10 == 0)) digit10 = 10; //上位のケタが0の場合、ブランク
DispValue[1] = SegmentFont[digit10];
DispValue[0] = SegmentFont[m];
//7セグLEDへの出力
PORTD = DispValue[X];
PORTB = X;
X++;
if ( X > 0x03 ) { //7セグLEDの全てのケタが表示したときの動作
X = 0x00; //1ケタ目に戻す
}
}
ボリュームで設定した値を7セグLEDに表示するとゆーシロモノで、isiduino(Arduino)の A/D コンバータの分解能は10bitですので、最大が1023になります。ただ、ブレッドボード使っているのと、電源があっぷあっぷだったり、外付けのボリュームの抵抗値が高いせいか、最下位のケタがふらついてしまいます。
でも、とりあえず動いているみたい(ぉぃ
- 固定リンク
- ¦
- コメント (2)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/fullcolor-pov-005/tbping
フルカラーPOVその6
Arduino で割り込み処理するには
前回のエントリで製作した(と言ってもブレッドボードの仮組だけど)PWM コントローラ兼回転数表示機ですが、回転数を数えるのに基準時間の間にフォトインタラプタのスリットに何回遮光板が通ったかで計測するワケですが、そうなると割り込み処理が必要だなと、Arduino のサイトにあるリファレンス(http://www.arduino.cc/en/Reference/HomePage)を見てもそれっぽいのがどーも見あたらない。「ひょっとして、Arduino には割り込みって無いの?」ということで渋々ポーリングで処理しようということで Arduino Software を起動して書き始めたわけですが、各ステップの動作時間(使用クロック数)がワカランではないか(当たり前)。最悪コンパイラが出したコードを見ながらタイミングをきめれば良いんだけど、そんな馬鹿なという思いが強くなっていったところで、「誰か勝手に作ってるんぢゃないの?」と思いググってみると、なんと、Arduino のサイトに解説があるではないか(゚o゚)\バキ
ということで、Arduino で割り込み使う方法はコチラ(http://www.arduino.cc/en/Reference/AttachInterrupt)。まったくどこに目をつけていたんだ<ワタシ
とよく見ると結構深い階層にあったみたい。ちょっと探しにくいなぁ...というか最初から組み込まれてるライブラリやら関数はリファレンスのページのトップに置いておいていいんぢゃない?<関係者各位
どーも、リファレンスによると、外部割り込みはデジタル入出力ピンの 2 番と 3 番のみが使えるようで、前回組んだ回路を変更(プログラムも変更)しなければならないようです。attachInterrupt 関数の使い方はこんな感じ(だと思う(゚o゚)\バキ)。
attachInterrupt(interrupt, function, mode)
- interrupt(割り込み入力ピン)
- 割り込み入力のピンを 0 または 1 に設定。
- 0:デジタル入出力2番ピン
1:デジタル入出力3番ピン
- function(関数名)
- 割り込み発生時に起動する関数名を設定。
- mode(割り込みトリガモード)
- 割り込みトリガ発生の信号レベルを設定。
- LOW:ローレベルの時にトリガ。
CHANGE:信号レベルが変化した時にトリガ(立ち上がり立ち下がり関係なしに)
RISING:ローレベルからハイレベルに立ち上がった時にトリガ
FALLING:ハイレベルからローレベルに立ち下がった時にトリガ
という具合。外部割り込み二つしかないのー、とかなり不安になる仕様だけど、そんな大規模なもん作るわけでもないだろうからこれでいいのかな?と、釈然としないモノを感じつつカウンター部を割り込みで処理するプログラムを書いてみました。
char X = 0;
char SegmentFont[11] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x67, 0x00};
char DispValue[4];
char digit10 = 0;
char digit100 = 0;
char digit1000 = 0;
int n,m;
int Value = 0;
void setup(){
DDRD=0xFF;
DDRB=0xFF;
pinMode(2,INPUT); //割り込みに使用するピン(2番)を入力に設定
attachInterrupt(0, count, FALLING); /*デジタル入出力ピン1 H→L になったら
count 関数を起動*/
}
void loop(){
delay(1);
//Value = analogRead(0);
/////////// 前回のエントリと同じ内容のため中略)///////////
PORTD = DispValue[X] & 0xFB; /*割り込みピン(2番。セグメントc)をマスクし
LEDセグメント出力*/
PORTB = X | (DispValue[X] & 0x04); /*セグメントcの出力を10番ピンに割り当て、
桁データ出力と合成して出力*/
X++;
if ( X > 0x03 ) {
X = 0x00;
}
}
void count(){ //割り込みイベント処理関数
Value++; //カウンタ値を1up
pinMode(2,OUTPUT); /*入力ピンを出力に切り替えると割り込みが掛からなくなる
らしい?(゚o゚)\バキ*/
delayMicroseconds(10000); /*10msecウェイト(チャタリング防止...なるのか?)
msec単位であれば、通常delay()なのだが、割り込み
処理で使うと固まってしまうみたい*/
pinMode(2,INPUT); //入力に戻す(割り込み許可)
}
と、まぁ、こんな感じです。あと必要なのはタイマ割り込みですが、これはまた次回にということで、ごきげんよー(ぉぃ
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/fullcolor-pov-006/tbping
フルカラーPOVその7
前回のエントリーで宿題にしていたタイマー割り込みを使ってみました。
いつものように、Arduino のリファレンスページ(拡張版:http://www.arduino.cc/en/Reference/Extended)でそれっぽいエントリーを探してみたもののちっとも見付からず、「タイマー割り込みなんて、組み込み系では真っ先に必要とされるハズなのになんでねーのよー」と釈然としないままライブラリのページ(http://www.arduino.cc/en/Reference/Libraries)を捜索してやっと発見・・・えー、なんで標準装備してないんだ?
とゆーことでライブラリのページにあった MsTimer2 (http://www.arduino.cc/playground/Main/MsTimer2)を使ってみることにしました。
MsTimer2 のページからライブラリのソース(http://www.arduino.cc/playground/uploads/Main/MsTimer2.zip)をダウン道路したら展開し、/{Arduino Software が入ったディレクトリ}/arduino-0011/hardware/libraries/ に展開して出来たフォルダごとコピーしてから、 Arduino Software を再起動し(ソフトウェア起動時にインストールされたライブラリをコンパイルするため)、Program Notification area (黒地のエリア)にエラーが出ていなければ準備完了。
このライブラリでインストールされる関数はこんな感じ。
- MsTimer2::set(設定時間(ms), 割り込み処理関数名)
- ・タイマ割り込みの設定。
- 設定時間(ms) :設定時間(符号無しlong型)をミリ秒単位で設定。
割り込み処理関数名:割り込み発生時に実行する関数名を設定。
- MsTimer2::start()
- ・タイマ割り込み有効化
- MsTimer2::stop()
- ・タイマ割り込み無効化
使い方がなんかイマイチ洗練されていない気がしますがまぁいいか(ぉぃ
とりあえず、こんな感じで使ってみました(重要な点だけコメント入れてます)。
#include <MsTimer2.h> //標準ライブラリぢゃないので、ヘッダファイルをインクルード
//////////////////////////中略///////////////////////////
int Value = 0;
int count =0;
void setup(){
DDRD=0xFF;
DDRB=0xFF;
pinMode(2,INPUT);
attachInterrupt(0, counter, FALLING); //外部割り込みの設定(前回のエントリ参照)。
MsTimer2::set(1000, flash); /*タイマ割り込みの設定 1000ms
割り込み処理関数=flash */
MsTimer2::start(); //タイマ割り込みイネーブル
}
void loop(){
//////////////////////////中略///////////////////////////
}
void counter(){ //外部割り込み発生時の処理。
count++; //カウンタを1up
}
void flash(){ //タイマ割り込み発生時の処理。
Value = count * 60; //サンプリング期間が1secなので、分速に変換するため60倍に
count = 0; //カウンタクリア
}
ソフトウェアが出来たところで、ハードウェアを取り付けます。と言ってもお試しなので、超テキトー(゚o゚)\バキ
フォトインタラプタの遮光板をどーしよーかなーと、パーツ屋を覗いていたらギアを発見。こいつにスリットを入れて遮光板にすることにしました。
んー、我ながら凄くゼータク(゚o゚)\バキ
でまー、写真のように金ノコで切り込み入れたはいいけど曲がってるし(笑)。
つーか、やってる途中で気付いたけど、スリットぢゃなくて、歯車の歯を検出させれば手間も掛からないし精度も高かった気がする(゚o゚)\バキ(゚o゚)\バキ
まだ仮止めなので、ユニバーサル基板の切れ端の先端にフォトインタラプタを両面テープで固定したものを 006P 電池の上にセロハンテープで取り付けました(゚o゚)\バキ
フォトインタラプタへの配線は、見ての通り空中配線でし(もっと拡大して見たーい)。
無負荷状態で電源も絞りきった状態で 1860rpm で回ってる模様。
その後、ボリュームを上げて2500rpm ほどまで上げましたが、やかましいのでそれ以上上げるのはやめました(゚o゚)\バキ
ちなみに回転台の下にタオルを敷いているのは回転中、振動が激しくてウルサイからでし(笑)。
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/fullcolor-pov-007/tbping
フルカラーPOVその9 ー いきなり完成
そんなワケで、ずっと更新してませんでしたが、いきなり完成しました(ぉぃ
この写真は、Make: Tokyo Meeting 02 とゆーイベントにこっそり持ち込んだのを友人のこの方に撮っていただいたもの。と言うわけで、5月の始めから着工開始したので、約半年掛けてやっと動作する状態までこぎ着けることが出来ました♪
半年も掛かってるクセして、ディテールはやっつけ仕事丸出しなのは、腕はさておきワタシが怠惰なのが主な原因で、実は前回のエントリの状態からこの形に仕上げるのに本業をやりつつ3,4日、工程が少ないのかワタシの仕事が早いのかヨーワカランけど、そんなに慌てなくても日頃から少しずつやれば片付いてるぢゃーん。つーか、最初のイメージでは1ヶ月ぐらいで出来るつもりでした(゚o゚)\バキ
ということで、その顛末をば。
本体フレームの加工
写真では中身入っちゃってますが、中身全部外して写真撮り直すの面倒なのでそのままで(ぉぃ
上の透明円盤(天板)は t5 アクリル板 φ200。下の円盤(底板)は t5 塩ビ板 φ200で、四隅の金属棒は支柱で10mm角 x 60mm。なぜ天板と底板で材質が違うかというと、手持ちのアクリルないし塩ビの板から2枚材料が取れなかったから(゚o゚)\バキ
材料は四角い板からジグソーを使って大まかに切り、バイスで固定したディスクグラインダーで削って仕上げるとゆー方法でヤリました。支柱のアルミ材は前作のフレームのをそのまま利用しました。
モーターコントローラ基板の製作
前回のエントリの時の回路から大きく変わったのはいいのですが、変更したときに描いたハズの回路図がどこにもない(と言うかホントに描いたのかすら怪しい(゚o゚)\バキ)。変更してから時間も経っており微妙に覚えて無くて、結局バラしかけたブレッドボードを元に戻してワイヤーを追いかけたり、それでもよく分からない所はプログラムのソースコードを見たりして回路を解読しました(゚o゚)\バキ
で、よせばいいのにブレッドボードの回路を更に変えてトランジスタアレー(TD62003)を 2SC1815 x4 に変えて部品ケチったりしました。基板は毎度お馴染みのユニバーサル基板(裏側の写真はコチラ)。こんな急な回路変更でも即座に対応できるのが良いね♪
基板上の 28pin IC は自作 Arduino コンパチ機 isiduino のニューバージョン(これについては後日別のエントリにて)。LM350の下にある銅箔はノイズ対策用の銅箔シールを切ったもので、念のための放熱用。
電源基板の製作
写真は基板の裏側。大電流が流れるところなので先に出た銅箔シールと同じ物を使って配線しました。本来ならプリント配線にするべきところですが、薬品使ってエッチングしたり、リューターで削り出すのも面倒なのでインチキしてます(゚o゚)\バキ
表側には、大電力のスイッチングによって起きる電圧の変動を押さえるための大容量アルミ電解コンデンサとアルミ電解コンデンサでは取り切れない高い周波数のリプルを吸収するフィルムコンデンサ、大電力をスイッチングするモータードライブ用のパワーFET(SUP85N15-21)、LED による簡易パワーインジケーターを実装しました(写真はコチラ)。
フォトインタラプタとGND側電極ブラシ取り付け
短冊状に切ったユニバーサル基板にフォトインタラプタとフォトインタラプタ用の抵抗と回転部(ターンテーブル)上のPOVに電源を供給するための電極ブラシ(t0.1リン銅板)を半田付けしたものを、10mm角のサイコロ状にカットしたアクリルにタップを切ったものを天板と底板に接着したところに写真のように固定。ターンテーブルのシャフトがGNDになります。
リン銅はバネのように弾力があるので、その弾力を活かして常にシャフトに接触するように折り曲げたりして配置するのがコツ。なんかこの辺はワタシ的には初の試みなので超不安でした(゚o゚)\バキ
ターンテーブル側電極ブラシ(Vcc)の取り付け
ユニバーサル基板の小片にt0.1リン銅板を半田付けしたものをターンテーブルのプーリにエポキシ系接着剤で固定。そこからAWG26(?)のビニール線(パソコンに使うフラットケーブルを裂いたもの)を使って配線。プーリに開けた穴(φ3)を通して反対側へ出るようにしました。
固定電極(Vcc)の取り付け
いつもの銅箔シール(笑)をドーナッツ状に切り写真のように天板に貼り付け、天板に穴を開けビニール線を通し半田付け(写真手前の白いもの。配線の種類は先のGND側のブラシの配線と同じもの)。
銅箔シールに擦り傷のようなものがありますが、これはターンテーブルの電極ブラシが通った跡です。
先の工程のブラシとはこんな感じに接触します。
スイッチ・ボリュームの取り付け
以前に途中まで(頭頂部の切除(゚o゚)\バキ)加工していたヘルメットに電源スイッチと回転速度調節用ボリュームを取り付けます。
写真右から電源スイッチ、回転速度調節ボリューム、謎のスイッチ(゚o゚)\バキ謎のスイッチは操作しても何も起こらないんですが、なんか電源スイッチとボリュームの二つだけだと寂しいしと言うことで付けました(ぉぃ)。でも一応メイン基板のマイコンには繋がってますので、将来何かに使うかも知れません。
ちなみに中の様子はこんな感じ。
ターンテーブルの配線
GND 側の配線は t0.1 リン銅板をドリルの刃とバイスを使って曲げ加工したものにAWG#26ビニール線を半田付けしたものをシャフトに固定。Vcc側は先の工程でプーリを貫通させた配線をさらにターンテーブルのアクリル板を貫通させて引き出しました。
POV基板側は引き出した配線を半田付けしてしまうとターンテーブルとプーリが分離できなくなってしまうので、このようにしてコネクタ接続としました。
間に合わなかったー(ぉぃ
当初バッテリー駆動させる予定でしたが、Make: Tokyo Meeting 02 (MTM2)に間に合いませんでしたので、電源ケーブルを長くし、ATX 電源に繋ぐことになってしまいました。バッテリーは一応用意してあったんですけど、充電器の製作が間に合いませんでした。
しかもこのケーブル、MTM2 の会場で加工してました...スゲー迷惑なヤツだ<ヲレ(゚o゚)\バキ
一応完成♪
本体フレームとヘルメットを12mm幅アルミ平板で固定し、電源,ボリュームの配線をして完成(後ろ側はこんな感じ)。
先に結果を写真で示したのでアレですが、この時点で一度も通しで動作チェックせずにMTM02会場に乗り込み動作させるなんて我ながら大した度胸だと思います(゚o゚)\バキ(゚o゚)\バキ
まぁ、最低ターンテーブルの上にある POV 回路だけはプロジェクトの初期から完成していたので、最悪そいつを手で振り回すって手もありますが(ぉぃ
何といいますか、やっぱ一夜漬けパワーは最強ですなぁ(しみじみ)(゚o゚)\バキ
つーか、こー上手いこと一夜漬けパワーと同じ物を余裕のあるときにも発揮できればなぁと常々思うんですが何か良い方法無いかしら?
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/fullcolor-pov-009/tbping
Arduino プログラマの設定
Arduino に出会う前、ワタシは Mac OS X で C でコードを書き gcc でコンパイル、USBasp を使いターゲット(AVRマイコン)にプログラムを書き込み開発してましたが、Arduino Software からはデフォルトでは USBasp でブートローダーの書き込みが出来ず、自作 Arduino 互換機こと isiduino のブートローダーの書き込みするときは(Arduino のアプリケーションの開発ではブートローダーの書き込みは一度で良いが、isiduino を何個も作るときは当然作った個数分だけ行う必要がある)いちいちコマンドラインに入ってから avrdude を使って書き込みを行っていました。
しかし、これでは余りにも不便だし、 Arduino Software の中身を見るとソースのコンパイルには avr-gcc、ターゲットへの書き込みは avrdude が使われていることが判明。つまり、今まで使っていた環境と同じ物がバックグラウンドで動いていたと言うことで、添付のドキュメントを元に Arduino Software の設定ファイルを見たのですが、どーもワカランつーか、プログラマ(ライタ)に関する記述がドキュメントにねーし(泣)。Arduino 本家のサイトにもそれらしい記述が見付けられなかったので(また前みたいに探し切れてなかっただけかも)、Arduino Software の全ソースを落としてきて X code でビルトしようということに...
ところが、ソースをコンパイルするとエラーが発生(゚o゚)\バキどーも、コンパイルではなく、リンカか、AVR 用のコードまで、X code の gcc でコンパイルしてるっぽい感じ。そんなワケでソースを見ると、どーもプログラマの設定は設定ファイルを参照してるみたい。要するに、ソースなんて落とす必要なんて全く無かったってこと(゚o゚)\バキ
と、言うことで落としてきたソースはとっとと捨てて(゚o゚)\バキ 最新の Arduino Software (0012)を落としてきて、ソイツの中身をいじることにします。そして、見つけ出したのが programmers.txt とゆーファイル(左スクリーンショット参照)。コイツを弄って USBasp のエントリーを作成すれば使えそうなので、他のプログラマの設定を参照しつつ、以下のような感じのエントリを先述のファイルの最後に書いてみました。
usbasp.name=USB asp
usbasp.protocol=usbasp
設定ファイルを変更したら、Arduino Software を起動し、メニューバーにある「Tools」→「Burn Bootloader」とクリックし、ちゃんと USBasp が表示されているか確認すると、ちゃんと表示されてました。勝手にソートされちゃってますけど、どーも、そーゆー仕様らしいです。
つーワケで、これで Arduino Software 一つでブートローダーの書き込みから、アプリケーションの開発が出来るようになりました。めでたしめでたし(ぉ
- カテゴリ
- Arduino
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/arduino-programmer-setting/tbping
Arduino を ATmega88 に移植してみました
isiduino mini 誕生
ある日、いつものように秋月電子をうろついてると ATmega88 が 250円で売られているのを発見。「んー、これが168だったら isiduino (自作 Arduino 互換機)に使えるのに...」と口惜しい思いをしつつも、Arduino 化せずにそのまま使えばいいやと購入して帰ったのですが、ATmega88 と 168 の違いは単純にフラッシュメモリの容量だけであとは全く同じ(ちなみにラインナップはこんな感で、ATmega48=4kB,88=8kB,168=16kB,328=32kB となっている)。ワタシが書く Arduino のスケッチなんて3kB満たないのが普通なんだから、ATmega88に移植しても問題ないだろう(Arduino Diecimila を移植した場合、ブートローダーに 2kB 程使うので、約6kB使用可能)つーことで移植に挑戦してみました。
ブートローダーの移植
まず、ATmega168 用のブートローダーのソースが入ったフォルダ(atmega168)をコピーし、「atmega88」にリネーム。コピーしたフォルダを開き、ソースのファイル名も紛らわしくなるので、「ATmegaBOOT_88.c」に変更。それに合わせて Makefile も編集。Makefile で指定しているソースファイル名を変更し、ターゲットのプログラムサイズもATmega88に合わせて変更(0x2000-0x800=0x1800だけど、ちょっと欲張って(゚o゚)\バキ 0x1900 にした)。こんな感じに。
プログラム名の変更。
# program name should not be changed... ←...まぁ気にしない気にしない(゚o゚)\バキ
PROGRAM = ATmegaBOOT_88
ターゲット(チップ種類)の変更と、領域(フラッシュメモリの容量)の設定。
MCU_TARGET = atmega88
LDSECTION = --section-start=.text=0x1900
そして、ATmegaBOOT_88.c (ブートローダーのソース)を変更。と言ってもプリプロセッサの条件文をいじるだけですが(゚o゚)\バキ
例えば、
#elif defined __AVR_ATmega168__
こんな行はこんな風にします
#elif defined __AVR_ATmega168__ || __AVR_ATmega88__
ただし、以下の部分(178行目〜181行目)は書き換えちゃダメよん。
#elif defined __AVR_ATmega168__
#define SIG2 0x94
#define SIG3 0x06
#define PAGE_SIZE 0x40U //64 words
それは、上記の行のすぐ上には↓こんな感じに既に ATmega88 用のコードがあるから
#elif defined __AVR_ATmega88__
#define SIG2 0x93
#define SIG3 0x0a
#define PAGE_SIZE 0x20U //32 words
と言う具合にソースコードを変更したら、いよいよコンパイル。と Arduino Software を起動して・・・と、行きたいところですが、どーも Arduino Software からはブートローダーのコンパイルはやってくれない模様。ということで、コマンドラインで、 make することに。
Macintosh:atmega88 isi$ make diecimila
ワタシの場合、Arduino を使う前は C でプログラムしていたので、avr 用の gcc (gcc 4.3, avr-libc 1.6.2)を予めインストールしてあったのでそのままコンパイルできましたが、無い場合は、Arduino Software が gcc をもっているので(<インストールしたディレクトリ>/arduino-0012/hardware/tools/avr/bin にあります)ソレを使えば別途インストールする必要はありません...と、今試してみたらこんなエラーが(途中改行入れてます)(゚o゚)\バキ
/Users/isi/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/bin/ld:
address 0x20a6 of ATmegaBOOT_88_diecimila.elf section .text is not within region text
どーも、コンパイラ(リンカ?)のバージョンによってはエラーになっちゃうみたいっす。ちなみにこのエラーの対処方法は、Makefile のケチった部分を 0x1800 にすればOK。
MCU_TARGET = atmega88
LDSECTION = --section-start=.text=0x1800
ユーザー領域は減っちゃいますが、これで使えるようになります。もし、ケチケチ路線でイキたいのであれば、AVR MacPack()なり WinAVR なりAVR用のgcc と avr-libc をインストールしましょう(ソースを弄るって手もあるけどいっか(ぉぃ)。
ということで、ブートローダーのコンパイルが終わると、ATmegaBOOT_88_diecimila.hex ファイルが出来上がりますので、コイツを ATmega88 に書き込みます。書き込みには前回のエントリでセットアップした USBaspを使います。ですが、このままでは Arduino Software からは今回作ったブートローダーの情報が登録されていないので、Arduino Software を起動する前に、 Diecimila,Lilypad などArduino ボードの種類を設定・登録する。 <インストールしたディレクトリ>/arduino-0012/hardware/boards.txt に以下に示すリストを追加して今回移植したブートローダーを登録します。
isiduino.name=isiduino mini
isiduino.upload.protocol=stk500
isiduino.upload.maximum_size=6400
isiduino.upload.speed=19200
isiduino.bootloader.low_fuses=0xff
isiduino.bootloader.high_fuses=0xdd
isiduino.bootloader.extended_fuses=0x00
isiduino.bootloader.path=atmega88
isiduino.bootloader.file=ATmegaBOOT_88_diecimila.hex
isiduino.bootloader.unlock_bits=0x3F
isiduino.bootloader.lock_bits=0x0F
isiduino.build.mcu=atmega88
isiduino.build.f_cpu=16000000L
isiduino.build.core=arduino
Arduino Software を起動し、ボード選択メニューを開くと今回移植したブートローダー isiduino mini (isiduino はワタシが自作した Arduino 互換機のシリーズ名)がメニューに現れるのでそれを選択します。
ちなみに、並び順は boards.txt の何処に書いても勝手にソートされてしまうよーです。
ハードウェアの製作
今回ボードを作らず、必要なシステムにチップのまま組み込んでしまおうということで、USB - シリアル変換は別体にし、プログラム変更するときだけ USB - シリアル変換を繋ぐ方式にしました。こーすることで小型化することができ、大量に作ってもコストが掛からないようになりました。と言うことで、前作の isiduino より小型化(フラッシュ容量も小型化(゚o゚)\バキ)したので、isiduino mini と命名しました。
写真はブレッドボード上に組んだ(と言っていいのか?)isiduino。右上のフラットケーブルで USB - シリアル変換に接続します。ちなみに、このブレッドボードの配線間違ってます。さて何処でしょう?(゚o゚)\バキってクイズにしちゃってますが、撮り直すの面倒なだけだったりします(ぉぃ
これが、USB - シリアル変換部。写真左側のコネクタが USB で右側がシリアル。シリアル端子には Tx・Rx 以外にも制御に使うリセットとケーブルから電源を供給するために電源とGNDの5端子となっています。
isiduino mini の全ての回路図はコチラ。
最後に、ハードウェアが完成したところで、USBasp を繋ぎ、Arduino Software を起動し、ブートローダーを書き込みます。方法は、Arduino Software を起動し、メニューバーの「Tools」→「Board」→「isiduino mini」とクリック(ドラグ)しターゲット(書き込み先)を設定。次に「Tools」→「Burn Bootloader」→「w/ USB asp」をクリックすると、書き込み開始します。
core ライブラリの書き換え
ブートローダーの書き込みも終わり、いよいよスケッチ(ユーザープログラム)が書けるぜー♪と、カリカリとコードを書いてソースを「Compile」すると大量のエラーが出てガッカリさせられます。初心者のヒトだったら自分のコードが間違ってるんぢゃないかなんて思ってしまいそーですが、ご安心を、書いたコードが原因ではなく、Arduino のコアになるコード(ライブラリ)が移植したチップに対応してないのが原因です。
ということで、エラーになっているコードを修正しましょー。エラーメッセージを見ると、 <インストールしたディレクトリ>/arduino-0012/hardware/cores/arduino/ 以下に入っているファイルが悪さしてるよーですので、まずはエラーの出ているコードを開いてみると、ブートローダーのソースを直したときの方法と同じ方法で対処できるのが分かると思います。ブートローダーの時と違うのは、ファイルがいくつにもまたがると言うところ。面倒ですが、やっていることは単純ですので、検索やシェルスクリプトを上手く使えば簡単に修正可能です(ワタシはスクリプトではなく検索・置換でやりました)。
ソースの修正が終わったところでもう一度コンパイルしてみてエラーが出ないことを確認して終了。
ということで、どれだけのヒトが必要なのかと言うか、ワタシ以外の誰が使うんだって感じだけど、今回弄ったファイルどもを纏めたものをコチラにアップしておきます。
最後に、この方法を使えば最新チップでフラッシュメモリ 32kB 版 ATmega328 や 4kB 版の ATmega48 にも移植可能だと思います...って、328 はすでにやってるよーですね。
『Arduino Hacks』
http://www.ladyada.net/library/arduino/bootloader.html
ということで早速落としてきてチェックすると、あれれブートローダーしかねぇーや(゚o゚)\バキ
おっかしーなぁ、通常版 Arduino (Diecimila など)としてプログラムを書き込むのかな?フラッシュメモリが増えたからデータロガーに良いぞなんて書いてあるから、プログラム領域よりもストレージが目的なんだろうか?それともワタシが根本的なところで間違えてるのか(゚o゚)\バキ
- 固定リンク
- ¦
- コメント (2)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/isiduino-mini/tbping
Re: Arduino を ATmega88 に移植してみました
Re: Arduino を ATmega88 に移植してみました
移植した後に気付きましたが、今回は Diecimila を移植したので16MHz のクリスタル付けてますけど、LilyPad を移植すればクリスタルも不要(AVR 内蔵 CR 発振器がクロックになる)ですね。まぁ速度は Diecimila の半分の 8MHz だし、精度も悪いのでまいっかって感じ。
Arduino と Mac でシリアル通信
今回はパソコンとシリアル通信をする実験。それとついでに LCD の実験。LCD の実験は以前にもやったのですが、Arduino Software が 0012 になってから LCD ライブラリが標準装備されるようになり、あれからどう変わったのかなぁと。と言うか、LCD の方はパソコンから送られたデータを LED で表示するよりLCD繋いで文字で見れて方がいいよね、って程度のコトなんですが(゚o゚)\バキ
と言うことで、左の写真が完成したところ。液晶の下にある基板は 秋月 LCD をブレッドボードで使うための治具。なんか最近治具ばっか作ってるなぁ。こう言うときは大抵何かやりたいけどどっから手を付けていいのか分からないときですね(゚o゚)\バキ
まぁ、今回はシリアル通信の実験とやることは決まってるんですが、目標はこの先にあるわけでして・・・。と、そんな話はさておき以前に比べ、配線なんかがだいぶスッキリしてるでしょ?治具のお陰ってのもあるんですが、前回と違い今回は、Arduino と LCD との接続が4bit 接続ということで配線が4本減っています。1Byte 送るのに2回データ転送が必要になってしまいますが、Arduino の希少な I/O を少なく押さえることが出来るというメリットがあります。
それで、これが回路図。回路としては超簡単。LCD データバスは上位4本(D4 〜 D7)のみ接続。D0 〜 D3 の4本は無接続(NC)とします。コントラスト調節用のボリューム(VR)の値はテキトーに決めた(゚o゚)\バキ
この秋月LCDですが、キャラクタ型(文字コードを送って文字を表示させるタイプ)のものはピンアサインは殆ど同じでしたが、電源とGNDが反対になっているものがありましたので要注意。
Arduino 側はまーテキトーに(ぉぃ
プログラムの方で変更可能ですので、何でもイイってえば何でも良いです。但し、0,1 番pin はシリアルで使う(USB - シリアル変換チップ FT-232 に繋がっている)ので使えません。もちろんアナログ入力ピンもダメだけど。
ワタシはとりあえず Arduino Softeware に入っているサンプルコードに合わせて結線しました。
サンプルコードの一覧を見ると丁度良さそうなコードがあったので、今回はそれを使います。使うコードは左のスクリーンショットで示してる「SerialDisplay」を使います。これはシリアルで送られてくる文字を表示するだけの単純なモノですが、今回は Arduino よりもパソコンの方がメインだし、シリアル通信も初めてだしいきなりややっこしいコード書いてワケワカになるよりはマシってことで。
isiduino にサンプルコードを転送したら、Arduino Software の Serial Monitor を開きます。左のスクリーンショットにあるようにアイコンをクリックすると、コードを書く画面の下に Serial Monitor が現れますので、テキトーに文字を入力して「Send」をクリックすると Arduino に繋いだ LCD に入力した文字が現れるはず。
で、イキナリ出ないんですが・・・(゚o゚)\バキ
どーも、LCD の初期化のタイミングが微妙にズレてるっぽくてコールドスタートした直後はイマイチみたいで、リセットを何度かかけるとイイみたい。とは言え再現性が悪いのでイマイチ自信がないっす。
と英数字はこれで良いのですが、この LCD には半角カナや記号(ギリシャ文字や半角で千や万や円など)も使えるのですが、これが SJIS なので、UTF-8 の Mac から半角カナを送ると当然文字化けします。
ということで、今度は Arduino Software からではなくシェルスクリプトで UTF-8 で入力した文字列を SJIS に変換して isiduino に送るように、簡単ですが以下のようなコードを書いてみました。
#!/bin/sh
device=/dev/cu.usbserial-A5002yyY #USB-Serial 変換アダプタのデバイスファイル名
printf "$1" | iconv -f UTF-8 -t SJIS > $device
そして、使い方はこんな感じ( lcd は上記スクリプトのファイル名)。
$ lcd "アホアホ isiチャン ハンカク カナ ニ モエモエ(バキ "
#表示バッファは1行40文字なので、文字が入らない部分はスペースで埋める。
すると、冒頭の写真のような表示になりました。
ところが、Arduino Software の Serial Monitor をオフするとコマンドラインからもアクセス不能になっちゃう。なんでだろ?とりあえず、 stty で設定変えてみようしても受け付けてくれないの。それで、再び Serial Monitor をオンにするとコマンドラインからも使えるように・・・ヨーワカラン(゚o゚)\バキ
- カテゴリ
- Arduino
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/arduino-serial/tbping
Arduino 腕時計
実はコレ、今年の正月休みに思いつきで初めてそれっきりになっていたモノだったりしして(゚o゚)\バキ
まずは、ブレッドボードで組んで動いたところを確認してからこの状態にまでもってきたのが1月の中頃。さっさと終わらせてまとめてブログに書くつもりがそのままお蔵入りに...(゚o゚)\バキ
このまま放置して完全に忘却の彼方に追いやられる前に蔵出しすることにしました。
と、前口上が長くなりましたが、ここからが本題。
タイトルにもあるとおり、これは Arduino (の自作互換品)を使って作った腕時計で、超小型リチウムイオン電池で動作し、時刻表示は7セグ LED ...ってタダそれだけなんですが(ぉぃ
まー、機能としてはそんなモンなんですが、いかにも手作りっぽくてカッチョエエーんぢゃないかなぁ。と作った本人は思っているんですが...ダメですかねぇ?(゚o゚)\バキ
ちなみに、基板は2階建て構造になっていて、2階は表示部と、操作するためのボタン類で、1階部分はバッテリと Arduino ブートローダー書き込み済み AVR マイコンと言った感じにしました。
こちらが1階部分の写真。
見事にバッテリとマイコンだけの状態。ビミョーにバッテリが基板からハミ出て見えるのは実際にハミ出てるから(ぉぃ
たまたま丁度良さそうな大きさのユニバーサル基板の端材があったので、それを使ったらこーなっちゃいました(わらい)。
で、街に持ち出してみたのですが、Arduino 電気食いすぎ(ぉぃ
LED 表示点けっぱなしだと4時間しか電池持たなくて全然時計として使い物にならん(゚o゚)\バキ
つーことで、LED 点灯しっぱなしは止めて、普段は時刻表示部分のLEDは消灯しておいて、ボタンを押したときだけ動作するようにプログラムを変更すると同時に、 Arduino のクロックを 16MHz → 8MHz に変更したところ、動作時間が12時間程になりました...っても、せめて24時間は動いてくれんとねぇ(わらい)
まーいいや(ぉぃ)。とりあえず、ベルト付けて腕時計にしよっと。
2009/05/25 追記
5/23〜5/24 に行われた Make Tokyo Meeting 03 (通称: MTM03)にデモしようと前日夜なべしてアクリルと格闘しながらフレームをつくりました。
それで、会場での評判はと言うとかなり良い感じ♪
一流のハッカーや Maker の認められて超嬉しと同時にホッとしました。内心「スルーされたらどうしよう」って思ってた。
ちなみに、横から見るとこんな感じ。
#どーしても、ソースを見たいとゆー酔狂な方(ぉぃ)は続きをどーぞ(゚o゚)\バキ
#include <MsTimer2.h>
char SegmentFont[11] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x67, 0x00};
char DigitChar=0;
char Digit=0x04;
char Second;
char Minit;
char Hour;
char led = HIGH;
char mode = 0;
char limit = 0;
char toggle;
char sHour = 0;
char sMinit = 0;
char sSecond = 0;
char up;
char down;
void setup(){
DDRC = 0xFF;
DDRB = 0xFF;
pinMode(7,OUTPUT);
digitalWrite(7, led);
//MsTimer2::set(475, HalfSecond); // 1/2 sec
MsTimer2::set(237, HalfSecond); // 1/2 sec
MsTimer2::start();
pinMode(4,INPUT);
pinMode(5,INPUT);
pinMode(2,INPUT);
attachInterrupt(0, SwMode,RISING);
}
void loop(){
switch(mode){
case 0:
ClockDisplay(Hour,Minit,1);
break;
case 1:
ClockDisplay(Minit,Second,0);
break;
case 2:
PORTC = 0x00;
delayMicroseconds(1000);
break;
case 16: //Hour Setting
ClockDisplay(sHour,sMinit,3);
if(!digitalRead(2)){
if(digitalRead(4) && (up == 0)){
if(sHour == 23){
sHour = 0;}
else{
sHour++;}
limit = 0;
}
if(digitalRead(5) && (down == 0)){
if(sHour == 0){
sHour = 23;}
else{
sHour--;}
limit = 0;
}
}
up = digitalRead(4);
down = digitalRead(5);
WaitTime(20);
break;
case 17: //Minit Setting
ClockDisplay(sHour,sMinit,2);
if(digitalRead(4) && (up == 0)){
if(sMinit == 59){
sMinit = 0;}
else{
sMinit++;}
limit = 0;
}
if(digitalRead(5) && (down == 0)){
if(sMinit == 0){
sMinit = 59;}
else{
sMinit--;}
limit = 0;
}
up = digitalRead(4);
down = digitalRead(5);
WaitTime(20);
break;
case 18: //Second Setting
ClockDisplay(99,sSecond,4);
if(digitalRead(4) && (up == 0)){
if(sSecond == 59){
sSecond = 0;}
else{
sSecond++;}
limit = 0;
}
if(digitalRead(5) && (down == 0)){
if(sSecond == 0){
sSecond = 59;}
else{
sSecond--;}
limit = 0;
}
up = digitalRead(4);
down = digitalRead(5);
WaitTime(20);
break;
default:
ClockDisplay(Hour,Minit,1);
break;
}
if(digitalRead(2) == 0){
attachInterrupt(0, SwMode,RISING);
}
}
void ClockDisplay(char upper,char lower,char disp_mode){
char disp[4];
char X = 0xFF;
disp[0]=lower % 10;
disp[1]=lower / 10;
switch(disp_mode){
case 0:
disp[2]=upper % 10;
disp[3]=upper / 10;
break;
case 1:
disp[2]=upper % 10;
disp[3]=upper / 10;
if(disp[3] == 0){disp[3] = 10;}
break;
case 2:
disp[2]=upper % 10;
disp[3]=upper / 10;
if(disp[3] == 0){disp[3] = 10;}
if(led == 0){
X = 0xF3;
}
break;
case 3:
disp[2]=upper % 10;
disp[3]=upper / 10;
if(disp[3] == 0){disp[3] = 10;}
if(led == 0){
X = 0xCF;
}
break;
case 4:
disp[2]=10;
disp[3]=10;
if(led == 0){
X = 0xF3;
}
break;
default:
disp[2]=upper % 10;
disp[3]=upper / 10;
break;
}
PORTB = ~(SegmentFont[disp[DigitChar]] >> 1);
PORTC = ~((~(Digit & X) & 0xFC) | (SegmentFont[disp[DigitChar]] & 0x01)) ;
Digit = Digit << 1;
DigitChar++;
if(Digit > 0x20){
Digit = 0x04;
DigitChar=0;
}
delayMicroseconds(1000);
}
void WaitTime(int time){
if(limit == time){
limit = 0;
mode = 0;
}
else{
if(toggle != led){
limit++;}
}
toggle = led;
}
void HalfSecond(){
led = !led;
digitalWrite(7, led);
if(led != 0){
if(Second == 59){
Second = 0;
if(Minit == 59){
Minit = 0;
if(Hour == 23){Hour = 0;} else{Hour++;}
}else{Minit++;}
}
else{
Second++;}
}
}
void SwMode(){
detachInterrupt(0);
if((mode == 2) || (mode == 18)){
if(mode == 18){
Hour = sHour;
Minit = sMinit;
Second = sSecond;
}
mode = 0;
}
else{
if(digitalRead(5)){
mode = 16;
sHour = Hour;
sMinit = Minit;
}
else{
mode++;
switch(mode){
case 17:
sMinit = Minit;
break;
case 18:
sSecond = Second;
break;
}
}
}
}
Xcode で Arduino
以前ワタシは、「 Eclipse で AVR 開発 」というエントリーで Eclipse を使った AVR 開発を紹介。そのエントリーの中でワタシは
いつも「Xcode でコード書きからコンパイル、デバッグまでできたらなぁ」などと思っていた
なんてコトを書いていたワケだけど、やっぱり同じ事考えていた人がちゃーんと居ました♪
『Make: Online : Arduino Xcode template』
http://blog.makezine.com/archive/2009/06/arduino_xcode_template.html
こっちは AVR 全般ではなく、Arduino の開発のよーですが。つか Arduino だけだったら Arduino Software で開発した方が動作も軽そうだけど(ぉぃ
まーそうは言っても、Arduino が出来るなら普通の C での開発環境を作るのは難しくないと思うので、両方対応していただけると嬉しいな。
って自分でやるとゆー発想はねーのかよ<ヲレ(゚o゚)\バキ
- カテゴリ
- Arduino
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/Xcode-Arduino/tbping
フリスクのケースを使って電子工作
今まで、フリスクをポリポリを囓りながら「やっぱ、このケースに何とか自分で作ったもん入れたいよなぁ。」と何となく思って、何個か捨てずに取ってあったのですが、なかなかイイ感じの工作が見付からない。この前作った「Arduino 腕時計」ならひょっとしたら、と思ったのですがいざフタを開けてみる(作ってみる)とバッテリーすら入らねぇー(゚o゚)\バキ
ということでそのまま放置していたのですが「Arduino を ATmega88 に移植してみました」で製作した USB - シリアルアダプタを収めてみてどの程度使えるのか試してみることに。
最初に作ったときのままだと背が高すぎて入らず。ということで、基板に挿すピンヘッダ(リード)をムシリ取る。
ピン一本一本分離するようにニッパーでプラの部分をカットしたあと、半田ごてで半田を融かしながらピンを抜いていきました。
でも、この方法ちょっとダメかも(詳しくは後述)(゚o゚)\バキ
ピンをムシリ去るとこんな感じに。なーんか、ランド(半田付けしていたところ)が少し捲れてるよーな・・・(゚o゚)\バキ
どーも、先の工程でニッパーでプチプチやったときにランドに負担かけてたよーです。
そんなワケで、次やるときはもうちょっとやり方工夫した方が良さそう...次って何時やるんだ?(゚o゚)\バキ
ちなみに、表側はこんな感じ。んもーフラックス使いすぎ>メーカー殿(゚o゚)\バキ つーことで、あまりにも酷いのでアルコール系洗浄剤でキレイにしました。
ピンをムシリ取った後、基板を最初から作り直そうと思ったけど、今まで使っていた基板をケースに収まるようにカットすれば使えるということが判明したので、自作した方の基板を半分にカット。写真のようにラッピングワイヤの端材で2枚の基板を接続しました。
半田付けが終わったら、ケースに組み込み。ケースへの固定は、みんな大好きなホットグルー。いぇーいグルービー♪(意味不明)。
ちなみに、この写真の配線間違ってます(゚o゚)\バキ
まー間違っていたところで、ワタシ以外のヒトには全く関係ないんですが(わらい)。
最初にピンヘッダを抜いたりしたのですが、微妙にジャンパピンの所が飛び出しちゃう。それで、ジャンパーピン(のピンヘッダ)を外そうかと思ったのですが、むしろちょっと飛び出てるぐらいの方がジャンパピンを差し替えるときに便利だろうということで、ケースの方を加工しました。
送受信ステータスの LED もケースの中に隠れてしまうので、ドリルで穴を開け、アクリル丸棒をスライスしたものを填め込んで導光体としました。
ちなみに USB と ターゲットへの接続ケーブルの端子はこんな感じ(USB:ターゲット)。
アクセスランプを点灯させたところ。なんか緑がイマイチな感じだけど、赤に比べて点灯時間が短いから...だと思うよ?(ぉぃ
で、先の写真ではラベルシールが加工している間に傷だらけになったので剥がしたんですが、余りにもあんまりなので(゚o゚)\バキ 別の空FRISKケースからラベルを移植しました。
反省点:ケースを加工する前にラベルは一旦剥がして避難させるべし!
ということで、初めてFRISKケースに電子機器を組み込んでみたワケですが。如何でしょうか?って、誰に聞いてるんだ?ってもちろん自分に聞いてるんですが(ぉぃ
縦横の幅はいいんですが、思ったより深さがなかったです。いつものことだけど、回路を組み込むのは比較的容易でも電池で泣かされるんだろうなぁと。で、そんなのはどーでも良くて、最も重要なのが
ケースを加工する前にラベルは一旦剥がして避難させるべし!
ですねー(二度目(゚o゚)\バキ)。これを怠ると、FRISK ケースがただのちっこいプラケースになってしまうってことですね(ぉぃ
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/Frisk-Case-Reuse/tbping
isiduino 168p
以前、秋月 AT mega88 を使った Arduino 互換機の話を書いたときから、「秋月価格で ATmega168」を扱ってくれたらなーと思っていたのですがなかなか扱ってくれず、シビレを切らしたワタシは Digi-Key に発注してまとめ買いしたわけですが、遂に秋月がワタシの願い(きっとワタシだけではないはず)を叶えてくれました♪
『AVRマイコン ATMEGA168P−20PU: マイコン関連 秋月電子通商 電子部品 ネット通販』
http://akizukidenshi.com/catalog/g/gI-03033/
しかし、型番をよく見ると分かるように、Arduino で使われている ATmega168 とは微妙に型番が違って、末尾に”P"が付いてます。と言うことで、イヤな予感しつつもとりあえずブートローダーの書き込みを開始。

ほーら、やっぱりダメだ(泣)。エラーの内容を読むとATmega168 ぢゃないよ。と言ってます。やっぱり、”P"の有無でシグネーチャーが違うようです。もちろん中身も違うのですが、サスペンドモードに違いはあるものの基本的には同じ物なんですけどねー。ということで、元々の Arduino 168/328P のブートローダーのソース( C のソースファイルと Makefile )を別ディレクトリ(atmega168p)にコピーして必要な箇所(余計なトコも弄ってる気もするけど(゚o゚)\バキ)を変更。Cソースの変更は ATmega88 と基本的に同じで(Arduino Software のバージョン改造バージョンの 0012 から 0016 に変更したため、ATmega88 だった部分が ATmega328P に変わってます)こんな感じになってる
defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
となっているところ(注意:”__AVR_ATmega168__” の記述がある行を変更。”__ATmega128__” と記述のある行もあるが、そこは変更しない。)に "__AVR_ATmega168P__” を挿入する感じで、以下のように変更(ボールド部分)。
defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
ATmega88 の時と異なるのは今回の場合はフラッシュメモリの容量は全く変わってないので、フラッシュメモリ容量の指定を変更する必要がないと言うことでしょうか。
そして、お次は Makefile の変更。
Makefile の変更はたった1箇所だけで、以下のようになります。
MCU_TARGET = atmega168
を
MCU_TARGET = atmega168p
に変更。1箇所でしかも1文字だから一見どこが変わったのか分からないぐらいですな(わらい)。
最後に boards.txt (詳しくは秋月 AT mega88 を使った Arduino 互換機の話を参照のこと)に ATmega168P用ブートローダーを登録します。やり方はほぼ、ATmega168(Diecimila)のブロックをコピペですが、以下のようにしました(ボールド部分はコピペから変更したところ)。
##############################################################
diecimila_p.name=Arduino Diecimila (168P)
diecimila_p.upload.protocol=stk500
diecimila_p.upload.maximum_size=14336
diecimila_p.upload.speed=19200
diecimila_p.bootloader.low_fuses=0xff
diecimila_p.bootloader.high_fuses=0xdd
diecimila_p.bootloader.extended_fuses=0x00
diecimila_p.bootloader.path=atmega168p
diecimila_p.bootloader.file=ATmegaBOOT_168_diecimila.hex
diecimila_p.bootloader.unlock_bits=0x3F
diecimila_p.bootloader.lock_bits=0x0F
diecimila_p.build.mcu=atmega168p
diecimila_p.build.f_cpu=16000000L
diecimila_p.build.core=arduino
##############################################################
全て完了したら、「ターミナル」(シェル環境)を立ち上げて、ブートローダーをコンパイルします。
UmasikaBookPro:atmega168p isi$ make diecimila
コンパイルが終わったら、Arduino Software を起動してブートローダーを書き込みます...
すると、こんな感じのエラー("¥"で終わっている行は折り返してます)がドバッとでて終了しちゃいました(合掌)(゚o゚)\バキ
avrdude -c usbasp -p atmega168p -P usbasp -e -u -U lock:w:0x3f:m ¥
-U efuse:w:0x00:m -U hfuse:w:0xDD:m -U lfuse:w:0xFF:m
avrdude: AVR Part "atmega168p" not found.
Valid parts are:
m6450 = ATMEGA6450 [/usr/local/etc/avrdude.conf:11538]
m3250 = ATMEGA3250 [/usr/local/etc/avrdude.conf:11349]
m645 = ATMEGA645 [/usr/local/etc/avrdude.conf:11160]
m325 = ATMEGA325 [/usr/local/etc/avrdude.conf:10971]
---------------------------中略-------------------------------
t2313 = ATtiny2313 [/usr/local/etc/avrdude.conf:7259]
m328p = ATMEGA328P [/usr/local/etc/avrdude.conf:7071]
m168 = ATMEGA168 [/usr/local/etc/avrdude.conf:6883]
m88 = ATMEGA88 [/usr/local/etc/avrdude.conf:6697]
---------------------------後略-------------------------------
エラーの内容を読むと、avrdude (Arduino Software からプログラムをターゲットに書き込むときに起動するプログラム)が 「ATmega168Pなんてヤツはオレ知らんぞ」と言ってるよーで、どーも、 /usr/local/etc/avrdude.conf にターゲットの型番とシグネーチャーを登録(チップのモデル毎に割り振られたユニークな番号)するようなので、ATmega168P の定義を追加。と言っても毎度のお馴染みのコピペ&ちょこっと変更(ボールド部分が変更した箇所)。
#------------------------------------------------------------
# ATmega168P
#------------------------------------------------------------
part
id = "m168p";
desc = "ATMEGA168P";
has_debugwire = yes;
flash_instr = 0xB6, 0x01, 0x11;
eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,
0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,
0x99, 0xF9, 0xBB, 0xAF;
stk500_devcode = 0x86;
# avr910_devcode = 0x;
signature = 0x1e 0x94 0x0b; #ATmega168 は 0x06。
---------------------------後略-------------------------------
今度こそと気合いを入れて、Arduino Software から書き込むと今度は成功♪
ふー、やれやれ(゚o゚)\バキ
- カテゴリ
- Arduino
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/isiduino-168p/tbping
ArduinoでNiMHチャージャーできるかな? vol.1
Make: Tokyo Meetingで何度かゲリラ出品したと言うか毎度おなじみ(?)のPOVヘルメット。そのPOVヘルメットの電源はパソコンに使われているATX電源によるAC駆動と自作NiMH組電池の2種類の電源で動くのだが、ACはともかく問題は電池の方、7.2V10Ahとゆー大容量バッテリのため市販の充電器やそこいらのキットでは充電時間が掛かりすぎるというか、大抵の場合フル充電する前にタイマーで充電終了してしまうということで、今までは市販の充電器で充電を3回ぐらいに分けて受電したりして騙し騙し使っていたが、これでは時間がかかるし、現在が何回目なのか覚えてられない正直やってられない。ということで何時かは充電器を作らないと、と思い市販のキットを改造しようかとキットを買ってきて調べてみたりしたが、回路は複雜だし融通は利かないしでどうもイマイチ。
フルスクラッチで設計することにしたのだが、急速充電の定番回路であるΔV方式を汎用チップ(オペアンプやトランジスタで組むと複雑になるし、かと言って専用ICだと痒いところに手が届かない。そしてなにより色々設定を変えたり(充電池のセル数など)すると言った融通が利きにくい。しかし、AVRやPICをはじめとするワンチップマイコンはA/Dコンバーターが数チャンネルとPWMが数チャンネルあったりしてフィードバック制御をするのに必要なI/Oを全て持っている上にパラメータ調整・変更や制御アルゴリズムの変更をソフトウェアで出来て楽チン。しかも液晶を繋いでボタンを幾つか付けたりできてUI的にもよい(要らなくてもとりあえず電圧でも表示とけばカッコイイし(笑)←ってのはさておき、充電プログレスバーを出したりしてもいいよね)と言うことで、マイコンを使ってみることに決定。マイコンを使って手軽にやるのなら徹底的にお手軽にArduinoを採用。初心貫徹である(違)。
前書きが長くなってしまったが、ここからが本題。
とは言えArduinoで本当にスイッチング電源が出来るのかものすごく不安。マイコンのPWM出力値(デューティー比)を変えれば電圧変わるのは当然だが、問題はノイズとリプル。マイコンのレスポンスが悪ければリプルが現れるし、スイッチング方式を使うということで、ノイズ対策を万全にしないと電圧を安定化させることができない(ΔV方式の場合、数10mVオーダーの電圧変化検出する必要があるのでノイズに対して神経質にならざるを得ない)。このような具合で不安と不安が入り交じる状態でのスタート(ぉぃ
最終目的は充電器にすることだが、まずは下図にある降圧形スイッチング電源の基本回路で実験。
基本回路と言いつつ、基本回路以外のものまで入ってしまってるが、それはそれ(ぉぃ
写真の緑線で囲っている部分がスイッチングレギュレータの中心部分で、青線で囲った部分はArduinoのPWM出力電圧(5V)では直接 MOS-FET のゲートを駆動できないため入れたレベル変換回路(負荷のアッパーサイドでスイッチングしてるので出力電圧(Vout)+ 5Vはないと十分にゲートをオンに出来ない。逆にボトムサイドをスイッチングする場合、この回路は無くても動作する。ただし、通常パワーMOS-FETはゲートソース間の電圧が10V前後がもっともオン抵抗が低いので、入れることをオススメする)。そして、紫の線で囲っている回路はMOS-FETのゲートに必要な電源をArduino(USB)から昇圧して作るための回路。
そして、ソフトウェアと言うかプログラムはこんな感じ。
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
#define SET_RES 0.00489 //5(V) / 1024(10bit ADCなので)= 0.0048828125
#define RES (SET_RES * 4) /* Vout (max) = 20(V)とする。
ADCフルスケール値 = 5(V)Arduinoのデフォルト。
抵抗分圧でVoutのフルスケール20VをADCのフルスケール5Vに
しているのでADCへの入力は実際の電圧の1/4。それをプログ
ラムで元の電圧に戻すための定数。*/
int Set=0;
int Vout=0;
int PWM_P = 0;
char num[10];
void setup()
{
TCCR1B = TCCR1B & 0b11111001; //PWM 1の周波数をデフォルトの490Hzから31.5kHzに変更
digitalWrite(12,0); //LCDのリセット
delay(500); //何故かコールドブートだと液晶が動かない
digitalWrite(12,1); //LCDリセット終わり
lcd.begin(16, 2); /*LCD初期化。16文字2行の液晶として使うためのもの
ハードウェア的にも16文字2行だけど、他のモードもあるの
で初期化処理は必要*/
lcd.print("Set = "); //固定文字列の表示
lcd.setCursor(0,1); //カーソル位置の変更(1文字目の2行目)
lcd.print("Vout = "); //固定文字列の表示
}
void loop()
{
Set = analogRead(0); //電圧設定の読み込み(出力電圧の設定はボリュームで行う)
delay(10);
Vout = analogRead(1); //出力電圧の取り込み
while((Vout > (Set + 20))||(Vout < (Set - 20))){ /*出力電圧が設定の範囲(±20LSB)
から外れている間にPWMで電圧を調節*/
if(Vout > (Set + 10)){ //出力電圧が設定値より10LSB以上高い場合
PWM_P--;
analogWrite(9,~PWM_P); //PWM値を更新
}
if(Vout < (Set - 10)){ //出力電圧が設定値より10LSB以上低い場合
PWM_P++;
analogWrite(9,~PWM_P);
}
Vout = analogRead(1); //出力電圧の取り込み(電圧調整後の電圧をモニタ)
delay(20); //ADCのマルチプレクサ切り替え待ち(値はテキトー)
Set = analogRead(0); //電圧設定の更新
}
lcd.setCursor(10,0); //1行目の表示(設定電圧)
lcd.print(" ");
lcd.setCursor(10,0);
lcd.print(Set * RES,10);
lcd.setCursor(10,1); //2行目の表示(出力電圧)
lcd.print(" ");
lcd.setCursor(10,1);
lcd.print(Vout * RES,10);
delay(50); //少しディレイ入れた方が調子いいみたいw
}
プログラムの細かい動作は上記リストのコメントを参照するとして、大まかな動作としては、
- 液晶ディスプレイの初期化・その他I/Oの初期化
- 設定・出力電圧をADCで取り込む
- 設定電圧の±20LSBから外れている間はwhileループで電圧の制御。±20LSBに入った場合ループから抜ける。
- LCDに現在の設定・出力電圧を表示
- 2.に戻る
この状態で動かしてみると、ボリュームを上げると電圧が上がるし絞ると電圧が下がって、設定した電圧の近辺で制御は掛かっているようなのだが、いかんせんリプルとノイズが酷い。リプルは大体60mVp-p程度なのに対してノイズは平均して130mVp-pで時々2〜300mVp-pのスパイク状のノイズが混じる感じ。
リプルに関してはLCローパスフィルタの特性のによるものと、フィードバックから制御までに掛かる遅延時間によるものとがあるが、プログラムのwhile()ループにある設定値の範囲(±20LSB)を調整しようとしたが、±20LSB以上狭めるとノイズの影響で設定の範囲に納まり切れずに永久ループに入ったりするので設定値をとりあえず±20LSBにしたのだが、プログラムでの調整ではこれ以上精度/ノイズは向上しなかったので別の対策を考える。
とりあえず、コンデンサを低ESRのモノに交換と行きたいところだが在庫が無し(アキバって遠いなーw)。その代わり容量は小さいけど低ESRのタンタルコンデンサの在庫があったので追加してみたが容量がやっぱ足りないみたいで効果なし。次にADCの電源(AVcc,Vref)周りが怪しいとAVRのマニュアルにあった回路(AVccに供給する電源にLCローパスフィルタを入れてノイズをカットする方法を試したら少し改善。しかし根本的な改善には至らず...と言うかそもそもUSBから取ってる電源そのもののリプル/ノイズが気になり、isiduino(Arduino互換機)を完全に停止した状態(つまりブレッドボードから抜いたってこと)オシロスコープのACモードで図ると案の定ノイズだらけ。5Vと12Vそれぞれの入力コンデンサを後日買ってきた倍の容量の低ESRのコンデンサに交換したところでいい時で30mVp-pとやっとハッキリとした効果が現れた。
しかしまだ、出力電圧が低いとき(つまりPWMのデューティー比が小さいときで、出力電圧7V以下)のリプルが高いということでもっと根本的な対策が必要なのかもしれない。
とりあえず思いつく範囲では
- アナログ用電源の分離
- 5V電源をUSBから取るのをやめて独立電源に(できれば12Vから3端子レギュレータでOKならそうしたい)
- ゲート用昇圧電源の電源を5Vからではなく12Vの方から取る
- グランドの分離(ブレッドボードでは難しい。基板作るときに考えよう)
とりあえず、簡単なものからやってダメならより面倒なのを試すという方針で。
つづく?
- カテゴリ
- Arduino
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/Arduino-Charger-01/tbping
Arduino でNiMHチャージャーできるかな? vol.2
前回のエントリ「Arduino でNiMHチャージャーできるかな?」で次回はノイズ・リプル対策という予告通りにノイズ対策について考えてみた。と、書くとさも誠実な人と思われるかも知れないが、実はノイズのことなんて無視して次に進もうとしてたら、更に酷くなって先に対策せざるを得なかったというのが真相(ぉぃ
そんなどーでもイイ話はさておき、まずは回路図のおさらい。回路的には基本的には同じなのでリンクだけ。変えたところはリンク先の回路図の青い線で書かれた部分で、出力にNiMH電池の代わりにダミー抵抗(10Ω20W)を繋いだだけの状態でスタート(回路図左側の配線に関しては後述)。
ダミー抵抗だけを追加した状態で測ったのが以下のスクリーンショット。

このスクリーンショットで、黄色の波形(以降CH1)は出力のリプルをACモードで測定した波形(DC成分=変動のない部分をカットしてノイズやリプルの成分だけを取り出したもの)で、青の波形(以降CH2)は、LCフィルタを通る前(MOS-FETのソース端子)の波形で(回路図的にはココ)、帯状に見えるのは周期が短くて、CH1の周期にレンジを合わせると波の間隔が狭くなり線同士がくっつくためなのだが、スクリーンショットを見ると分かるように、CH2の帯の濃淡が一定周期で濃くなったり薄くなっててしかも、その濃淡の周期が出力のリプルの周期と同期して見えるのも分かる。
しかし、なぜCH2の帯にこのような濃淡が出てるのか全く分からない。もしかしたら、ArduinoのPWMがヘンでワタシの知らないところでPWM出力を止めちゃう期間があるのか?などと思ったりしたがどうもそういうことは無いらしくMOS-FETのゲート端子の波形をモニタしてもそのような現象は見られなかった。ということで、Arduino(というかisiduinoはシロと断定。あとは、LCフィルタの設計ミスによるリプル除去不足というのがあるが、このリプルの周期は45〜100Hz程度と非常に低くLCフィルタで除去するとなると非常に大きなLCが必要ということで非常にイヤンな展開になる上に、スイッチング周期よりも低い周期のリプルはフィードバック回路の遅延時間によるもの一瞬脳裏をかすめたが、そのことは余り考えたくないのでとりあえずは考えないことにする(ぉぃ
偶然による発見
その日は全く原因が解らないわ眠いわでふて寝。明日Arduinoの方を弄るかということにした次の日。仕事から帰り前日の続きをやろうとブレッ ドボードに電源とオシロスコープを繋ぎ測ると、昨日散々悩んでも原因が解らなかったリプルが雲散霧消してるではないか!一体昨日のリプルは何だったんだろ う、もしかして幻?
ということで、この問題は解決♪ということにして次に・・・と、MOS-FETのゲート電圧をモニタするのに繋いでいたミノムシクリップを外そう とした瞬間、ゲート電圧源の出力コンデンサ(LCフィルタのコンデンサ)のリード端子が抜けていたことを偶然発見。コンデンサのリード端子を挿し直しても う一度波形を測ると再びヤツ(リプル)が現れた。つまり幻では無かったということ。そして再びコンデンサを抜くとリプルが消 える(リプルが消えた理由は恐らく、ゲート電圧が直流から高周期パルスになることで、リプルの周波数も上がりLCフィルタが効くようになったためだと思わ れる)。つまり、ゲート電圧生成回路が原因である可能性が高いということで、ゲート電圧生成回路の出力波形(ACモードで交流分=リプル・ノイズのみを抽 出。)の波形をを見てみるとこんな感じに

CH1の波形は出力のリプルで、CH2の波形がゲート電圧生成回路の出力波形のリプル(回路図的にはコ コ)なのだが、両者の周期が完全に同期してるのが分かる。ということでゲート電圧の変動が犯人と見て間違いないだろう。しかし、このリプルの対策 方法が分からない。とりあえず、ゲート電圧生成回路をゲート駆動回路から切り離してみると、リプルが消えた。つまり負荷によって変動ということは、ゲート 電圧生成回路のドライブ能力の問題である可能性が高い。
設計初期の段階から、5Vから20Vに昇圧ってのはちょっと無理があるかなという思いと、5V系にはあまりノイズ発生源になるものは繋ぐのはマズ いよな(Arduino内蔵のADCにも使ってるから)という思いもあり、ゲート電圧生成回路の電源を12Vからと取ることにした(回 路図左側の配線変更)。すると・・・

はい、キターッ!
綺麗に消えたぜ♪今まで使っていたレンジでは波形として確認するのが困難なほどリプルが小さくなった。Arduinoでモニタしている電圧値もバ タつかなくなってきてる。しかしよく見るとまだリプルは出ているのが判るが、今まで出ていたものとは周波数からして異なるのが分かるだろうか。
恐らく実用上この程度なら問題ないと思うのだが、やはり気になる方も多いと思う(ってヲレだけだよなそんなの...つーか、読者だってヲレだけだ よなきっとw)ので、レンジを変えてみるとこんな感じ。

スクリーンショットの「Delta」と書かれた場所を見ると、15.20mVということで、リプル電圧は約15mVにまで低下したことが分かる。 まだヒゲ状のノイズがチラチラ現れているがこれはまた別の対策が必要であるがそこまで神経質になる必要はないので無視。
ということで、リプル・ノイズ対策はひとまずこれにて終了。
結論
前回のエントリで考えた対策で今回実行した対策は太字の部分。
-
アナログ用電源の分離
-
5V電源をUSBから取るのをやめて独立電源に(できれば12Vから3端子レギュレータでOKな らそうしたい)
-
ゲート用昇圧電源の電源を5Vからではなく12Vの方から取る
-
グランドの分離(ブレッドボー ドでは難しい。基板作るときに考えよう)
と言うことで、とった対策は一つだけw。
対策を書き出した段階で想定していた原因としては、ゲート電圧生成回路こと昇圧型スイッチング電源がノイズ源になっているのではないかということ だったのだが、実際はゲート電圧生成回路の出力のドライブ能力不足によるゲート電圧変動が原因で出力にリプルが現れた。というのが結論。
また、今回リプルが大幅に減り安定してきたので、プログラムも変更し、設定値の許容範囲を±20LSBから±10LSBに変更。アルゴリズムの変 更はナシでパラメータをちょろっといじったのみ。以下のリストはは変更箇所周辺の抜粋。
while((Vout > (Set + 10))||(Vout < (Set - 10))){
if(Vout > (Set + 5)){
PWM_P--;
analogWrite(9,~PWM_P);
}
if(Vout < (Set - 5)){
PWM_P++;
analogWrite(9,~PWM_P);
}
Vout = analogRead(1);
delay(20);
Set = analogRead(0);
}
マージンを半分に減らしてもちゃんと安定したぞ。うーん、いい感じ♪
- カテゴリ
- Arduino
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://isi.kicks-ass.net/blog/isi/bakilog-2.0/Arduino-Charger-02/tbping
ヒモ式蛍光灯をモダンにしてみた
その昔、ワイヤレスリモコンのテレビが普及し始めた頃、「部屋の電気(照明)もリモコン式になればいいのに」と母に話しても「何言ってるの、そんなのヒモを付けて長くすればいいのよ」と一蹴。でも、長いヒモが部屋のど真ん中でダラーンとしてると邪魔でしょうがないよね?部屋の中を歩くといつの間にかだらしなく伸びたヒモが体にまとわりついてて(特にすずらんテープでやると大変だw)勝手にカチカチとやっちゃうと発狂したくなるんだが・・・
などと思ってる間に室内灯もワイヤレスリモコンが当たり前の時代に突入。ということで、我が家の室内灯もモダン化を図ろうってなワケで、こんなモノを作ってみました♪
リモコン式の室内灯に買い換えたり、既設の機器に一切手を加えること無く実装することに成功。メカニズムは次の動画を見れば一目瞭然(初めのヤツでも音だけで分かるか)(わらい)。
リモコンから信号を受けたら、サーボモーターでヒモを引っ張り点灯モードを切り替える…以上!
シンプル・イズ・ベストってヤツですよ。
とは言え、リモコン受信の部分が何気に面倒くさかった。サーボモーターの使用も今回が初だし、初めてのものが多かった分時間がかかってしまった。
まず、リモコンは何にするかが問題だが、答えは簡単だった。この前ブッ壊れたばかりの MacBook Pro (Early 2006)の付属リモコンがあったのでそれを採用することで解決。
と、いうことでMacBook Proリモコンの信号を拝借すべくArduinoを使って受信したのをMacでモニタ(Arduino IDE 付属のシリアルモニタを使用)すべく以下のような回路にする…って、回路と言うほどの代物ぢゃないけどな。
そして、これが受信テストのプログラムソース。
const int SenserPin = 2; // リモコン受信モジュールを繋いでいるArduinoピン(Digital)の指定
#define LENGTH 25 // サンプリング量(バイト)
#define COUNT 7
#define SAMPLE_DELAY 380 // サンプリング周期調整用ディレイ(要調整)
int IrState = HIGH; // センサー入力(負論理:受光時LOW)
byte Data[LENGTH]; //サンプリングデータ(配列)
int Length = 0;
int Count = 0;
void setup() {
Serial.begin(19200);
}
void loop(){
while(IrState == HIGH){ // センサがリモコンの光を受けるまで待機。受光したらサンプリング開始
IrState = digitalRead(SenserPin);
}
while(Length < LENGTH){ // サンプリングデータ(配列)が満杯になるまでサンプリング
IrState = digitalRead(SenserPin);
if (IrState == LOW) {
Data[Length] = Data[Length] | 0b00000001; // 受光("1")の時は配列要素のLSBを"1"に。
}
else {
Data[Length] = Data[Length] & 0b11111110; // 非受光("0")の時は配列要素のLSBを"0"に。
}
if(Count < COUNT){
Count++;
Data[Length] = Data[Length] << 1; // 配列要素が満杯でなければ、左シフト
}
else {
Count = 0; // 配列要素が満杯になったら、次の要素にする
Length++;
}
delayMicroseconds(SAMPLE_DELAY);
}
Length = 0;
for (int i = 0;i < LENGTH;i++){ // サンプリングデータのシリアルへの出力
Serial.print("0x"); // 各要素の先頭に16進数を表す"0x"を付加
Serial.print(Data[i],HEX); // 各要素を16進表記で出力
Serial.print(","); // 区切り文字
}
Serial.print("\n"); // 全ての要素を出力したら改行
Command1_OK = 0;
IrState = HIGH;
delay(100);
}
SAMPLE_DELAY値を調整しつつ何度かリモコン信号を受信した結果、MacBook Pro リモコンの再生ボタンは”0xFF,0xFF,0xFF,0x0,0x9,0x4,0x10,0x48,0x21,0x86,0x18,0x61,0xB6,0xD8,0x6D,0x86,0xDB,0x6D,0xB6,0x1B,0xC,0x30,0xC0,0x0,0x0"であることが判明…たぶん(ぉぃ
この調査結果と同じデータを受信したらサーボモーターを動かすようにプログラムと回路を作成すれば完成。ということで、まずは回路図。基本的に先のテスト回路にサーボモーターがくっついただけなんだけど、受信モジュールの接続端子が変わってたりして。あと、図中のLEDは動作確認用で受信OKならLEDをトグルし続けるというもので、無くても問題無い。
そして、プログラムのソース。
#include <Servo.h>
Servo servo1;
const int SenserPin = 8;
const int ledPin = 2;
#define LENGTH 25
#define COUNT 7
#define SAMPLE_DELAY 380
int IrState = HIGH;
int LEDState = LOW; // 受信確認LEDは最初は消灯
byte Data[LENGTH];
// 一致比較用データ。受信したデータが正しい加確認するためのモノ。
byte Command1[LENGTH] = {0xFF,0xFF,0xFF,0x0,0x9,0x4,0x10,0x48,0x21,0x86,0x18,0x61,0xB6,0xD8,\
0x6D,0x86,0xDB,0x6D,0xB6,0x1B,0xC,0x30,0xC0,0x0,0x0};
int Command1_OK = 0;
int Length = 0;
int Count = 0;
void setup() {
pinMode(ledPin, OUTPUT);
servo1.attach(9);
}
void pull(){
for(int pos = 0; pos < 270; pos += 1) // サーボモーターの関数。
{ // ほぼ、Arduino IDEのサンプルコードそのままパクリw
servo1.write(pos);
delay(5);
}
}
void loop(){
while(IrState == HIGH){
IrState = digitalRead(SenserPin);
}
while(Length < LENGTH){
IrState = digitalRead(SenserPin);
if (IrState == LOW) {
Data[Length] = Data[Length] | 0b00000001;
}
else {
Data[Length] = Data[Length] & 0b11111110;
}
if(Count < COUNT){
Count++;
Data[Length] = Data[Length] << 1;
}
else {
Count = 0;
Length++;
}
delayMicroseconds(SAMPLE_DELAY);
}
Length = 0;
for(int i = 0;i < LENGTH;i++){ // 受信が全て終わったら受信データと比較用データをバイト単位で確認
if(Data[i] == Command1[i]){ // 一致していたら、Command_OK をカウントアップ。
Command1_OK++; // 全部一致していれば、配列の長さと同じになる。
}
}
if(Command1_OK >= (LENGTH - 2)){ // 一致比較のジャッジ。
LEDState = ~LEDState; // 完全一致は難しいみたい(汗)。
digitalWrite(ledPin,LEDState); // なので、2バイトまでは間違いを許してあげるw
pull();
}
Command1_OK = 0;
IrState = HIGH;
delay(100);
}
本来なら受信データと比較用データは完全一致しないと駄目だと思うんだけど、どーにも調子悪い。ボタン3回押して2回しか利かないみたいなことになっちゃうので、大幅に妥協して2/25バイトまでは間違いを許す仕様に変更…まー今のところ大丈夫みたい。モノは試しと他のボタンを押してみたけど反応しないしOK!・・・たぶん(ぉぃ
あとは、ブレッドボードに組んでいた回路を基板にして室内灯に実装するのみ。今回は室内灯には一切手を加えず、何時でも簡単に元通りに復元できるよう、マグネットで貼り付ける方式に決定…ってたまたま会社で貰った廃材のマグネットが出てきたってだけなんですが。とは言え、ただマグネットを付けただけでは室内灯に傷をつけてしまう恐れがあるので、ポリイミドテープで養生(その他のテープだと蛍光灯の光と熱で劣化してしまうハズ)。
設計当初、基板に直接サーボモーターを固定するつもりだったのだが、サーボのアームが切り換えスイッチに近づき過ぎということで、渋々近所のホームセンターでアルミLアングル材の小片を買い、サーボモーターの固定金具を作成。
これらを実装した空きスペースにマイコンとその周辺回路を実装と配線するという感じで、Arduino もイタリアンな本家ではなく、AVRをそのまま使った isiduino mini を使用。
と、ここで完成と行きたいところだけど、ダメだった・・・受信モジュールが蛍光灯の光の影響をモロに受けてしまって受信不能状態に。蛍光灯の光がかぶらない場所に受信モジュールを移動させるか、センサー外周を遮光物で囲むしかないが、イイところに透明パイプを発見。黒ビニテてグルグル巻きにしたら上手く行った(ホッ)。
ってなワケで、これで実用できる状態にはなったものの・・・・・
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)










最終的には電池駆動にしますんでご安心を。と言うか、どの程度の充電池が必要なのかも判ってなかったり(゚o゚)\バキ