PICとメカな日々

Webにも萌えにも限界を感じたオタクがPICマイコンをいじる日々。

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

バイナリ時計のデバッグ

 その後バイナリ時計を動かしてたが、時刻の1の桁が時々不正表示になる現象が発生。

 原因が何かしばらくわからんかったが、桁をドライブしてるRA4ポートがオープンドレインのためにHレベルにしても電圧が十分上がらず、RB0~3からLED経由でかかってくる電圧を逆流させていることが判明。

 オープンドレインについてはこのサイトを参照。

 もはや余ったポートもないので、スイッチに使ってたPORTBのピンと入れ替えたら治った。
スポンサーサイト

とりあえずバイナリ時計作った。

 なんとなく時計でも作るかと思って、検索したらどっかのページにあった2進数時計を作ってみる。

 bin_clock


16F84のポートほぼ全部を使って、4×6のLEDマトリックスを動かしてる。PORTBの0~3が4ビットの表示、残りをシンク側の桁ドライブと時刻調整のスイッチに使用。
 最初はトランジスタで桁ドライブしてやらんとうごかんかと思ったが、よく考えたらシンク電流が25mAとれるので、4ビット同時点灯としても5mAくらいは流せるんだった。実際には0~9までの表示しかないから同時点灯は3つまで。てことは7mAくらいでもOK。よって、

 LEDの電圧降下=1.5V
 LED電流=7mA
 LED抵抗=(5.0V-1.5V)÷7mA=500Ω

となる。

 クロックは本当は水晶にしないといかんのだろうけど、あとで取り替える事にして当面10Mhzのセラロックを使う。2^nじゃないクロックだからプログラムが面倒だが。

 回路図はこう。

binary_clock


プログラムはコレ。長くてスマン。

 ちなみにまだ出来たばっかりで、致命的なバグがあるかもしれんのでこれをコピーして同じもん作るとか考えたりしないように>見てる人

/*

  時計の習作 PIC16F84使用
  10Mhzセラロック仕様
  
*/
#include<pic.h>
#include<delay.h>
__CONFIG(0x3FF2);        //CONFIG:CP=OFF,PWRT=ON,WDT=OFF,OSC=HS

void display(void);
void time_adjust(void);

unsigned long timer_count=0;  //タイマ定数設定
unsigned char hour=0;
unsigned char min=0;
unsigned char sec=0;
void main(void)
{
  PSA=0;          //プリスケーラを使用する
  PS2=1;
  PS1=0;
  PS0=0;          //プリスケーラは1:32

  T0CS=0;          //クロックソースは内部命令サイクル
  TMR0=0;          //TMR0をリセット
  T0IF=0;          //T0IFをリセット
  
  T0IE=1;          //TMR0割り込み発生を許可
  GIE=1;          //割り込みを許可
  
  PORTA=0b00000000;      //PORTAをリセット
  PORTB=0b11110000;      //PORTBをリセット
  TRISA=0b00000000;      //RAを出力に設定
  TRISB=0b11100000;      //RB5,6,7を入力に設定
  
  PORTA=0b00000000;      //PORTAをリセット
  PORTB=0b11110000;      //PORTBをリセット

  while(1)          //無限ループ
  {
    display();        //時刻表示
    time_adjust();      //時刻調整
  }
}

