| 二進数マイコンロボットの製作 | |
|
|
![]() 画面の明るさを読み取って、腕を上げるロボットを作ります。 白い画面にセンサーを近づけて電源を入れると、 明るさを調べて白と黒の境界値を決めます。 境界値が決まると腕を上下します。失敗すると腕を下げます。 白と黒の画面を作るプログラム作って、実行すると、センサーの下のカメが黒から白に変わるとラジコンサーボが動きます。黒にもどすとニュートラルの位置にもどります。 ※ラジコンサーボは、分解して、中にある可変抵抗器を取り外すと、回転するようになります。 |
|
| <準備> 1体あたりの製作費は、1500円程度です。 | |
・ ラジコンサーボ・・・2個(450円~の安物で良い)・ フォトリフレクタ(白黒で電流の流れが変化するセンサー) ・・・・2個(80円×2)・ PICマイコン PIC12F1572・・・・1個(140円)、ICソケット・・・・1個(11円)・抵抗 470Ω2本・・・・(数円)、300Ω2本・・・・(数円) ・スイッチ、電池ボックス(3本用)、スズメッキ線、導線 |
| 1.部品を配線する |
![]() |
| <電池ボックスの外に配線した例> |
![]() |
| <電池ボックスの上に配線した例> |
![]() |
| 2.プログラミングの準備 |
| C言語でプログラミングするには、MPLAB X IDE を起動して、以下の手順で行います。 |
| 1 | を起動します。 |
| ・起動すると、これまでに作ったプロジェクトがあると、左側に一覧で表示されます。 |
| 2 | プロジェクトを作成します。 | |
| ・プログラムは、プロジェクトごとに管理されます。1つのプログラムに1つのフォルダとして1つのプロジェクトになります。 プログラミングした内容は、プロジェクトの中にファイルとして作ります。 | ||
| (1) | File → New Project... | ![]() |
| (2) | Choose Project → Standard Project | |
| (3) | Select Device → Family = Mid Range 8-bit → PIC12F683 | ![]() |
| (4) | Select Compiler → XC8 | ![]() |
| (5) | Select Project Name and Folder → Project Name | |
| 3 | プログラムファイルを作ります。 | |
| ・プロジェクトの中にファイルを作り、そこにプログラムを書いていきます。1つのプロジェクトに1つのファイルが普通で、複数のファイルを作ったときは1つのファイルとして考えます。 | ||
| (1) | ファイルを作る場所を指定する | ![]() |
| (2) | File → Newfile... |
|
| (3) | File Name を書き入れて 終わり |
|
| 4 | プロジェクトのプロパティーを設定します。 | |
| ・作ったプログラムをPICに書き込めるように、PICkit3の電圧設定をします。 | ||
| (1) | プロジェクト名を右クリックして、プロパティーを開く | ![]() |
| (2) | PICkit3のPower を撰ぶ |
![]() |
| (3) | チェックを入れて4.75Vに設定する |
|
| 3.プログラミング |
| ・プログラムファイルのプログラムを書いていきます。 | ||
| // --------------------------------------------------------------------------------------------- // 2進数ROBOT PIC12F1572 (C)2025.12.27 inakakoubouKANAI // フォトトランジスタ(LBR-127HLD受光部) 2個使い PCモニタ判定でサーボを動かす //1 Vdd 電源 (+) 電源のプラス(3.3V〜5V)を接続 //2 RA5 デジタル入力 (未使用)※ADC不可。プルアップ //3 RA4 アナログ入力(AN3) 左センサー(LBR-127HLDのEmitter) //4 RA3 デジタル入力 ノイズ対策用(内部プルアップ設定済み) //5 RA2 アナログ入力(AN2) 右センサー(LBR-127HLDのEmitter) //6 RA1 PWM1出力 サーボ1(右側)の信号線へ //7 RA0 PWM2出力 サーボ2(左側)の信号線へ //8 Vss 電源 (-) 電源のマイナス(GND)を接続 // --------------------------------------------------------------------------------------------- |
||
| #include <xc.h> #define _XTAL_FREQ 16000000 // CONFIGURATION BITS #pragma config FOSC = INTOSC #pragma config WDTE = OFF #pragma config PWRTE = ON #pragma config MCLRE = OFF #pragma config CP = OFF #pragma config BOREN = ON #pragma config LVP = OFF |
・このPICをどれくらいのクロックで使うか、ピンの役割をどうするかなどの設定。 ・#pragma config LVP は、電圧が下がったときのリセット機能だが OFF にしておかないとRA3ピンを入力ピンとして使えない。 |
|
| unsigned int GS_RA1; unsigned int GS_RA0; unsigned int pulse1; unsigned int pulse2; int THRESHOLD1; int THRESHOLD2; |
・プログラムで使うグローバル変数の宣言。 | |
| // ADC読み取り関数 unsigned int read_ADC(unsigned char channel) { // チャンネル選択(RA2=AN2, RA4=AN3) ADCON0 = (unsigned char)((channel << 2) | 0x01); __delay_us(50); // サンプリング時間を多めに確保 ADGO = 1; while(ADGO); return ((unsigned int)((ADRESH << 8) | ADRESL)); } |
・アナログ信号を受け取るための設定。 | |
| void set_calibration() { THRESHOLD1 = 1023; // 左センサー(RA4) unsigned int val_left = read_ADC(3); // RA4(AN3) while (val_left < THRESHOLD1) { val_left = read_ADC(3); // RA4(AN3) THRESHOLD1 -=10; if (THRESHOLD1<10){ THRESHOLD1 = 10; break; } } THRESHOLD1 -=10; THRESHOLD2 = 1023; // 右センサー(RA2) unsigned int val_right = read_ADC(2); // RA2(AN2) while (val_right < THRESHOLD2) { val_right = read_ADC(2); // RA2(AN2) THRESHOLD2 -=10; if (THRESHOLD2<10){ THRESHOLD2 = 10; break; } } THRESHOLD2 -=10; // --- キャリブレーションの成否 --- if ((THRESHOLD1==0)||(THRESHOLD1==1013)||(THRESHOLD2==0)||(THRESHOLD2==1013)) { out_PWM1(4000); out_PWM2(2000); __delay_ms(100); } else { // 1回目:両腕上げ out_PWM1(2000); // 右上げ out_PWM2(4000); // 左上げ __delay_ms(300); // 2回目:両腕ニュートラル out_PWM1(3000); out_PWM2(3000); __delay_ms(300); // 3回目:もう一度両腕上げ out_PWM1(2000); out_PWM2(4000); __delay_ms(300); // 最後にニュートラルに戻して終了 out_PWM1(3000); out_PWM2(3000); __delay_ms(500); // 落ち着くまで少し待つ } } |
・フォトリフレクターからの読取り感度のキャリブレーションを行う。 ・紙の白黒で動作させるときは、白の紙ぶフォトリフレクターを向けて電源を入れる。 ・PCモニターの白黒で動作させるときは、フォトリフレクターのLED電源のソケットを抜いて、フォトリフレクターを画面の白の上に向けて電源を入れる。 ・キャリブレーションが成功すると腕を上下に動かす。 |
|
| void p_initialize() { OSCCON = 0b01111000; // 16MHz // ANSELA: RA4(AN3), RA2(AN2)をアナログ入力に設定 ANSELA = 0b00010100; // TRISA: RA0,RA1=出力, 他=入力 TRISA = 0b00111100; // ADC設定: 右詰め, Fosc/16, Vref=Vdd ADCON1 = 0b10100000; // ノイズ対策:未使用ピン(RA3, RA5)のプルアップ OPTION_REGbits.nWPUEN = 0; WPUA = 0b00101000; INTCON = 0x00; PORTA = 0b00000000; } |
・8本あるピンの使い方の設定。 それぞれのピンが入力か出力か、デジタルかアナログか、内部抵抗を使うか、使わないかなので、設定ができるが、PICの種類による規定がある場合もある。 |
|
| void out_Initialize(void) { unsigned int PWM_PERIOD = 31999; // 実績のある設定に基づき周期を設定 PWM1PRH = (PWM_PERIOD >> 8) & 0xFF; PWM1PRL = PWM_PERIOD & 0xFF; PWM2PRH = (PWM_PERIOD >> 8) & 0xFF; PWM2PRL = PWM_PERIOD & 0xFF; // クロック源設定 PWM1CLKCON = 0b00000000; PWM2CLKCON = 0b00000000; PWM1TMR = 0; PWM2TMR = 0; // プリスケーラー 1:64 (0b110 << 3) PWM1CLKCON &= 0b11100111; PWM1CLKCON |= (0b110 << 3); PWM2CLKCON &= 0b11100111; PWM2CLKCON |= (0b110 << 3); // PWM有効化 PWM1CON = 0b11000000; PWM2CON = 0b11000000; // 初期デューティ (1.5ms) PWM1DCH = (3000 >> 8) & 0xFF; PWM1DCL = 3000 & 0xFF; PWM2DCH = (3000 >> 8) & 0xFF; PWM2DCL = 3000 & 0xFF; PWM1PHH = 0; PWM1PHL = 0; PWM2PHH = 0; PWM2PHL = 0; // ロード更新 PWM1LDCONbits.LDA = 1; PWM2LDCONbits.LDA = 1; while(PWM1LDCONbits.LDA == 1 || PWM2LDCONbits.LDA == 1); } |
・PWMを作るための設定。 実際の出力をオシロスコープで検証しながら設定した。PICに書かれた仕様書と異なるがこれで正常に動作する。 |
|
| void out_PWM1(unsigned int GSP) { PWM1DCH = (GSP >> 8) & 0xFF; PWM1DCL = GSP & 0xFF; PWM1LDCONbits.LDA = 1; while(PWM1LDCONbits.LDA == 1); } void out_PWM2(unsigned int GSP) { PWM2DCH = (GSP >> 8) & 0xFF; PWM2DCL = GSP & 0xFF; PWM2LDCONbits.LDA = 1; while(PWM2LDCONbits.LDA == 1); } |
・ラジコンサーボを動かすデジタル信号をPICに内蔵されたハードウェアでPWMとして出力するための設定。 PICによって、この機能があるのと無いのとがある。 |
|
| void out_steering() { // アナログ値の読み取り unsigned int val_left = read_ADC(3); // RA4(AN3) unsigned int val_right = read_ADC(2); // RA2(AN2) // 左センサー(RA4) -> PWM2(RA0) if(val_left > THRESHOLD) { GS_RA0 = 4000; // 左 } else { GS_RA0 = 3000; // ニュートラル } out_PWM2(GS_RA0); // 右センサー(RA2) -> PWM1(RA1) if(val_right > THRESHOLD) { GS_RA1 = 2000; // 右 } else { GS_RA1 = 3000; // ニュートラル } out_PWM1(GS_RA1); } |
・フォトリフレクターからの信号によって、どのようにラジコンサーボを動かすかを設定している。 | |
| void main(void) { p_initialize(); out_Initialize(); set_calibration(); while(1) { out_steering(); __delay_ms(10); } } |
・プログラムが起動したとき最初に実行されるメインルーチン。 ・while(1)で永久ループにしておく。 |
|
| 4.ビルド |
| ・ Loading completed と出たら、ビルド成功です。 |
![]() |
| 5.書込み |
・PIC12F1572をセットして、 Programming/Verify complete と出たら書込み成功です。 |
![]() |
| 6.完成 |
| フォトリフレクターが白黒を読み取って、白だとラジコンサーボの腕を上げます。 |
白黒の紙で動かすときは、白い紙をフォトリフレクターの前に置いて電源を入れます。 電源が入り、腕が上がります。 白い紙を無くすと腕が前になります。 |
PCの画面で動かすときは、フォトリフレクターのLEDの電源ソケットを抜いて、 白い画面にフォトリフレクターを向けて電源を入れます。 キャリブレーションが終わると、腕を上下します。 画面が白から黒に変わると、腕を前にします。 |
クレーンゲームの賞品に組み込んでみました。 |
.gif)