太陽の追尾装置の製作

サーボモータと光センサーで太陽の追尾装置を作ってみた。 太陽追尾というか、よーするに明るいところを追いかける装置です。 
f:id:manpukukoji:20171004121609j:plain
マイコンは、16F1827、センサーは、Cdsセルで、上下左右、4つのセンサーで、上下でより明るい方、左右でより明るい方を向くようにサーボモータをコントロール。 上下で120度、左右180度の可動範囲になっています。
センサーの隔壁は、最初、筒型のパトリオットミサイルのランチャーみたいなのを試してみたのですが、いまいち、うまく作動しなかったので、シンプルな、田の字型の隔壁スタイルにしたら、わりと良さげだったので、これを採用。
f:id:manpukukoji:20171004121640j:plain
一応、基盤は汎用性をもたせて、サーボのコントロール部分をメイン基盤とし、センサー部分は、ドーターボードのようにして別基盤にしています。
ライトでグリグリやると、なんか面白いです。

サーボモータで光を追跡

回路図は、以下
f:id:manpukukoji:20171004112237p:plain

ほんでもって、PICのプログラムは、以下です。

/*	Project Twin servo control
	PIC16F1827 with two servo moter and 4 Cds cell sensor
	trace the britest spot (Sun tracker)
*/

/*PIN of 16F1827 asign
	RA0 : Cds1 (Upper)		RB0 : Servo PWM Vertical
	RA1 : Cds2 (Lower)		RB1 : Servo PWM Holizontal
	RA2 : Cds3 (Right)		RB2 : Rx
	RA3 : Cds4 (Left)		RB3 : 
	RA4 :  				RB4 : 
	RA5 : MCLR			RB5 : Tx
	RA6 : 				RB6 : 
	RA7 : 				RB7 : 
*/
#include <pic.h>

#define _XTAL_FREQ  8000000    // delay用(クロック8MHzで動作時)
#define INT_START 25536		//20msの割り込みの初期値(65536-25536=40000)

__CONFIG( WRT_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & FOSC_INTOSC & CP_OFF & CPD_OFF) ;
__CONFIG(PLLEN_OFF & STVREN_ON & BORV_25 & LVP_OFF);

unsigned short next1,next2;	//next1 for UpDown, next2 for RightLeft


void delay(unsigned char d){
	int i;
	for(i=0;i<d;i++) __delay_ms(10);
}

void interrupt pwm( void )
{
    // タイマ1割り込み処理
    if( TMR1IF )
    {
        RB0 = 1;
        RB1 = 1;

        CCPR1H = (next1>>8);	//next1 for UpDown, next2 for RightLeft
		CCPR1L = (0x00ff & next1);
        CCPR2H = (next2>>8);
		CCPR2L = (0x00ff & next2);
        TMR1 = INT_START;   // 20msec毎に割り込み
        TMR1IF = 0; // タイマ割り込みフラグをクリア
    }

    // CCP1割り込み処理
    if( CCP1IF )
    {
        RB0 = 0;
        CCP1IF = 0; // コンペアマッチ割り込みフラグをクリア
    }

    // CCP2割り込み処理
    if( CCP2IF )
    {
        RB1 = 0;
        CCP2IF = 0; // コンペアマッチ割り込みフラグをクリア
    }
}



