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

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

物理実験用簡易計測器

物理実験用簡易計測器


物理実験用教材でいろいろ測れるものが市販されているのですが,複数導入するには
ちょっとお値段が高めなので,あくまで簡易的に測れるものを低価格でできないか,
ということで,マイコンを使って作ってみました.
6ch入力で,超音波センサで距離を測ったり,ログを取ったり,
複数のデジタルセンサでラップタイムを測って速度や加速度を計算したり
するものです.
目的とすることができそうなところまで作ったので公開します.
あとはぼちぼちソフト組みます.

超音波センサで距離計測してみたところ↓

CIMG0553.JPG

Arduinoのスケッチを公開→ 物理実験プラットフォーム


// ----------------------------------------------------------------------------------
// 物理実験プラットフォーム Ver 0.1
//     
// PC0-PC5: 6チャンネル Analog or Digital入力
// PB0-5はパネル入力スイッチ
// PB0:Go,PB1:Back, PB2:Cursor Down, PB3:Cursor Up, PB4:Cursor Right, PB5:Cursor Left
// PD2-7: LCDコントロール
// 更新履歴
// 2010.10.04  開発開始
// 2010.10.05  Ver0.1 とりあえず原型できた
// ----------------------------------------------------------------------------------

#include < LiquidCrystal.h>
#include < MsTimer2.h>

#define ACH1 0 // アナログ入力定義 (ACH1-6)
#define ACH2 1
#define ACH3 2
#define ACH4 3
#define ACH5 4
#define ACH6 5

#define DCH1 14 // デジタル入力定義 (DCH1-6)
#define DCH2 15
#define DCH3 16
#define DCH4 17
#define DCH5 18
#define DCH6 19

#define SW_GO 8 // パネルスイッチ定義
#define SW_BACK 9
#define SW_DOWN 10
#define SW_UP 11
#define SW_RIGHT 12
#define SW_LEFT 13

int cnt;
int mmenu;
long pw, pwB; // 距離測定に使うパルス幅を読み取る変数,pwBは一つ前の値で割込みで保持
int vps;
int dch[7];
unsigned long time; // 内部時計読み取り用変数
unsigned long time2, time3, time4, time5, time6; // センサ差分時間
int logdat[500];
int logcnt;

// LiquidCrystal lcd(rs, rw, enable, d4, d5, d6, d7);
LiquidCrystal lcd(2, 19, 3, 4, 5, 6, 7);


// ----------------------------------------------------------------------------------
// 割り込みにより呼び出す.ボタンやボリュームを監視,LCDを表示
// ----------------------------------------------------------------------------------
void disp(){

// 速度計算
cnt++; if (cnt>5){ // 100ms×5=500ms(0.5秒)毎に速度計算
cnt=0;
vps=(pwB-pw)*2;
pwB=pw;
}

// ログ用カウンタ(499以下の時にカウントアップ)
if (logcnt<499) logcnt++;

}

// ----------------------------------------------------------------------------------
// 各種測定関数
// ----------------------------------------------------------------------------------

// 距離の測定
void distance(){
lcd.clear();
lcd.print("distance");

while (digitalRead(SW_BACK)==HIGH){
pw=pulseIn(DCH1,HIGH)/55;
lcd.setCursor(0,1); lcd.print(pw); lcd.print("cm ");
lcd.setCursor(7,1); lcd.print(vps); lcd.print("cm/sec ");
}
}

