2009-11-23
arduinoの良いところは書き込み器がなくても自作できるという点。基板上のMPUにはファームウェアを書き込む必要があるのだがUSB経由で書き込みが出来るらしい。
arduinoの特徴をざっと纏めておく
・マイコンのお勉強用ツール。同様の物はずっと以前からあったが高価だった。
オープンソースで有ることやオライリー(Make:)が旗振り役になってくれたので利用者が増えてきている
今後2~3年でもっと増えることは間違いない。
マイコン=PICだったが、arduinoの登場で変わる可能性もある。
・プログラムを書き込んだらUSBから切り離して使える。旧バージョンにはシリアルインターフェースの物もある。
・プログラムはC言語風味
arduino専用の開発環境(Windows上のソフト)がある
・arduino本体は¥3200と安価。
・本体だけでは使える物にはならない。通常はブレッドボードが必要。もちろんパソコンも。
初期投資は総額6~7千円程度になるだろう。
使ってみたまとめ
・USBから電源供給できるのは便利だが電源を切るためにはUSBコネクターを引き抜く以外に方法が無い。
回路が動かない場合は電源を直ぐ切りたいのだがそれが出来ない。回路が完成するまでに何度もUSBコネクターを抜き差しすることになる。
PICの開発環境(PICkit2&3)の場合この面倒な作業は必要ない。書き込みプログラムから電源を切れる。
・かなり普及したが「それは偶然動いているだけだ」という回路や間違った情報が多い。
但し「検証」出来ると言うこと自体が今までと違う。
PICの場合はアセンブラ利用者が多いのでちょっと見ただけでは間違っていることすら検証不能なことが多い。
日本で入手しやすい部品に置き換える。日本と言うより秋月電子だが... 地方に住んでいると1カ所で部品の購入が済まないと振り込み手数料や送料だけで¥2000~¥3000かかってしまう。
部品のレイアウトは極力変更を加えないようにした。USBコネクターを移動させたが、それ以外はオリジナルと同じ。部品も面実装品ではなくリード部品に変更して作りやすくした。
arduinoの最新版はUSB電源供給と外部電源供給が自動切り替えできるようになっている。当初最新版をアレンジして作るつもりだったが回路に怪しいところがあったので1つ古いバージョンに切り替えた。秋月電子で適当なFETが売っていないというのも切り替えた理由の1つ。
USBVCCはUSBの+5に繋がっている。FETの右側の+5Vは文字通りこの回路の+電源。FETの向き逆なんじゃないか? ボディダイオード経由で電流が流れてしまう。 この回路のまま製品化されてしまっているのだが....
2009-11-25
片面基板でできるかやってみたがジャンパー線が多くなりそうなので止めた。EAGLEの自働配線機能は性能が悪いのでELECTRAのお試し版で実験。ELECTRAは旧バージョンより性能落ちたか? 余りよい配線をしていないような気がする。
ELECTRAの最新版は色の趣味が悪い
arduinoの開発環境をダウンロードしてみた。80MBもある。インストーラーは無く適当な場所に解凍してProgramFilesに置いておくだけ。USBドライバーは別途インストールが必要。ハードが出来てからでないと上手く繋がらないとき原因がわからなくなるので後回し。インストールの面倒くささはオープンソースらしくちょっとだけ面倒。
2009-11-26
部品表を書いて価格を集計してみた。キット化しないと価格メリットは出ない。キット化して¥2400程度か?
2009-11-27
ベタパターンとの静電容量を気にしてかGNDは網目状になっている。この程度の回路では気にする必要は無いだろう。フレキシブル基板の場合、曲げやすくするために網目状にすることがあるそうだ。P板.comの製造基準書か何かに書いてあった。
パターン完成。製造は何かのついでにやろう。
2009-11-29
FETは意図的に逆に取り付けてあるようだ。ATmega1280搭載のarduinoでも同様の配線になっている。
やはり逆に付いてる
この配線はすごい。EAGLEの自働配線ではこれだけ高密度に配線することは不可能なので手動で配線したに違いない。
2009-12-01
もしかしたらボディダイオードの順方向電圧はショットキーダイオードよりも小さかったりするのかと思ったがそうではなかった。FETが逆に付いている理由は定かで無いが、回路の動きを追ってみると問題がある
LM317等の電圧可変タイプのシリーズレギュレターを使用した実験電源を使うとパソコンを壊す可能性が有りそう。以下のようになると思うのだが...
1.ArduinoをUSBで接続する
2.実験用電源の電圧を7.4VにしてDCジャックに繋ぐ(もしくは5V付近から徐々に電圧を上げていって7.4Vに達したときに)
3.D1の順方向電圧降下を0.9Vと仮定するとVINは6.5Vになる
4.LM358のCMPは3.25Vになる
5.VCC30は3.3VなのでIC5Aの出力は0ポルトになる
6.IC5BはボルテージフォロアなのでIC5Aと同じ電圧を出力する。つまり0ボルトになる。
7.PチャネルFET NDT2955 がONする
8.パソコンの電圧がMC33269の出力より低いとNDT2955を介して+5V->USBVCCに電流が流れる
電圧が無段階に変更できる電源を使うときは要注意だ。
ボディダイオードの順方向電圧。
2009-12-05
常識だったらしいのだが知らなかった。FETが逆にも電流流せるって事を。Pチャネルならドレインよりゲートが負電圧になればFETがONして、ドレイン-ソース間が正でも負でも電流が流れる。これでFETが逆に付いている理由がわかった。普通にダイオードを入れるとダイオードの順方向電圧降下だけArduinoの電圧が下がってしまうがFETがONするとFETのON抵抗分の電圧降下だけで済んでしまうのでUSBの電源電圧と殆ど同じ電圧を供給できるって事のようだ。外部電源電圧が十分高ければ上に書いたような外部電源->USB逆流の問題は起こらない。Arduinoの外部電源電圧の最低値は7VのようなのでD1はショットキかな? Vinが6.5Vになると逆流が起こるのでショットキ(順方向電圧0.3V程度)にしておけば外部電源電圧7V以上でVinが6.7V以上になって逆流は起きない。
これを見て気がついた。リニアテクノロジーのLT4358。ほぼ理想ダイオード。大電流の逆流阻止用。
FETって逆方向にも使えるんだ。FETはONしている。Arduinoと同じ結線をしてドレイン-ソース間の電圧を測る。約0V。FETがOFFしているとボディダイオードの順方向電圧の0.5V程度になる。
トランジスターでも試してみた。逆にも流れる。必要性が無いので逆に流す回路が無かったってだけか。
トランジスターはPNPトランジスターの定番2SA1015Y。この回路でLEDは点灯する。
±5V電源で実験
2009-12-07
理屈がわかったのでFETとオペアンプを追加。オペアンプはオリジナルと同じ物。FETは面実装タイプの物。このFETは秋月電子で入手可能なFDS4935。リード部品にしたかったのだがサイズがTO-220なのと高価なので止めた。ダイオードは1S3。
FETとオペアンプを追加した
2010-01-04
OLIMEXのデザインルールに変更するのに一苦労。EAGLEの標準ライブラリーに無い部品もあるので回路図からライブラリーを逆生成する機能(EAGLEの標準ULPに含まれている)を使ったりして変換。OLIMEXは年末に溜まったオーダーを処理をしているはずなのでオーダーシートが送信されてくるまでにかなり時間がかかるだろう。順調に行けば1/23頃に基板を受け取ることが出来るはず。
激しく酷い写真だ。arduino意外にも色々面付して発注。右上がarduino
2010-01-06
思ったより早く来た。直ぐにオーダー。OLIMEXからの「Tanks!」メールも来たので14日後には基板が届くだろう。
1ユーロ=¥132だから、¥9834
2010-01-24
基板が届いた
足を取り付けるねじ穴はあった方がよいと思う
当方の作品で編み目パターンを採用するのは初
ポリスイッチを使用するので特性を簡単に調べてみた。ポリスイッチは電源経路に直列に入れるので電流を流したときに電圧降下が気になる。
電流140mAの時
ポリスイッチの両端電圧0.22V
ポリスイッチは250mA用。ちょっと電圧降下が大きい。何だかイマイチ。
260mAの時
約0.4V
組立
フラックスをアルコール洗浄。半田のヤニは歯ブラシで落とす
Arduino標準のソケットは下側。使いにくいので2.54mmピッチのものを直ぐ上に配置。ソケットは足を数本抜いて使う
組立完了。そしてファームウェア書き込み
完成
ファームウェアは自己書き込みが可能。
動かしてみたが動作が非常に不安定。不安定というより殆ど正常に動作せず。電源電圧が4.8V以下に下がると動作しない。基板のセラロック周辺を触るとそれに反応する感じ。PICに比べると非常に不安定。発信回りの問題なので水晶をセラロックに変更した事に起因している可能性有り
こんなエラーが出る
発信回りの問題なのは明らかなのでデータシートを見てみた。それらしい項目があるのでヒューズビットを変更
水晶とセラロックではヒューズビット(PICで言うコンフィグレーションワード)の設定が違う
ヒューズビットのLOWバイトを「CF」、「CE」、「DE」にして見るも動作不安定。何となく電源に対して神経質になっている感じ。
ATMEGA328を引き抜いてブレッドボードで動かしてみる。電圧3.5V付近まで正常に動く。何故かブレッドボードだと安定して動く???
やはり電源の影響を受けている感じ。電源経路の配線をArduino->ブレッドボードの電源ライン->ATMEGA328にすると動くがArduino->ATMEGA328にすると動かなくなる。何故か遠回りの方が正常に動く。水晶に変更してみた方がよさそう。16MHzの水晶の手持ちがないので要買い出し。
ブレッドボード経由でATMEGA328を繋ぐ
2010-02-03
発振子を交換。水晶だと安定動作する。
16MHzの水晶
20pFのセラミックコンデンサ
2010-02-05
回転計を移植してみた。タイマーオーバーフロー割り込みを使っていないのでLEDがちらつく。質を求めるとArduinoには限界がある。Arduinoの欠点纏め。
・言語がC言語風で初心者向きではない。
セミコロンの必要性
代入演算子(=)と比較演算子(==)の書き間違い
switch case の Break忘れ
等、C言語の悪いところを引きずっている
・割り込み機能が弱いのでタイミング依存の物が書きにくい
「製品」を作るためのプラットホームとしては不適当。
・初心者向きにしてあるが故に少し難しいことをやろうとするとArduinoを使用しない方がむしろ簡単
・MPUの勉強にはならないのでArduino以外への環境にステップアップしたいときの労力がかなり大きい。
恐らく多くの人はここから抜け出すことがかなり難しい。
但しPIC+MPASMで勉強を始めた人よりは多くの目的を達成することが出来るだろう。
センサーは3本足トランジスター型のホールIC(ドリルが邪魔で見えない)
オリジナルのプログラムは380行ほどあり、それと比べるとかなり小さく記述できているがArduinoという環境による削減効果が半分、この程度のコードで我慢せざるを得なかったという点が半分。
0001 //
0002 // Tachometer written by kuromaguro 2010-02-05 Japan
0003 //
0004 const byte Digit_N = 0xFF;
0005 const byte Digit_0 = 0x03;
0006 const byte Digit_1 = 0x9F;
0007 const byte Digit_2 = 0x25;
0008 const byte Digit_3 = 0x0D;
0009 const byte Digit_4 = 0x99;
0010 const byte Digit_5 = 0x49;
0011 const byte Digit_6 = 0x41;
0012 const byte Digit_7 = 0x1F;
0013 const byte Digit_8 = 0x01;
0014 const byte Digit_9 = 0x09;
0015
0016 const byte STATUS_READY = 0;
0017 const byte STATUS_START = 1;
0018 const byte STATUS_DISPLAY = 2;
0019
0020 int led_seg_A = 3;
0021 int led_seg_B = 4;
0022 int led_seg_C = 5;
0023 int led_seg_D = 6;
0024 int led_seg_E = 7;
0025 int led_seg_F = 8;
0026 int led_seg_G = 9;
0027
0028 int led_dig_4 = 13;
0029 int led_dig_3 = 12;
0030 int led_dig_2 = 11;
0031 int led_dig_1 = 10;
0032
0033 byte led_val[4];
0034 byte led_pos;
0035
0036 volatile unsigned int count;
0037 volatile byte stat;
0038 volatile unsigned long start_micros;
0039 volatile unsigned long end_micros;
0040 volatile unsigned long rotate;
0041
0042
0043 void setup() {
0044 pinMode( led_seg_A, OUTPUT );
0045 pinMode( led_seg_B, OUTPUT );
0046 pinMode( led_seg_C, OUTPUT );
0047 pinMode( led_seg_D, OUTPUT );
0048 pinMode( led_seg_E, OUTPUT );
0049 pinMode( led_seg_F, OUTPUT );
0050 pinMode( led_seg_G, OUTPUT );
0051
0052 pinMode( led_dig_4, OUTPUT );
0053 pinMode( led_dig_3, OUTPUT );
0054 pinMode( led_dig_2, OUTPUT );
0055 pinMode( led_dig_1, OUTPUT );
0056
0057 led_val[3] = Digit_8;
0058 led_val[2] = Digit_8;
0059 led_val[1] = Digit_8;
0060 led_val[0] = Digit_8;
0061
0062 led_pos = 1;
0063
0064 count = 0;
0065 stat = STATUS_READY;
0066 attachInterrupt(0, interrupt_rotate, FALLING); // on digital pin 2
0067 }
0068
0069 void led_seg_out(byte seg_data ) {
0070 digitalWrite(led_seg_A, bitRead( seg_data, 7 ));
0071 digitalWrite(led_seg_B, bitRead( seg_data, 6 ));
0072 digitalWrite(led_seg_C, bitRead( seg_data, 5 ));
0073 digitalWrite(led_seg_D, bitRead( seg_data, 4 ));
0074 digitalWrite(led_seg_E, bitRead( seg_data, 3 ));
0075 digitalWrite(led_seg_F, bitRead( seg_data, 2 ));
0076 digitalWrite(led_seg_G, bitRead( seg_data, 1 ));
0077 }
0078
0079 void display_led() {
0080 switch( led_pos ) {
0081 case 1:
0082 digitalWrite(led_dig_4,HIGH); // LED OFF
0083 led_seg_out(led_val[0]);
0084 digitalWrite(led_dig_1,LOW); // LED ON
0085 led_pos++;
0086 break;
0087 case 2:
0088 digitalWrite(led_dig_1,HIGH);
0089 led_seg_out(led_val[1]);
0090 digitalWrite(led_dig_2,LOW);
0091 led_pos++;
0092 break;
0093 case 3:
0094 digitalWrite(led_dig_2,HIGH);
0095 led_seg_out(led_val[2]);
0096 digitalWrite(led_dig_3,LOW);
0097 led_pos++;
0098 break;
0099 case 4:
0100 digitalWrite(led_dig_3,HIGH);
0101 led_seg_out(led_val[3]);
0102 digitalWrite(led_dig_4,LOW);
0103 led_pos = 1;
0104 break;
0105 }
0106 }
0107
0108 byte ByteToDigit( byte number ) {
0109 byte return_value;
0110
0111 switch( number ) {
0112 case 0: return_value = Digit_0; break;
0113 case 1: return_value = Digit_1; break;
0114 case 2: return_value = Digit_2; break;
0115 case 3: return_value = Digit_3; break;
0116 case 4: return_value = Digit_4; break;
0117 case 5: return_value = Digit_5; break;
0118 case 6: return_value = Digit_6; break;
0119 case 7: return_value = Digit_7; break;
0120 case 8: return_value = Digit_8; break;
0121 case 9: return_value = Digit_9; break;
0122 }
0123 return return_value;
0124 }
0125
0126 void LongToDigit( unsigned long rpm ) {
0127 byte val[4];
0128
0129 val[0] = Digit_0;
0130 for( int i = 1 ; i < 4 ; i++ ) {
0131 val[i] = Digit_N;
0132 }
0133 for( int i = 0 ; i < 4 ; i++ ) {
0134 if( rpm != 0 ) {
0135 val[i] = ByteToDigit( (byte)(rpm % 10) );
0136 }
0137 rpm = rpm / 10;
0138 }
0139 for( int i = 0 ; i < 4 ; i++ ) {
0140 led_val[i] = val[i];
0141 }
0142 }
0143
0144 void loop()
0145 {
0146 unsigned long diff_long;
0147 unsigned long tmp;
0148 unsigned long rpm;
0149
0150 display_led();
0151 delay(1);
0152
0153 if( count < 2000 ) {
0154 count++;
0155 } else {
0156 led_val[0] = Digit_0;
0157 for( int i = 1 ; i < 4 ; i++ ) {
0158 led_val[i] = Digit_N;
0159 }
0160 stat = STATUS_READY;
0161 }
0162
0163 if( stat == STATUS_DISPLAY ) {
0164 if( start_micros < end_micros ) {
0165 diff_long = end_micros - start_micros;
0166 tmp = diff_long / 1000;
0167 rpm = rotate * 60000L / tmp;
0168 }
0169 LongToDigit( rpm );
0170 stat = STATUS_READY;
0171 }
0172 }
0173
0174 void interrupt_rotate()
0175 {
0176 switch( stat ) {
0177 case STATUS_READY:
0178 stat = STATUS_START;
0179 start_micros = micros();
0180 rotate = 0;
0181 count = 0;
0182 break;
0183 case STATUS_START:
0184 rotate++;
0185 if( count >= 1000 ) {
0186 end_micros = micros();
0187 stat = STATUS_DISPLAY;
0188 }
0189 break;
0190 }
0191 }
0192
0193 //--------- E N D -------------------------------------------------------
0194
後でわかったことを追記(2013-11-07)
・7セグメントLEDの桁ストローブ(同時に点灯しているように見せかける処理)はタイマー割り込みを使う
・タイマー割り込みはMsTimer2。標準ではインストールされないのでダウンロード必要
上記プログラムはこれらを使用していない。
2010-02-11
20枚程度基板を作る予定。これが最終基板パターン。
2010-03-14
基板が届いたのでキット化開始。FT232の半田付けが難しいので器用な人向けキット。
2010-03-15
キット化完了。基板のみも¥600で販売。
袋詰め
試作機(左)と量産機(右)