« Arduinoで作る太陽光の方向を向く2軸サーボ | Main | Arduino で Sonic Radar を作る »

07/14/2017

Arduinoで(太陽)光の方向を追いかける2軸サーボ(New Algorithm)

Img_20170708_153936 Img_20170708_153958 Img_20170706_101405 Img_20170706_101420













Arduino Nanoで(太陽)光の方向を追いかける装置をブレッドボード上に作ってうまく稼働したので、小さなユニバーサル基板(60mm x 40mm)の上に部品を置いて製作してみた。
ケースも100均ショップで、適当な大きさの円筒形貯金箱を入手したので、その中に基板を入れ、ケース上面にLDRセンサー(前回作ったもの)を装着したサーボを固定した。

装置が新しくなったので、それに併せて光を追いかけるスケッチも自分のオリジナルな発想でロジックを考え、光の方向を探索する時間も短縮できるようにした。その結果、光を追いかける速度は格段に速くなり、室内などでテストした際、室内灯を消灯すると、初期の位置に戻り、点灯すると直ちに灯りの位置を向く。またセンサー部に手を翳すと、手の影を嫌ってより明るい方向を向くように動くので、その仕草がなかなか可愛い。

と書いてから、本当に明るい方向を向いているのだろうか・・・と初期の動きが気になったので、センサーを経度方向約170度分を周して、そこで明るい場所を探索の初期値にするようにスケッチを追加した。
緯度方向は、初期値を決め打ちして、探査をしていないので、そのために初期値の緯度・経度値から位置を確定するまでに少し時間がかかる場合がある。

スケッチは当初のものより少し長くなってしまった。しかし、まあまあ納得がいくようになったのでスケッチを公開することにする。
緯度方向の初期値探査が欲しい場合には、私のスケッチに倣って探せば良いし、経度方向の初期探査が不要なら、(34~55行までと関連のある部分を)外せばいい。それでも大きな問題無く稼働すると思う。

《Sketch》

// The Sunlight Tracker New Algorithm  by Savvy 2017.07.14
//
#include <Servo.h>
Servo servohori;
int svLimitMax = 175;
int svLimitMin =   5;
int servoh     = svLimitMin;   // Initial value of search angle

Servo servoverti; 
int svLimitHigh = 120;
int svLimitLow  =   5;
int servov      =  45;  // Initial value of search angle

// Assign the wireing color to LDRs
int ldrtopl = 2;  // top left LDR Green wiring
int ldrtopr = 1;  // top right LDR Yellow wiring
int ldrbotl = 3;  // bottom left LDR Blue wiring
int ldrbotr = 0;  // bottom right LDR Red wiring

int topl;
int topr;
int botl;
int botr;

int hstep;
int vstep;
int alpha;
int  beta;

 void setup () {
  servohori.attach(10);    // horizontal motor servo  (Blue wiring)
  servoverti.attach(9);    // vertical motor servo  (Green wiring)

// search initial horizontal angle between servo limit min-max angle
  int i    = 0;
  int imin = 0;
  int lx[]  = { 9999, 9999, 9999, 9999, 9999, 9999, 9999};
  int hstp  = (svLimitMax - svLimitMin) / 6;
  int lxmin = 9999;
  alpha = svLimitMin;
  beta  = servov;

  for ( i=0; i<7; i++ )
  {
   lx[i] =  wlight( alpha, beta);
   alpha = alpha + hstp;
   if( lx[i] < lxmin )
   { lxmin = lx[i];
    imin = i;
     }
  }
  delay(200);
  // this is the initial location of horizontal servo
  servohori.write( svLimitMin + hstp*imin );
}
void loop(){
  // Read the servo set angle at the moment
  servoh = servohori.read();
  servov = servoverti.read();
  
  // Read the light number of each LDR
  topl = analogRead(ldrtopl);
  topr = analogRead(ldrtopr);
  botl = analogRead(ldrbotl);
  botr = analogRead(ldrbotr);
  
  // calculate the average value
  int avgtop   = (topl + topr) / 2;   // average of top LDRs
  int avgbot   = (botl + botr) / 2;   // average of bottom LDRs
  int avgleft  = (topl + botl) / 2;   // average of left LDRs
  int avgright = (topr + botr) / 2;   // average of right LDRs

  if( (avgtop < 1012) & (avgbot < 1012) )  // the servo acts while in the light
  {
    hstep = xstep(avgright,avgleft);  // determination of the horizontal serch step angle
    servoh = servoh + hstep;
    
    if((svLimitMin < servoh) & (servoh < svLimitMax))  // acts between max - min limits
    { 
       servohori.write(servoh);
    }
    
    vstep = xstep(avgtop,avgbot);   // determination of the vertical serch step angle 
    servov = servov + vstep;
    
    if((svLimitLow < servov) & (servov < svLimitHigh))
    {
        servoverti.write(servov);
    }       
  }
  delay(200);
}
int xstep(int avg1, int avg2)
  // classify the step value from the two light value
{
  int jcase = avg1 - avg2;
  int result;
    
    if(jcase < -30 ) {
      result = 10; 
    }
    if((-30 <= jcase) & (jcase < -10)){
      result = 3;
    }
    if((-10 <= jcase) & (jcase <  -2)){
      result = 1;
    }
    if(( -2 <= jcase) & (jcase <  2)){
      result = 0;
    }
    if(( 2 <= jcase) & (jcase < 10)){
      result = -1;
    }
    if(( 10 <= jcase) & (jcase < 30)){
      result = -3;
    }
    if( 30 <= jcase ){
      result = -10;
    }
    return result;
}
int wlight(int alpha, int beta)
{
   servohori.write(alpha);
   servoverti.write(beta);
   int loc  = (analogRead(ldrtopl) + analogRead(ldrtopr) + analogRead(ldrbotl) + analogRead(ldrbotr)) / 4; 
   delay(200);
   return loc;
}

« Arduinoで作る太陽光の方向を向く2軸サーボ | Main | Arduino で Sonic Radar を作る »

PC and PC troubles」カテゴリの記事

Comments

Post a comment

Comments are moderated, and will not appear on this weblog until the author has approved them.

(Not displayed with comment.)

TrackBack

TrackBack URL for this entry:
http://app.cocolog-nifty.com/t/trackback/540128/65527267

Listed below are links to weblogs that reference Arduinoで(太陽)光の方向を追いかける2軸サーボ(New Algorithm):

« Arduinoで作る太陽光の方向を向く2軸サーボ | Main | Arduino で Sonic Radar を作る »

November 2017
Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    

Recent Trackbacks

無料ブログはココログ