// ラップタイムの測定
void laptime(){
int i;
lcd.clear();
lcd.print("meas. lap time");

lcd.setCursor(0,1); lcd.print("set default");
while (digitalRead(SW_GO)==HIGH); // ”GO”ボタン待ち
dch[1]=digitalRead(DCH1);
dch[2]=digitalRead(DCH2);
dch[3]=digitalRead(DCH3);
//dch[4]=digitalRead(DCH4);
//dch[5]=digitalRead(DCH5);
//dch[6]=digitalRead(DCH6);
delay(1000);
lcd.setCursor(0,1); lcd.print("ready ");

while(digitalRead(DCH1)==dch[1]);
time=millis(); // 内部時計の初期値を読む
lcd.setCursor(0,1); lcd.print("Timer start! ");
while(digitalRead(DCH2)==dch[2] && digitalRead(SW_GO)==HIGH); // センサの変化待ち,GOボタンで抜ける
time2=millis()-time;
lcd.setCursor(0,1); lcd.print("measured lap 2 ");
while(digitalRead(DCH3)==dch[3] && digitalRead(SW_GO)==HIGH); // センサの変化待ち,GOボタンで抜ける
time3=millis()-time;
lcd.setCursor(0,1); lcd.print("measured lap 3 ");
/*
while(digitalRead(DCH4)==dch[4] && digitalRead(SW_GO)==HIGH); // センサの変化待ち,GOボタンで抜ける
time4=millis()-time;
lcd.setCursor(0,1); lcd.print("measured lap 4 ");
while(digitalRead(DCH5)==dch[5] && digitalRead(SW_GO)==HIGH); // センサの変化待ち,GOボタンで抜ける
time5=millis()-time;
lcd.setCursor(0,1); lcd.print("measured lap 5 ");
while(digitalRead(DCH6)==dch[6] && digitalRead(SW_GO)==HIGH); // センサの変化待ち,GOボタンで抜ける
time6=millis()-time;
lcd.setCursor(0,1); lcd.print("measured lap 6 ");
*/
delay(1000);

// 測定結果表示
i=2;
while (digitalRead(SW_BACK)==HIGH){
if (digitalRead(SW_DOWN)==LOW){ i++; if (i>3) i=2; }
if (digitalRead(SW_UP)==LOW) { i--; if (i<2) i=3; }
delay(200); // ボタンはなす時間をちょっと待ち
switch (i){
case 2: lcd.setCursor(0,1); lcd.print("1->2 :"); lcd.print(time2); lcd.print("ms "); break;
case 3: lcd.setCursor(0,1); lcd.print("1->3 :"); lcd.print(time3); lcd.print("ms "); break;
//case 4: lcd.setCursor(0,1); lcd.print("1->4 :"); lcd.print(time4); lcd.print("ms "); break;
//case 5: lcd.setCursor(0,1); lcd.print("1->5 :"); lcd.print(time5); lcd.print("ms "); break;
//case 6: lcd.setCursor(0,1); lcd.print("1->6 :"); lcd.print(time6); lcd.print("ms "); break;
}
}
}

// 距離のログを取って表示 ログは100msごと,割込み周期
void logdist(){
int i;
lcd.clear();
lcd.print("distance log");
// メモリクリア
for (i=0;i<499; i++) logdat[i]=0;

lcd.setCursor(0,1); lcd.print("Waiting ");
while (digitalRead(SW_GO)==HIGH); // ”GO”ボタン待ち
lcd.setCursor(0,1); lcd.print("Logging ");
logcnt=0;
while(logcnt<500 && digitalRead(SW_BACK)==HIGH){
logdat[logcnt]=(int)(pulseIn(DCH1,HIGH)/55);
}
lcd.setCursor(0,1); lcd.print("Finish! ");
delay(1000);

// ログ結果表示
i=0;
while (digitalRead(SW_BACK)==HIGH){
if (digitalRead(SW_DOWN)==LOW){ i++; if (i>499) i=0; }
if (digitalRead(SW_UP)==LOW) { i--; if (i<0) i=499; }
delay(100);
lcd.setCursor(0,1); lcd.print(i); lcd.print(":"); lcd.print(logdat[i]); lcd.print(" ");
}
}