void main(void){

     int m1,m2,vdata;		//m1 for UpDown, m2 for RightLeft
	 int v1,v2,h1,h2;	//ADC value
	 
     m1=3000;		//1.5mSec
     m2=3000;

	vdata=0;
	
     OSCCON     = 0b01110010;    // 内部クロックは8MHzとする
     OPTION_REG = 0b00000000;
//割り込み設定
	 CCP1CON=0b00001010;	//compair mode
	 CCP2CON=0b00001010;
     T1CON=0b00000100;		//1:1 PreScaler
//     CCP1M=0b1010;		//CCP1 Compair Interrupt
//     CCP2M=0b1010;		//CCP2 Compair Interrupt

//pin設定
     TRISA  = 0b00101111;    // 1で入力 0で出力 RA0-RA3:Input RA6-RA7:Outputに設定(RA5は入力専用)
     TRISB  = 0b00000000;    // RB1-RB7全てを出力に設定 RB0,RB1をサーボ制御に使用
     ANSELA = 0b00001111;    //RA0-RA3 をADCにセット
     ANSELB = 0b00000000;    //汎用ポート RB3(AN9)をADCにセット
     PORTA  = 0b00000000 ;   // RA出力ピンの初期化(全てLOWにする)
     PORTB  = 0b00000000 ;   // RB出力ピンの初期化(全てLOWにする)

//ADC設定
	 ADCON0 = 0b00100100;
	 ADCON1 = 0b11000000;	//右寄せ, Fosc/8

//割り込み初期値
    TMR1IE = 1; // タイマ1割り込み有効
    CCP1IE = 1; // コンペアマッチ割り込み有効
    CCP2IE = 1; // コンペアマッチ割り込み有効

    TMR1 = INT_START;
    next1 = INT_START + 3000;  // 1.5msec
    next2 = INT_START + 3000;  // 1.5msec

    TMR1ON = 1; // タイマ1 開始

    TMR1IF = 0;
    CCP1IF = 0;
    CCP2IF = 0;
    PEIE = 1;
    GIE  = 1;    // 全割り込み有効


while(1) {

//ADC 

//ADC0
	ADCON0=0b00000011;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	v1=vdata;
	
//ADC1
	ADCON0=0b00000111;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	v2=vdata;


//ADC2
	ADCON0=0b00001011;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	h1=vdata;

//ADC3
	ADCON0=0b00001111;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	h2=vdata;

//Compair brightness
//Vertical direction
	if(v1>v2){
		if((v1-v2)>3){
			m1=m1+(v1-v2);
			if(m1>=4000){m1=4000;}
		}
	}
	else if(v1<v2){
		if((v2-v1)>3){
			m1=m1-(v2-v1);
			if(m1<=1900){m1=1900;}
		}
	}

	next1=INT_START+m1;
	
//Holizontal direction
	if(h1>h2){
		if((h1-h2)>3){
			m2=m2+(h1-h2);
			if(m2>=4800){m2=4800;}
		}
	}
	else if(h1<h2){
		if((h2-h1)>3){
			m2=m2-(h2-h1);
			if(m2<=1000){m2=1000;}
		}
	}
	
	next2=INT_START+m2;
	

	delay(10);

}	//End of While
}	//End of main

百均のルーターの歯とマブチモーターでミニテーブルソーを作ってみたら・・・。

百均のミニルーター用の、のこぎり歯を使ってちょこっとしたミニテーブルソーみたいなのができないかな? と思って、模型用のマブチモータを使って作ってみたけど、何も切れなかったというお話・・・。  失敗談です。
f:id:manpukukoji:20171004092329j:plain
もともと、基盤とかを切るのにいちいちゴキゴキやっているのも面倒なので、ちっちゃいテーブルソーみたいなのがあれば、チョイーンと切れちゃって、とっても便利かな? と、思ったんだけど、そんなに甘くはなかった・・・。
結果は、こんな感じ。

百均のルーターの歯でミニテーブルソーを作ってみたら・・・。

使ったモータは、RE-280 というモデルで、3V駆動で、適正負荷が15gf・cm となっている。
要するに、モータの選択を間違ったということかな? ギアボックスとか使えば、力は出せるだろうけど、その分回転速度が落ちちゃうから、やっぱり、もう少し、でっかいモータでやるべきなんでしょうね。
また、なんか良さげなモータが手に入ったら、試してみようかな・・・って、懲りないね・・・。

調光式懐中電灯を光センサにつないだサーボで受けると・・・。

光の強度で回転をコントロールするようにしたサーボモータに、調光式の懐中電灯の光を当ててみたところ、光の強さをおとしたモードにすると、サーボモータがジワジワと変な動きをし始めた。

調光式懐中電灯を光センサにつないだサーボで受けると・・・。