void display()          //時刻表示ルーチン
{
  //hourの10の桁
  PORTA=0b00011111;      
  RB4=1;            //全列OFF

  PORTB = (0xF0 & PORTB) | (0x0F & (hour/10));    //PORTBの下4bitにhourの10の桁出力
  RB4=0;            //hourの10の桁ON
  DelayMs(1);
  
  //hourの1の桁
  PORTA=0b00011111;      
  RB4=1;            //全列OFF
  
  PORTB = (0xF0 & PORTB) | (0x0F & (hour%10));    //PORTBの下4bitにhourの1の桁出力
  RA4=0;            //hourの1の桁ON
  DelayMs(1);
  
  //minの10の桁
  PORTA=0b00011111;      
  RB4=1;            //全列OFF
  
  PORTB = (0xF0 & PORTB) | (0x0F & (min/10));    //PORTBの下4bitにminの10の桁出力
  RA3=0;            //minの10の桁ON
  DelayMs(1);
  
  //minの1の桁
  PORTA=0b00011111;      
  RB4=1;            //全列OFF
  
  PORTB = (0xF0 & PORTB) | (0x0F & (min%10));    //PORTBの下4bitにminの1の桁出力
  RA2=0;            //minの1の桁ON
  DelayMs(1);
  
  //secの10の桁
  PORTA=0b00011111;      
  RB4=1;            //全列OFF
  
  PORTB = (0xF0 & PORTB) | (0x0F & (sec/10));    //PORTBの下4bitにsecの10の桁出力
  RA1=0;            //secの10の桁ON
  DelayMs(1);
    
  //secの1の桁
  PORTA=0b00011111;      
  RB4=1;            //全列OFF
  
  PORTB = (0xF0 & PORTB) | (0x0F & (sec%10));    //PORTBの下4bitにsecの1の桁出力
  RA0=0;            //secの1の桁ON
  DelayMs(1);
}

void time_adjust()
{
  //hourのカウントアップ
  if(RB5){          //hourスイッチを見る
    DelayMs(30);      //チャタリング待ち
    if(RB5){
      hour++;
      if(hour >=24){
        hour = 0;
      }
    }
    while(RB5){      //ボタンがオフになるまで待つ
      display();    //待っている間の表示
    }
    DelayMs(50);      //も一回押すには0.05秒待ち
  }
  
  //minのカウントアップ
  if(RB6){          //minスイッチを見る
    DelayMs(30);      //チャタリング待ち
    if(RB6){
      min++;
      if(min >= 60){
        min = 0;
      }
    }
    while(RB6){      //ボタンがオフになるまで待つ
      display();    //待っている間の表示
    }
    DelayMs(50);      //も一回押すには0.05秒待ち
  }
  //secのカウントアップ
  if(RB7){          //secスイッチを見る
    DelayMs(30);      //チャタリング待ち
    if(RB7){
      sec++;
      if(sec >= 60){
        sec = 0;
      }
    }
    while(RB7){      //ボタンがオフになるまで待つ
      display();    //待っている間の表示
    }
    DelayMs(50);      //も一回押すには0.05秒待ち
  }
}

interrupt clock_count()          //割り込みルーチン
{
  if(T0IF){
    T0IF = 0;            //割り込みフラグクリア
    TMR0=131;            //TMRを125カウントに指定:256-125=131
    timer_count++;
    if(timer_count == 625){
      timer_count =0;        //タイマカウント(1sec=10M=4*32*125*625)
      sec++;
      if(sec >= 60){
        sec = 0;
        min++;
        if(min >= 60){
          min = 0;
          hour++;
          if(hour >= 24){
            hour = 0;
          }
        }
      }
    }
  }
}

S7136の実験

 センサ実験シリーズの続き。こんどは浜松ホトニクスのS7136。

S7136-1


 S7136と赤外LEDのTLN115Aを組み合わせる。このS7136てセンサは、自力でLEDを点滅させて外乱光の影響を排除したセンシングができるそうな。

S7136-2


 まずそのまま通電した場合。S7136からの出力は0vになる。

 S7136-3


 次に仕切り板で赤外LEDとの間をさえぎった場合。出力は5V弱に。

 出力がデジタルだから、A/DポートのないPICでも使いやすいわけだな。前面にあるモノを感知するためにはセンサ回りに一工夫いりそうだけど。

