3/2011
35/49

#include <12F675.h>#device ADC=10#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR,BROWNOUT#use delay (clock=4000000)#byte RA=5#bit sig = RA.5 //サーボへの信号#bit LED_r = RA.1//赤LED#bit LED_g = RA.2//緑LED#bit sw_1 = RA.3//赤スイッチ#bit sw_2 = RA.4//緑スイッチvoid main() { long int value,onT,off T,shuki=14000;//周波数が70Hzになるようにshukiを調整 long int v2,v4;//2バイトの変数を追加 byte i,j,v1,v3,iv2,iv4; set_tris_a(0x19);//01,1001 GP1,GP2,GP5が出力ポート、他は入力に設定 setup_adc_ports(NO_ANALOGS); setup_adc_ports(AN0_ANALOG);//ポート0をアナログに設定 setup_adc(ADC_CLOCK_INTERNAL);//ADCのクロックを内部クロックに設定 while(1){ set_adc_channel(0); //ADCを読み込むピンを指定 delay_us(40); value = read_adc(); //読み込み onT=948+value; off T=shuki-onT; v1=onT/1000; v2=onT % 1000; v3=off T/1000;v4=off T % 1000; iv2=v2/8;iv4=v4/8;//v2,v4は999を超えないので、8で割れば255以内 for(i=0;i<8;i++){ sig=1; delay_ms(v1); for(j=0;j<iv2;j++){ delay_us(1); } sig=0; delay_ms(v3); for(j=0;j<iv4;j++){ delay_us(1); } } }} このプログラムでは、delay_us(1);をforループで指定された回数回るというアイディアです。理論的には100回ループすれば、delay_us(100);に相当するはずです。これなら、ループ変数をlongでとれば、1000回ループしても問題はありません。 しかし、これはあくまで理論的な話で、現実はループをすることでのタイムロスは0ではありません。delay_us(1);を100回ループするに必要な時間は1/1万秒とはなりません。もっと多くの時間を要します。これは、マイコンのクロックにも依存します。今回はレゾネータを省略して4MHzで動作していますが、このクロックを速くすれば、タイムロスは減少します。オシロスコープで何回かプログラムのパラメータを変えて(変えたのはv2、v4を割り算する値の8)現実的な値を見つけ出しました。工夫したプログラムによって、若干のタイムロスがいくつか生じて、周波数も70Hzを下回ったので、shukiの値も少し変えました。これで、ほぼ、ボリュームを回したときと同じ感覚でサーボの軸位置が決まります。ボリュームを回してから、ほんのわずかのタイムラグがあってサーボが反応しますがこれは、for(i=0;i<8;i++){8の値のためです。これは、ボリュームで決まった電圧値によって、同一の波形を8回送るためものです。このループを入れないと、電圧チェック(ボリュームの位置チェック)の頻度が上がります。8の値を多くとれば、反応が遅くなります。減らせば、反応は速くなります。実験では、8の値を4にしても問題なく、むしろリアルタイムに動くようです。−33−実験ノート

元のページ  ../index.html#35

このブックを見る