000000 ランダム
 HOME | DIARY | PROFILE 【お気に入りブログ登録】 【ログイン】

CPUを作ろう ~計算機教材とマイコンと電子工作~

太陽光追尾装置

前出の装置は,太陽光を追尾する装置です.
物理の先生からのご注文で,光学の実験で鏡を使って太陽光を教室内に入れておくことができないか?とのことで,それをマイコン制御で作ってみました.
太陽の当たる場所に設置して,太陽が動いても鏡の角度を変えて指定した方向に光を送り続けます.下の写真のように鏡の片隅に部分的にセンサ用のサブミラー(ビニールテープで囲った部分)を作り,サブミラーを受けるセンサの光分布がずれたときに修正をかけるように制御しています.

製作中↓
CIMG2986.JPG

CIMG2987.JPG

ハード完成↓

CIMG2994.JPG

動作試験中↓

CIMG2999.JPG

センサ部分↓
CIMG3003.JPG

最初にサブミラーの光がセンサに当たるように調節すればあとはそれを維持してくれます.
光がセンサーから外れてしまうと修正することはできませんが,太陽はゆっくりしか動かないので実用上は問題なし.
構造上,ステッピングモータのステップ角以下での調整はできませんので近距離用.遠くに光を送る場合は,ギヤダウンが必要ですが,同様の構造でそれなりのものは作れると思います.

太陽光追尾装置:鏡をずらしても自動で鏡が調整される動画.

製作はAVRのAtmega328Pを使い,ソフトウェアはArduinoのIDEで作成.

回路は以下の通りポートを使用するように作成.

PB0-PB3 左右回転のステップモータ(配線:橙,黄,青,赤の順に励起,白と黒は+V)
PD4-PD7 上下回転のステップモータ(同上)
PD2 上ボタン(ボタンは10kΩでプルアップしてポートへ)
PD3 下ボタン
PB4 右ボタン
PB5 左ボタン

AN0 光センサ(右)フォトトランジスタを100Ωでエミッタフォロワにしてポートへ.
AN1 光センサ(左)
AN2 光センサ(下)

PC3 LED1 モード表示,0:制御なし,1:制御あり
PC4 LED2 センサ全部しきい値以上かどうか.しきい値以下のセンサがあれば調整.
PC5 モード切替ボタン

プログラムについて,
モータは1-2相励磁でステップ角を細かくする.
3角形に配置したセンサの光が当たってない方向に光を当てるように鏡を調整.
センサの値はシリアル出力してPCでモニタ可能とする.

Arduinoのスケッチ.
(ポートを直接まとめてアクセスするとまれに励磁が抜けることがあったので,1本ずつ励磁パターンを与えている)

//**************************************************************************
//
// 太陽光追従光実験システム Sunflower 熊本高専 葉山清輝
//
// 2011.6.22 Ver 1.0 
//**************************************************************************
#define PTR 0 // 右センサ,アナログ入力
#define PTL 1 // 左センサ,アナログ入力
#define PTD 2 // 下センサ, アナログ入力


#define R_BTN 12 // 右ボタン
#define L_BTN 13 // 左ボタン
#define U_BTN 2 // 上ボタン (AN3)
#define D_BTN 3 // 下ボタン (AN4)
#define EX_BTN 19 // スタートスイッチ(AN5)
#define LED1 17 // LED表示, モード0:消灯,モード1:点灯
#define LED2 18 // LED表示, 一部しきい値以下:0,全センサしきい値以上:1

#define RTH 8000
#define LTH 8000
#define DTH 8000

// 割込み内で値を変化させる変数はVolatileで宣言が必要
volatile int patRL=0, patUD=0; // モータの励磁パターンの位相
volatile int sensR, sensL, sensD; // センサの値
volatile int mode=0; // 制御モード,0:初期設定,1自動制御,EXボタンで交互に入替え

//--------------------------------------------------------------------------
// 鏡制御開始
//--------------------------------------------------------------------------
void MirrorOn() {
patRL=0; patUD=0;
MotorOut();
}

//--------------------------------------------------------------------------
// 鏡右回転
//--------------------------------------------------------------------------
void MirrorR() {
if (patRL > 0) patRL--; else patRL = 7;
MotorOut();
}

//--------------------------------------------------------------------------
// 鏡左回転
//--------------------------------------------------------------------------
void MirrorL() {
if (patRL < 7) patRL++; else patRL = 0;

MotorOut();
}

//--------------------------------------------------------------------------
// 鏡上回転
//--------------------------------------------------------------------------
void MirrorU() {
if (patUD > 0) patUD--; else patUD = 7;
MotorOut();
}

//--------------------------------------------------------------------------
// 鏡下回転
//--------------------------------------------------------------------------
void MirrorD() {
if (patUD < 7) patUD++; else patUD = 0;
MotorOut();
}