この懐中電灯は、光(最強)→光(中)→光(弱)→点滅モード→SOSモード と、順に切り替えることができるようになっている。
この懐中電灯の光を光センサー(Cdsセル)に受けて、AD変換してその値に応じてサーボモータの角度をコントロールしたところ、このビデオのように光の中と弱のときにジワジワとサーボが動いて、安定しなかった。
どうやら、調光するのに、PWMでコントロールしているようで、目ではわからない速度で点滅していて、それを光センサーは感じ取ったようだ。実際にばらして回路を調べたわけではないけれど、同様に光センサーで点滅速度を調べてみると、240Hz くらいで点滅しているみたい・・・。思ったよりも高い周波数だった。
ちなみに、点滅モードとSOSモードでは、もちろん、ギュンギュンとサーボは、暴れたが、ついでに、しらべたら、点滅は7Hzくらいで点滅していた。

PIC16F1827でサーボモータ2軸を制御

PIC16F1827を使ってサーボモーター2個をコントロールしてみた。
f:id:manpukukoji:20170924104300j:plain
16F1827は、タイマー1の割り込みでコンペアモードが4つ使えるみたいなので、4つのサーボモーターがコントロールできそう・・・。
とりあえず、ADコンバータ使って、半固定抵抗で電圧をぐりぐりやって2軸を動かしてみた。
f:id:manpukukoji:20170927085603p:plain
使ったサーボモータは、GWSのMINI STD というのと、TowerProのSG-5010 ですが、使うサーボによって、プログラムの値を変更しないと、ならないと思います。
このまま使って、高価なサーボモータ壊しちゃったりしないようにご注意ください。
あくまでも、自己責任で・・・。よろしく!

ちなみに、僕は、いまだに古いMPLAB IDE(v8.6)でHiTech-C使っているので、最新のIDEとは、ちょっと違うと思うけど、include のヘッダとか、Configrationの表記以外は、だいたい、似たようなものではないかと思います。

プログラムは、以下

/*	Project Twin servo control
	PIC16F1827 with two servo moter and 2VR AD control
*/

/*PIN of 16F1827 asign
	RA0 : VR1 				RB0 : Servo1 Control
	RA1 : VR2 				RB1 : Servo2 Control
	RA2 : 	 				RB2 : 
	RA3 : 	 				RB3 : 
	RA4 :  					RB4 : 
	RA5 : MCLR				RB5 : 
	RA6 : 					RB6 : 
	RA7 : 					RB7 : 
*/
#include <pic.h>

#define _XTAL_FREQ  8000000    // delay用(クロック8MHzで動作時)
#define INT_START 25536		//20msの割り込みの初期値(65536-25536=40000)

__CONFIG( WRT_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & FOSC_INTOSC & CP_OFF & CPD_OFF) ;
__CONFIG(PLLEN_OFF & STVREN_ON & BORV_25 & LVP_OFF);

unsigned short next1,next2;	//next1 for UpDown, next2 for RightLeft

void delay(unsigned char d){
	int i;
	for(i=0;i<d;i++) __delay_ms(10);
}

void interrupt pwm( void )
{
    // タイマ1割り込み処理
    if( TMR1IF )
    {
        RB0 = 1;
        RB1 = 1;

        CCPR1H = (next1>>8);	//next1 for UpDown, next2 for RightLeft
		CCPR1L = (0x00ff & next1);
        CCPR2H = (next2>>8);
		CCPR2L = (0x00ff & next2);
        TMR1 = INT_START;   // 20msec毎に割り込み
        TMR1IF = 0; // タイマ割り込みフラグをクリア
    }

    // CCP1割り込み処理
    if( CCP1IF )
    {
        RB0 = 0;
        CCP1IF = 0; // コンペアマッチ割り込みフラグをクリア
    }

    // CCP2割り込み処理
    if( CCP2IF )
    {
        RB1 = 0;
        CCP2IF = 0; // コンペアマッチ割り込みフラグをクリア
    }
}