// アナログ信号読み取り表示
void analog(){
int i=1;
lcd.clear();
lcd.print("analog read");
while (digitalRead(SW_BACK)==HIGH){
if (digitalRead(SW_DOWN)==LOW){ i++; if (i>6) i=1; }
if (digitalRead(SW_UP)==LOW) { i--; if (i<0) i=6; }
lcd.setCursor(0,1); lcd.print("CH"); lcd.print(i); lcd.print(":");
switch (i){
case 1: lcd.print(analogRead(ACH1)); break;
case 2: lcd.print(analogRead(ACH2)); break;
case 3: lcd.print(analogRead(ACH3)); break;
case 4: lcd.print(analogRead(ACH4)); break;
case 5: lcd.print(analogRead(ACH5)); break;
case 6: lcd.print(analogRead(ACH6)); break;
}
lcd.print(" ");
}
}

// デジタル信号読み取り表示
void digital(){
lcd.clear();
lcd.print("digital read");
while (digitalRead(SW_BACK)==HIGH){
lcd.setCursor(0,1); if (digitalRead(DCH1)==LOW) lcd.print(0); else lcd.print(1);
lcd.setCursor(2,1); if (digitalRead(DCH2)==LOW) lcd.print(0); else lcd.print(1);
lcd.setCursor(4,1); if (digitalRead(DCH3)==LOW) lcd.print(0); else lcd.print(1);
lcd.setCursor(6,1); if (digitalRead(DCH4)==LOW) lcd.print(0); else lcd.print(1);
lcd.setCursor(8,1); if (digitalRead(DCH5)==LOW) lcd.print(0); else lcd.print(1);
lcd.setCursor(10,1); if (digitalRead(DCH6)==LOW) lcd.print(0); else lcd.print(1);
}
}


// ----------------------------------------------------------------------------------
// 初期化
// ----------------------------------------------------------------------------------
void setup() { // スタート時1度だけ実行

lcd.clear();
lcd.print("Phys.EX Platform");

// パネルのスイッチを入力に設定
pinMode(SW_GO,INPUT);
pinMode(SW_BACK,INPUT);
pinMode(SW_DOWN,INPUT);
pinMode(SW_UP,INPUT);
pinMode(SW_RIGHT,INPUT);
pinMode(SW_LEFT,INPUT);
// パネルのスイッチをプルアップ(入力ピンにHIGHを書くとプルアップ)
digitalWrite(SW_GO,HIGH);
digitalWrite(SW_BACK,HIGH);
digitalWrite(SW_DOWN,HIGH);
digitalWrite(SW_UP,HIGH);
digitalWrite(SW_RIGHT,HIGH);
digitalWrite(SW_LEFT,HIGH);

logcnt=0; // ログ用カウンタリセット
MsTimer2::set(100,disp); // 100ms(1/10秒)で割込み,disp()を呼び出す
MsTimer2::start();
}

// ----------------------------------------------------------------------------------
// 繰り返し実行
// ----------------------------------------------------------------------------------
void loop(){

if (digitalRead(SW_DOWN)==LOW){
while(digitalRead(SW_DOWN)==LOW);
mmenu++; if(mmenu>4) mmenu=0;
}
if (digitalRead(SW_UP)==LOW){
while(digitalRead(SW_UP)==LOW);
mmenu--; if(mmenu<0) mmenu=4;
}

// display main menu
lcd.setCursor(0,1);
switch (mmenu){
case 0: lcd.print("Meas. distance"); break;
case 1: lcd.print("Meas. lap time"); break;
case 2: lcd.print("log distance "); break;
case 3: lcd.print("Meas. analog "); break;
case 4: lcd.print("Meas. digital "); break;

}

// jump measure
if (digitalRead(SW_GO)==LOW){
while(digitalRead(SW_GO)==LOW);
switch (mmenu){
case 0: distance(); break;
case 1: laptime(); break;
case 2: logdist(); break;
case 3: analog(); break;
case 4: digital(); break;
}
lcd.clear(); // 測定をして帰ってきたときは画面クリア
lcd.print("Phys.EX Platform");
}
}


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