//--------------------------------------------------------------------------
// モータ出力
//--------------------------------------------------------------------------
void MotorOut() {
switch (patRL){
case 0:
digitalWrite(8,HIGH);
digitalWrite(9,LOW);
digitalWrite(10,LOW);
digitalWrite(11,LOW);
break;
case 1:
digitalWrite(8,HIGH);
digitalWrite(9,HIGH);
digitalWrite(10,LOW);
digitalWrite(11,LOW);
break;
case 2:
digitalWrite(8,LOW);
digitalWrite(9,HIGH);
digitalWrite(10,LOW);
digitalWrite(11,LOW);
break;
case 3:
digitalWrite(8,LOW);
digitalWrite(9,HIGH);
digitalWrite(10,HIGH);
digitalWrite(11,LOW);
break;
case 4:
digitalWrite(8,LOW);
digitalWrite(9,LOW);
digitalWrite(10,HIGH);
digitalWrite(11,LOW);
break;
case 5:
digitalWrite(8,LOW);
digitalWrite(9,LOW);
digitalWrite(10,HIGH);
digitalWrite(11,HIGH);
break;
case 6:
digitalWrite(8,LOW);
digitalWrite(9,LOW);
digitalWrite(10,LOW);
digitalWrite(11,HIGH);
break;
case 7:
digitalWrite(8,HIGH);
digitalWrite(9,LOW);
digitalWrite(10,LOW);
digitalWrite(11,HIGH);
break;


}
switch (patUD){
case 0:
digitalWrite(4,HIGH);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
break;
case 1:
digitalWrite(4,HIGH);
digitalWrite(5,HIGH);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
break;
case 2:
digitalWrite(4,LOW);
digitalWrite(5,HIGH);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
break;
case 3:
digitalWrite(4,LOW);
digitalWrite(5,HIGH);
digitalWrite(6,HIGH);
digitalWrite(7,LOW);
break;
case 4:
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(6,HIGH);
digitalWrite(7,LOW);
break;
case 5:
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
break;
case 6:
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,HIGH);
break;
case 7:
digitalWrite(4,HIGH);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,HIGH);
break;
}
}


//--------------------------------------------------------------------------
// センサー処理
//--------------------------------------------------------------------------
void Sens(void) {
sensR +=analogRead(PTR);
sensL +=analogRead(PTL);
sensD +=analogRead(PTD);
}

//--------------------------------------------------------------------------
// モードチェンジ ,割込みで処理
//--------------------------------------------------------------------------
void chmod(void) {
if (digitalRead(EX_BTN)==LOW) {
if (mode==0) {
mode=1;
digitalWrite(LED1,HIGH);
} else {
mode=0;
digitalWrite(LED1,LOW);
}
delay(400); // チャタリング防止
}
}

//--------------------------------------------------------------------------
// 初期化
//--------------------------------------------------------------------------
void setup()
{
pinMode( 4, OUTPUT); // PD4-7 左モータ
pinMode( 5, OUTPUT);
pinMode( 6, OUTPUT);
pinMode( 7, OUTPUT);
pinMode( 8, OUTPUT); // PB0-4 右モータ
pinMode( 9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);

pinMode(U_BTN, INPUT);
pinMode(D_BTN, INPUT);
pinMode(R_BTN, INPUT);
pinMode(L_BTN, INPUT);

pinMode(LED1, OUTPUT); // mode
pinMode(LED2, OUTPUT); // センサ状態:全しきい以上かどうか

Serial.begin(9600); // シリアルポートを開く,壁センサチェック用

MirrorOn();
}

//--------------------------------------------------------------------------
// メインループ
//--------------------------------------------------------------------------
void loop()
{
int i;

if (digitalRead(U_BTN)==LOW || digitalRead(D_BTN)==LOW || digitalRead(R_BTN)==LOW || digitalRead(L_BTN)==LOW ){

if (digitalRead(U_BTN)==LOW) MirrorU();
if (digitalRead(D_BTN)==LOW) MirrorD();
if (digitalRead(R_BTN)==LOW) MirrorR();
if (digitalRead(L_BTN)==LOW) MirrorL();
delay(75);

} else {

sensR=sensL=sensD=0;
for (i=0;i<20;i++){
Sens();
chmod();
delay(100);
if (digitalRead(U_BTN)==LOW || digitalRead(D_BTN)==LOW || digitalRead(R_BTN)==LOW || digitalRead(L_BTN)==LOW ) break;
}
if (sensR>RTH && sensL>LTH && sensD>DTH) digitalWrite(LED2,HIGH); else digitalWrite(LED2,LOW);

if (mode==1) {
if (sensR< RTH && sensL >LTH ) MirrorR();
else if (sensR> RTH && sensL< LTH ) MirrorL();
else if (sensR< RTH && sensL< LTH){
if (sensD >DTH) {if (sensR< sensL) MirrorR(); else MirrorL(); }
}
if (sensR> RTH && sensL >LTH && sensD< DTH ) MirrorD();
if (sensD> DTH && sensR< RTH && sensL< LTH) MirrorU();
}
}

Serial.print("sensR:"); Serial.println(sensR);
Serial.print("sensL:"); Serial.println(sensL);
Serial.print("sensD:"); Serial.println(sensD);


}


Copyright (c) 1997-2018 Rakuten, Inc. All Rights Reserved.