void main(void){

     unsigned long m1,m2,vdata;		//m1 for UpDown, m2 for RightLeft
     unsigned int f1,f2; //flag for PWM increase or decrease	 

     m1=3000;		//1.5mSec
     m2=3000;

	vdata=0;
	
     OSCCON     = 0b01110010;    // 内部クロックは8MHzとする
     OPTION_REG = 0b00000000;
//割り込み設定
	 CCP1CON=0b00001010;	//compair mode
	 CCP2CON=0b00001010;
     T1CON=0b00000100;		//1:1 PreScaler

//pin設定
     TRISA  = 0b00101111;    // 1で入力 0で出力 RA0-RA3:Input RA6-RA7:Outputに設定(RA5は入力専用)
     TRISB  = 0b00000000;    // RB1-RB7全てを出力に設定 RB0,RB1をサーボ制御に使用
     ANSELA = 0b00001111;	//RA0-RA3 をADCにセット
     ANSELB = 0b00000000;	//汎用ポート RB3(AN9)をADCにセット
     PORTA  = 0b00000000 ; // RA出力ピンの初期化(全てLOWにする)
     PORTB  = 0b00000000 ; // RB出力ピンの初期化(全てLOWにする)

//ADC設定
	 ADCON0 = 0b00100100;
	 ADCON1 = 0b11000000;	//右寄せ, Fosc/8

//割り込み初期値
    TMR1IE = 1; // タイマ1割り込み有効
    CCP1IE = 1; // コンペアマッチ割り込み有効
    CCP2IE = 1; // コンペアマッチ割り込み有効

    TMR1 = INT_START;
    next1 = INT_START + 3000;  // 1.5msec
    next2 = INT_START + 3000;  // 1.5msec

    TMR1ON = 1; // タイマ1 開始

    TMR1IF = 0;
    CCP1IF = 0;
    CCP2IF = 0;
    PEIE = 1;
    GIE  = 1;    // 全割り込み有効

    f1=1;
    f2=1;
while(1) {

//ADC 

//ADC1
	ADCON0=0b00000011;
	__delay_ms(1);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	m1=(vdata*2400)/1024+1800;
	if(m1>=4200){m1=4200;}
	if(m1<=1800){m1=1800;}
	
//ADC2
	ADCON0=0b00000111;
	__delay_ms(1);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	m2=(vdata*3800)/1024+1000;
	if(m2>=4800){m2=4800;}
	if(m2<=1000){m2=1000;}

	next1=INT_START+m1;
	next2=INT_START+m2;


	delay(3);

}	//End of While
}	//End of main

AM2321とArduinoで温湿度計を作った

温湿度センサAM2321を使って、持ち歩き用の温湿度計を作ったけど、携帯するには、ちょっと大きくなっちゃった。
f:id:manpukukoji:20170924080014j:plain
AM2321は、以前に秋月で購入しておいた物だけど、端子のピッチが1.27とへんてこなんで使いにくい。今は、秋月でも通販していないみたいで、かわりにピッチが2.54のAM2320が販売されているようですね。
今回は、できれば持ち歩きたいと思って、プリント基板を作ってみたけど、片面基盤なんで、あまり小さくならなかった。ちなみに、僕の場合、プリント基板は、トレーシングペーパーに印刷して、ポジ感光基盤をブラックライトで感光させて作っている。
ブラックライトは、最近電気やとかホームセンタでは、手に入りにくく、車用品店でなんとか購入。
Arduinoは、ATMEGA328にブートローダを書き込んでチップ単体で3V駆動して使用。これだと、I2Cの電圧を変換しなくてすむしね。
ほんで、回路は、こんな感じ。
f:id:manpukukoji:20170924080102j:plain
で、プログラムは、これまた、あちこちのサイトを参考にさせていただき、ほとんどコピペに近いが、以下のように作成。
タクトスイッチは、温度と湿度の切り替え用
実際のところ、3Vでは、7セグの表示が暗くて、昼のアウトドアでは、よく見えない。
また、ボタン電池だと電池の持ちもいまいち・・・。
と、いうわけで、実際のところ、安定化電源から電源をとりデスクトップで室内の温度と湿度を表示している。