MCLRはプルアップだった

 とりあえず16F84でなんか作ってみたが、なぜか動かない。
 実験基盤の方ではちゃんと動くので、セラロックが悪いのか電源なのか接触不良なのかずっと悩んでたが、ようやく原因が判明。

 リセット信号のMCLRはプルアップしておかないといかんのだった。フリーにしたから0vに落ちたことになってリセットがかかってたんだな。

もう届いた

 土曜日に頼んだばかりなのにもう届いた。早いぞマルツパーツ。

マルツパーツ館も使う

 部品を通販で買う際、おおむね値段とか品揃えを考えると秋月がもっともポピュラーだとは思うんだが、たまに無いモノがあったり単価は安いがロットがやたら大きかったりといろいろ問題もある。
 んで、支払い手段でクレジットカードが使えないのも問題なんだよな。代引きになるのでサラリーマンの場合ヨメの人にお願いしないといけない。

 その辺考えて、マルツパーツの方も使ってみることにした。


http://www.marutsu.co.jp/


 単価は多少高いが、クレジットカードが使えて送料も安い。さしあたって、16F84で時計関係のモノをつくるためのクリスタルと、RS232C関係のチップ等を購入。

PIC12F675使うか

 さて、温度センサ実験にオペアンプ実験と来たんで、秋月ライタも手に入ったことだし次はA/D変換の練習を考える。

 PICC-Liteが使えてA/D変換のあるPICとなると、使いやすいのは12F675。安いし。

 しかし、問題はA/D変換した結果をどうやって確認するかだよな。ポートが6つしかないからA/D入力にひとつ使うとのこり5本。16F84の時みたいに8ビットポートを丸ごとLEDに出力して確認することもできんしな。

 やっぱこの本にあるみたいにシリアルポートにつなぐしか無いかなあ。

フォトセンサ実験

 こんどはフォトセンサの実験。LM35と同様カホパーツセンターで売ってた代物。GP2S05ちゅうて、秋月だと10個300円で安く売ってる。

GP2S05 秋月通販


 データシートはこれ。

 見ての通り赤外LEDとフォトトランジスタが一体化してる。大きさが小さいんでブレッドボードでの実験が出来ないため、ユニバーサル基盤で実験回路を組む。
GP2S05-2


 写真だと見にくいが、テスタで出力電圧を見ると4.27V。

GP2S05-3


 白いものをセンサの近くに持っていくと、出力電圧が1.92Vになる。

GP2S05-4


 同じ白いものでも、反射状態が違うと3.08Vに。

 センサの型番でググるとライントレーサーには広く使われてるらしいが、全面や側面で使おうとすると検出距離が短すぎるかも。

オペアンプ実験

 温度センサのLM35Dも買ってきたけど、これは出力電圧が10.0mV/℃になってる。つまり0℃なら0Vで100℃なら1.0Vと直線になってるので非常に使いやすいわけだが、A/D変換しようとすると0~5Vの範囲を10bitで拾うわけだから、有効範囲のほんの一部しか拾えない。
 もっと精度を高めようとすると電圧を増やしてやる必要があるということで、オペアンプが必要になる。

 オペアンプの使い方については以下のサイトを参考にする。

 古閑先生のサイトにある電子回路設計の基礎
 http://www.picfun.com/circuitframe.html

 Wikipedia:「オペアンプ」の項

 こないだコミケ帰りに秋月寄って、なんとなく買った物の中にオペアンプICのLM358があったのでこれを使って実験。可変抵抗でアナログ信号を作って、ブレッドボードにオペアンプ回路を組んで出力をテスタで見る。

 LM358


 回路図はこんな感じ。
OPAMP


 実験した結果。


in  out  増幅度
0.00 0.01
0.03 0.38 12.67
0.13 1.45 11.15
0.24 2.74 11.42
0.34 3.15 9.26
0.38 3.16 8.32
1.22 3.15 2.58



 使った抵抗値はR1=1kΩ、R2=10kΩなので
 増幅度A=1+R2/R1 = 11.00

 出力電圧が上がってくると3.15Vあたりで飽和してるみたいだけど、LM358のデータシート
