フードドライヤーの太陽光追尾その5 完成の巻

フードドライヤーの太陽光追尾その4 - cruzioのブログ の続きです。

試作だった回路を基板に起こし、部品等の実装を進めていきます。

バッテリーは単3x 2で 5V への昇圧器内蔵充電器(ガラケー時代のもの、以前1個50円で投げ売りされていたときに大量購入した)を使うことにしました。

足が入らなくなっていた Arduino Nano は、一部のピンのみピンヘッダーに挿すことにしました。これは完成後の写真で、基板側は 7ピン分の長さのソケット2列になっています。

ケースは 6mm 厚の板材のため、スイッチ類をどうやって付けるか悩みました。結局、裏側にアクリル阪を付けて、そこに取り付けました。電源スイッチは木の厚みがあって、シーソーやトグルは付けられないためロータリースイッチにしています。

下部ケース裏面。地面に建てたポールに取り付けるため、底面はこのように細工しています。

こちらがポール側です。ドライヤー箱+追尾機は軽いのでこの程度でOK。

塩ビパイプを地面に埋めておき、ドライヤー使用時はアルミパイプを刺します。たまたま塩ビの内径がアルミパイプにぴったりだったのでこのようにしました。

追尾機の組み立て完了。このくらい余裕があると楽です。

CDS センサー部がとても邪魔で、ぶつけて壊しそうです。黒い仕切りを板ではなく厚紙にすれば良いかも。

さっそく試運転。奥さんがローズマリーを乾かしたいというので、私はイチゴを入れることにしました。

パイプに取り付けて自立します。このように設置したのはネコ除けのためですが、小さい虫も入らなそうでマル。

動作の様子をアップロードしました。動きはとてもゆっくりです。ひとつ難点は電源投入時にサーボモーターを初期位置に設定するのですが、そのときに現在位置から初期位置にサーボモーターがデフォルト速度で動いてしまいます。これがとても早い!ので中身の入った箱をセットした状態で電源を入れると大変なことになります。これは、サーボモーターは現在位置を読み出すことができない仕様のためです。電源遮断時の最後の位置をEPROMに保持しておく方法もありますが。。今回は対策として、電源を切る前に手動で初期位置付近に位置合わせしておく、ということで回避しました。VRとプッシュSWはそのためのものです。

youtu.be

夕方、取り込みました。乾き具合は如何に?

薄く切ったイチゴはペラペラに乾きました。厚みがあるのはまだ水気があります。あまり薄いのは食べた気がしないので、ちょっと厚めに切って、2日間乾かすのが良さそうでした。ローズマリーはかなり茶色っぽくなってしまいました。熱のせいかな?

夕方、おつまみになりました。

今回は回転台の実装方法を考えるのと木工の工作が思ったより大変でしたが、動作も期待通りで楽しく作れました。何と言っても実用的です。晴れの予報の日は何かしら干したくなります(笑)。すべて段ボールでも作れると思うので中高生の夏休みの工作にちょうどいいかも知れません。

回路図とプログラムです。

#include <Servo.h>
#define BUTTON_PIN 2 //位置設定ボタン
#define SERVO_PIN 3 //サーボ制御 ex.9
#define DEBUG_LOG 0 //Serial output control
#include <Bounce2.h>
Bounce2::Button button = Bounce2::Button();

Servo myservo;  // create servo object to control a servo
const int vrPin = A2; //位置設定VR
const int sensPin1 = A3;   // CDS1 input ex.A0
const int sensPin2 = A4;   // CDS2 input ex.A1
const int maxArr = 5; //移動平均配列サイズ
int sensVal1[maxArr], sensVal2[maxArr];
int currentDeg=1500; //サーボ初期値 中央 South
int arrPos=0; //移動平均
uint8_t u8state=0;
unsigned long u32wait;
const long intervalS=100;
const long intervalL=5000;//3000;
long intervalMillis=intervalS; //interval to execute
int delta; //delta of 2 CDS
const int deltaThreshold=20; //in-focuse if wihtin deltaThreshold
int totalSensVal1, totalSensVal2;
//int ledPin = LED_BUILTIN;

void initcode() {//init servo position;
  myservo.attach(SERVO_PIN, 500, 2500); //limit within 180 deg
  button.attach( BUTTON_PIN, INPUT_PULLUP );
  button.interval(5);
  button.setPressedState(LOW);
  for (int i=0;i<maxArr;i++) {
    sensVal1[i]=sensVal2[i]=0;
  }
  myservo.write(currentDeg);
  delay(1000);
  //pinMode(ledPin, OUTPUT);
  //digitalWrite(ledPin, LOW);
}

void moveToVR() {
  int vrValue=analogRead(vrPin);
  int deg = map(vrValue, 0, 1023, 500, 2500);
  int i;
  if (currentDeg>deg) {
    for (i=currentDeg;i>deg;i--) {
      myservo.write(i);
      delay(5);
    }
  } else
  if (currentDeg<deg) {
    for (int i=currentDeg;i<deg;i++) {
      myservo.write(i);
      delay(5);
    }
  }
  currentDeg=i;
}

void setup() {
  //Initialize serial and wait for port to open:
  if (DEBUG_LOG) {
     Serial.begin(9600);
    while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
    }
  }
  initcode();
  u32wait = millis() + intervalMillis;
  //digitalWrite(ledPin, HIGH);
}

void loop() {
  button.update();

  switch( u8state ) {
  case 0:
    if ( button.pressed() ) {
      moveToVR();
    }
    if ( millis() > u32wait ) u8state++; // wait state
  break;
  case 1:
    if (arrPos>=maxArr) arrPos=0; //arrPos>9
    sensVal1[arrPos] = analogRead(sensPin1);
    sensVal2[arrPos] = analogRead(sensPin2);
    arrPos++;
  //注意!! switch 文の case 部に変数宣言と初期化があると、エラーは出ないが正常に動作しない。
  //int totalSensVal1=0, totalSensVal2=0;
    totalSensVal1=0, totalSensVal2=0;
    for (int i=0;i<maxArr;i++) { //i<10
      totalSensVal1=totalSensVal1+sensVal1[i];
      totalSensVal2=totalSensVal2+sensVal2[i];
    }
    delta=totalSensVal2-totalSensVal1;
    u8state++;
  break;
  case 2:
    boolean update=false;
    if *1&&(currentDeg<2500))  {
      currentDeg++;
      intervalMillis=intervalS;
      update=true;
    } else
    if *2 {
      currentDeg--;
      intervalMillis=intervalS;
      update=true;
    } else
    if *3 {
      currentDeg++;
      intervalMillis=intervalL;
      update=true;
    } else
    if *4 {
      currentDeg--;
      intervalMillis=intervalL;
      update=true;
    }
    if (update) {
      myservo.write(currentDeg);
        if (DEBUG_LOG) {
          Serial.print("SensVal1=");Serial.print(totalSensVal1);
          Serial.print("\t");
          Serial.print("SensVal2=");Serial.print(totalSensVal2);
          Serial.print("\t");
          Serial.print("delta=");Serial.print(delta);
          Serial.print("\t");
          Serial.print("interval=");Serial.print(intervalMillis);
          Serial.print("\t");
          Serial.print("deg=");Serial.print(currentDeg);
          Serial.println("\t");
        }
    }
   
    u32wait = millis() + intervalMillis;
    u8state = 0;
  break;
  } //end switch()
}



 

 



*1:delta < -(deltaThreshold+100

*2:delta > deltaThreshold+100)&&(currentDeg>0

*3:delta < -deltaThreshold)&&(currentDeg<2500

*4:delta > deltaThreshold)&&(currentDeg>0