#include <SevSeg.h>
#include <Wire.h>

#define ADDR 0x5C

byte HH,HL,TH,TL,dummy;
int Temp, Humid, DispData;
volatile int chMode = HIGH;
volatile unsigned long time_prev = 0, time_now;

SevSeg sevseg; //Instantiate a seven segment object

void dispchg() {
  time_now = millis(); //現在の割り込み時刻を取得
  if( time_now-time_prev > 20){  
    chMode= !chMode;
  }
   time_prev = time_now;
}

void setup() {
  byte numDigits = 3;
  byte digitPins[] = {3, 6, 7}; // 左が上位桁
  byte segmentPins[] = {4, 8, 10, 12, 13, 5, 9, 11}; // A..G, DPの順

 pinMode(2,INPUT_PULLUP);

  sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins);
    Wire.begin();

 attachInterrupt(0,dispchg,RISING);
}

void loop() {
  int i,j;
  //------------------------------
    Wire.beginTransmission(ADDR);
  //Wire.write(0);
  delay(1);
  Wire.endTransmission();
  
  Wire.beginTransmission(ADDR);
  Wire.write(0x03);
  Wire.write(0x00);
  Wire.write(0x04);
  Wire.endTransmission();
  
  delayMicroseconds(1500);
  
  Wire.requestFrom(ADDR,6);
  delayMicroseconds(30);
  Wire.read();
  Wire.read();
  HH=Wire.read();
  HL=Wire.read();
  TH=Wire.read();
  TL=Wire.read();
  
  Humid=HH*256+HL;
  if(TH & 0x80){
    Temp=-1*((TH & 0x7F)*256+TL);
  }
  else{
    Temp=TH*256+TL;
  }

  
  //------------------------------
   if (chMode == HIGH) {DispData = Humid;}
   else {DispData = Temp;}
  
    for (j=0;j<100;j++){
    sevseg.setNumber(DispData, 1);
    sevseg.refreshDisplay();
    }
    delay(10);

  }

ホタルの光の色をLEDで再現・・・できるか?

f:id:manpukukoji:20160815221142j:plainホタルの光を測定する装置ができたので、早速、データを取ってみた。
何度か失敗した挙句、なんとか、それっぽいデータがとれたので、カラーLEDで再現してみた。

まず、カラーLEDでRGBをそれぞれ単色で点灯して、カラーを見てみたところ、単色で点灯しても他の色を含んでいるようだ。
ちなみに、手元のLEDでは、それぞれの色でカラーメータで3000付近に合わせたところ以下のような値が得られた。

Red Green Blue
3016 15 4
25 3042 297
8 102 2995

これを見ると、赤はそれほどでもないけれども、緑と青は、割とお互いに影響を受けているのがわかる。
これだと、得られたデータとぴったり同じ値で光らせるのは、ちょっと難しいかも・・・。
とりあえず、Arduinoで点灯回路を組んでみた。
可変抵抗で電圧をAD変換して、その値にあわせて、LEDのRGBをそれぞれPWM点灯している。

ともあれ、ホタルのデータに近い値で光らせてみたのがこの写真。

見た感じ、かなり緑に近い感じがする。 実際のホタルは、もう少し黄色が強い感じがするので、どうなのかな・・・? むしろ、周りのArduinoについている黄色のLEDの方がホタルの光の色に近いような気がする・・・。
もう少し、いろいろ試してみる必要がありそうだ。

ホタルの明滅をデータロギング

f:id:manpukukoji:20160814093208j:plain蛍の光をデータに落とすデータロガーを作ってみた。
データは、ホタルの明滅パターンを取るための、光の強度をサンプリングする光センサと、ホタルの光の色をRGBでサンプリングする、カラーセンサの2つのセンサからなっています。
これら2つのセンサからのデータをArduinoでA/D変換、サンプリングしてSDカードに記録するというもの。
回路図は、こんな感じ。
f:id:manpukukoji:20160809205608j:plain