http://markun.cs.shinshu-u.ac.jp/learn/OPamp/Manual/lm358.html
を見ると


出力電圧振幅 Vo=0~+Vs-1.5



 とあるので、電源電圧4.5Vから1.5V引くと3.0V。だいたいこんなところか。

PICライタ買ってきた

 そろそろ16F84評価基盤から脱出するため、定番の秋月PICライタを買ってきた。カホパーツで電源・ケーブル込みのセットを購入。あわせてVer.4アップデートキットも購入。

AKI-PICkit


 キットなので作ること自体はさほど難しくない。

AKI-PIC


 むしろ問題は、基盤むき出しでケースなしなんでどうすっかだよな。コレ使ってる人は各自でケースに入れてるらしいが。

 16F84に縛られなくなったので、PICC-Lite対応範囲からアナログポートの付いてるものってことで12F675もひとつ買ってきた。んで、アナログポートがあるからにはアナログセンサもいるだろうと温度センサのLM35も購入。
PIC12F675

LM35DZ


 12F675とLM35DZのほうは、とりあえずA/D変換の学習に使用する予定。

センサ買うぞ

 コミケの2日目西館でこんな本売ってたので買ってきた。

 同人誌


 他にもハードウェア系サークルの本いろいろ買ってきたが、今回いちばん役に立ちそうなシロモノ。Hi-Tech PICC-Liteの本てあたりがミソですな。
 そんで、読んでて注目したのが2冊目のロボット製作記事。光センサとモータドライバIC使ってロボット作ってるんだが、よさげな光センサデバイスが使われてますな。浜松ホトニクスのS7136ちゅうシロモノ。

 ググると、やっぱしツクモロボット館で通販してた。

http://www.rakuten.co.jp/tsukumo/435950/456281/456282/

 ついでにツクモロボット館のセンサのあたりを見ると、他にも使えそうなセンサがいろいろと。

 例:シャープの光学測距センサ。
http://www.rakuten.co.jp/tsukumo/435950/437048/

 しかしなんだ、IC化されたセンサって出力がアナログ電圧で出てくるのが多かったりするから、やっぱPICのほうもA/D変換ついてるチップを使うこと考えた方が良いのかもしれんな。16F628とか。

 なにはともあれセンサを調達するため、S7136と赤外LED、それにGP2D12も一個買ってみることにする。

ドライバICの実験

 しばらく止まっていたエアロRCの自律化計画だが、何もしないのも退屈なので正月休みのついでに関係部品の実験をしてみる。

 ツクモロボット館から届いたドライバIC。
TA7291P


これがどんな感じに動くか実験回路を組んでみる。ブレッドボードにTA7291Pを突っ込んで、データシート見ながら電源やら信号線やらつないでみる。信号の入力は10kΩでプルダウンしたスイッチに接続。

TEST_CIRCUIT


 まず電源電圧を測ってみる。
BATT

 単3三本なので定格4.5V、実測4.37V。

 次に、スイッチ1を押して正転状態で図った出力電圧。
NORMAL

 プラス方向に3.71Vの電圧が発生。

 さらに、スイッチ2を押して逆転状態で図る。
REVERSE

 マイナス方向に3.70Vの電圧が発生。

 というわけで、一応意図通りにドライバICからモーター動かすための正転・逆転状態の電圧は出てくる。が、トランジスタでスイッチを切り替えてるためにどうしても4.37-3.71=0.66Vの電圧降下が起きるという事ですな。
 もっと電圧の高いモーターなら0.66Vくらいの効果はあまり気にしなくてもいいかもしれんが、元が3Vで動かそうかというモーターだけにこの電圧降下は結構バカにならない。
 それに、3V駆動だとPIC用に別途電源を用意する必要も生じるわけで、結局エアロRCに元々搭載できる単3×2本では済みそうにないという事か。どうすっかな。

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。