光センサは、S9648にLM358で増幅してArduinoでA/D変換、 カラーセンサは、S9706を使ってRGBのデータを取り込み、ロジックレベル変換モジュールを通して、SDカードに記録している。
センサは、ピンポン玉を半分に切って、底部にセンサをセットして、この中にホタルを入れて、少しの間ピンポン玉の中で光ってもらう。 一応、積分球のようにホタルが中で移動しても平均的な反射光をサンプリングするような効果を期待したけど、センサがむき出しなので、あまり意味はないかもしれない。まぁ、これでいいのだ!

これまでも同様の光センサで、明滅パターンを取っていたのだけど、これまでは、カラーセンサがなく、シリアル通信でPCと直結していたので、機動性に問題があった。また、ホタルの飛ぶところは、暗いので、PCのバックライトの明かりが明るすぎて、何かと問題が多いので、今回のものに改良してみた。

使い方は、電源をONにすると、LEDが3回点滅して、光の強度測定モードで始動します。
ロギング開始ボタンを押すと、光センサからのデータがAD変換されてSDカードにdatalog.txtというファイルに記録されます。
電源をONする際に、ロギング停止ボタンを押したまま電源を入れると、カラー測定モードで始動します。
同様にロギング開始ボタンを押すと、カラーセンサからのデータがcolorlog.txt というファイルに記録されます。
入力データが上限値をこえると、LEDが点灯して入力レベルの調整が必要なことを教えてくれます。
まぁ、詳細は、スケッチを追っていただければわかると思います。
カラー測定データをシリアルモニタで見る場合は、シリアルモニタを立ち上げる際にロギング停止ボタンを押しておかないと、強度測定モードになってしまうので注意が必要です。

Arduinoのスケッチは、これまた、あちこちのサイトを参考にさせてもらって、つぎはぎして、以下のようなものになった。
自分でも、どこのスケッチを引っ張ってきたのかわからなくなっちゃっているけど、カラーセンサに関しては、こちらのサイトから、主な部分は、ほぼ、そのまま引用させていただいている。
建築発明工作ゼミ2008: Arduino デジタルカラーセンサ S9706

他にもSDカードのライブラリとかA/D変換とかセンサの扱いとかいろいろとコピペさせていただいています。
まぁ、まさにスパゲッティのようなスケッチできれいに作れていないし、改良すべきところも沢山あるけど、ひとつの参考までに、以下、スケッチです。

#include <SD.h>

#define LED_PIN 4	// 4番ピンをデーターLogging 開始LEDに設定       Light Intensity
#define STARTBUTTON 2	// 2番ピンをデータLogging開始に設定		Light Intensity
#define STOPBUTTON 3	// 3番ピンをデータLogging開始に設定		Light Intensity
#define PEAK_LED 7	// 7番ピンをピークLEDに設定		        Light Intensity

#define RANGE 6		//  8番ピンをRange端子に設定		        Color Sensor
#define GATE  16	//  9番ピンをGate端子に設定			Color Sensor
#define CK   5		// 10番ピンをCK端子に設定			Color Sensor
#define DOUT 15		// 11番ピンをDout端子に設定			Color Sensor

volatile int loggmode=0;		//Logging mode 設定のための変数 (1=Light Intensity mode / 0=Color mode)

int red,green,blue;   //RGB三色の変数を用意 for Color Sensor

// この値は使用しているシールドや基板に合わせて変更すること。たとえば、
// イーサーネットシールドは 4
// Adafruit のSDシールドは 10
// Sparkfun のSDシールドは 8
const int chipSelect = 10;	//自作のSDシールドは10番ピンで作成
unsigned long tm,ptm;		//期間(millis)の計算のための変数
int mm;
volatile int loggsts=0;	  //Logging Startのフラグ
volatile int datapos=0;  //data start endのマーク
File dataFile;

//start buttonを押したときの割り込み処理
void loggstrt()
{
  loggsts=1;
  digitalWrite(LED_PIN,HIGH);
  datapos = 1;
}

//Stop Buttonを押したときの割り込み処理
void loggstp()
{
  loggsts=0;
  digitalWrite(LED_PIN,LOW);
  digitalWrite(PEAK_LED,LOW);
  datapos = 2;  
}

void setup()
{
  int i;
  
  pinMode(LED_PIN,OUTPUT);
  pinMode(PEAK_LED,OUTPUT);

    //Range,Gate,CK端子をデジタル出力に設定
  pinMode(RANGE,OUTPUT);
  pinMode(GATE,OUTPUT);
  pinMode(CK,OUTPUT);
  //Dout端子をデジタル入力に設定
  pinMode(DOUT,INPUT);


  // シリアルポート初期化
  Serial.begin(9600);

  Serial.print(F("Initializing SD card..."));

  // SSピン(Unoは10番、Megaは53番)は使わない場合でも出力にする必要があります。
  // そうしないと、SPIがスレーブモードに移行し、SDライブラリが動作しなくなります。
  pinMode(SS, OUTPUT);

  // SDライブラリを初期化
  if (!SD.begin(chipSelect)) {
    Serial.println(F("Card failed, or not present"));
    // 失敗、何もしない
    while(1);
  }
  Serial.println(F("ok."));

  // 日付と時刻を返す関数を登録
  SdFile::dateTimeCallback( &dateTime );
  
   tm = millis();
   mm=0;
  
    //Pull Up 設定
    pinMode(STARTBUTTON, INPUT_PULLUP);
    pinMode(STOPBUTTON, INPUT_PULLUP);

	//Logg mode の設定(0=Light Intensity / 1=Color sensor)…Logging停止ボタンを押して電源をいれるとカラーモードになる。
	loggmode = digitalRead(STOPBUTTON);

	// カラーモードのときには、LEDを5回点滅
	if (loggmode==0){
		for(i=1;i<6;i++){
			digitalWrite(LED_PIN,HIGH); digitalWrite(PEAK_LED,HIGH); delay(500);
			digitalWrite(LED_PIN,LOW); digitalWrite(PEAK_LED,LOW); delay(500);
		}
        }
 	// 光強度モードのときには、LEDを3回点滅
	if (loggmode==1){
		for(i=1;i<4;i++){
			digitalWrite(LED_PIN,HIGH); digitalWrite(PEAK_LED,HIGH); delay(500);
			digitalWrite(LED_PIN,LOW); digitalWrite(PEAK_LED,LOW); delay(500);
		}
        }
   
    //割り込み設定
    attachInterrupt(0,loggstrt,FALLING);
    attachInterrupt(1,loggstp,FALLING);
    
    loggsts=0;
}


void loop()
{
// ------------ Light Intnsity Logging  ----------------------------------------
	if(loggmode==1)
	{	
	  if(loggsts==1)
	  {
		// ファイルを開く
		   dataFile = SD.open("datalog.txt", FILE_WRITE);

		 // もしファイルが開けたら値を書き込む
		  if (dataFile) {
		    ptm=tm;
		    tm=millis();
		    int value = analogRead(0);
    
                    if(datapos == 1){dataFile.println("S");}
		    dataFile.print(tm-ptm);
		    dataFile.print(",");
		    dataFile.println(value);
                    if(datapos == 2){dataFile.println("E");}
                    datapos = 0;
		    dataFile.close();
		    // シリアルポートにも出力
		    Serial.print(tm-ptm);
		    Serial.print(",");
		    Serial.println(value);
    
			//データが最大値に達したら、LEDを点灯
		    if (value>730){digitalWrite(PEAK_LED,HIGH);}
		    else {digitalWrite(PEAK_LED,LOW);}

    
		  }
		  // ファイルが開けなかったらエラーを出力
		  else {
		    Serial.println(F("error opening datalog.txt"));
		  } 

		  // 一秒待つ
		//  delay(1000);

	  } // ---------- End of loggsts==1 ... Logging Start ------------------------------
	}	// ---------- End of loggmode==1 ... Light Intensity Logging ----------------------------------


// ---------------Color Logging --------------------------------------------
	if(loggmode==0)
	{
		if(loggsts==1)
		{
				// ファイルを開く
		   dataFile = SD.open("colorlog.txt", FILE_WRITE);

		 // もしファイルが開けたら値を書き込む
		  if (dataFile) {
//		    int value = analogRead(0);
			// >>>>>>>>>>>>>>>>>>>>>>>>>>
			  //測光時間用の可変抵抗器の読み込み(アナログ入力:0番ピン)
			int val=1000;

			//Gate,CK端子をLowに設定
			digitalWrite(GATE,LOW);
			digitalWrite(CK,LOW);
			delayMicroseconds(2000);//2000マイクロ秒待機

			//感度設定(HIGH:高感度に設定)  
			digitalWrite(RANGE,HIGH);

			//測光開始(光量の積算を開始) 
			digitalWrite(GATE,HIGH);
			//測光時間(valを代入し可変的に設定)
			delay(val+1);
  
			//測光終了(光量の積算を終了) 
			digitalWrite(GATE,LOW);
			delayMicroseconds(4);//4マイクロ秒待機
  
			red=shiftIn();//赤の処理
			green=shiftIn();//緑の処理
			blue=shiftIn();//青の処理

			//Gate端子をHighに戻す  
			digitalWrite(GATE,HIGH);

		    ptm=tm;
		    tm=millis();

                    if(datapos == 1){dataFile.println("S");}
		    dataFile.print(tm-ptm);
		    dataFile.print(",");
		    dataFile.print(val,DEC);
		    dataFile.print(",");
		    dataFile.print(red,DEC);
			dataFile.print(",");
			dataFile.print(green,DEC);
			dataFile.print(",");
			dataFile.println(blue,DEC);
                    if(datapos == 2){dataFile.println("E");}
                    datapos = 0;
		    dataFile.close();

		    // シリアルポートにも出力
		    Serial.print(tm-ptm);
		    Serial.print(",");
		    Serial.print(val,DEC);
		    Serial.print(",");
			Serial.print(red,DEC);
			Serial.print(",");
			Serial.print(green,DEC);
			Serial.print(",");
			Serial.println(blue,DEC);
 

			// >>>>>>>>>>>>>>>>>>>>>>>>>
    
  
			//データが最大値に達したら、LEDを点灯
		    if ((red>4000)||(green>4000)||(blue>4000)) {digitalWrite(PEAK_LED,HIGH);}
		    else {digitalWrite(PEAK_LED,LOW);}

    
		  }
		  // ファイルが開けなかったらエラーを出力
		  else {
		    Serial.println(F("error opening datalog.txt"));
		  } 

		  // 一秒待つ
		//  delay(1000);

		}	// End of loggsts==1 ... Logging Start ------------------------
	}	// ---------- End of Loggmode==0 ... Color Logging ----------------

}	// End of loop

void dateTime(uint16_t* date, uint16_t* time)
{
  uint16_t year = 2015;
  uint8_t month = 7, day = 4, hour = 12, minute = 0, second = 0;

  // GPSやRTCから日付と時間を取得
  // FAT_DATEマクロでフィールドを埋めて日付を返す
  *date = FAT_DATE(year, month, day);

  // FAT_TIMEマクロでフィールドを埋めて時間を返す
  *time = FAT_TIME(hour, minute, second);
}

//12ビット分のパルス送信と読み込み処理
int shiftIn(){
  int result=0;//検出結果用の変数を用意(0:初期化)
  for(int i=0;i<12;i++){//12ビット分の繰り返し処理
    digitalWrite(CK,HIGH);//1ビット分のクロックパルス出力(HIGH)
    delayMicroseconds(1);//1マイクロ秒待機
    if(digitalRead(DOUT)==HIGH){//Dout端子からの出力がHighの場合
      result+=(1<<i);//12ビットのi桁目に1を代入(i桁分だけ左にシフト)
    }
    digitalWrite(CK,LOW);//1ビット分のクロックパルス出力(LOW)
    delayMicroseconds(1);//1マイクロ秒待機
  }
  delayMicroseconds(3);//3マイクロ秒待機
  return result;//結果を出力
}