Connect with us

Help with a sample code of sun tracking with Arduino Uno

Discussion in 'Microcontrollers, Programming and IoT' started by Bojan Andonovski, Jun 11, 2015.

Scroll to continue with content
  1. Bojan Andonovski

    Bojan Andonovski

    4
    0
    Jun 11, 2015
    Hi

    I have Pololu High-Power 18V 15A motor driver, Arduino Uno microcontroler, 12V DC worm gear Motor and light sensor module. Im building a prototype for tracking a solar panel. So , from example in the morning the panels are in their initial (home, horizontal position) and start tracking the sun and motor start moving. I include the code but when testing the motor is moving always when light is bigger than upper thresh. Which is not correct as I wont that motor stop moving and panel stops when sun reach its maximum and at the end of the day panel comes back (motor runs in other direction).

    Include the sample code. So what Im missing here?
    Code:
    
    /*
    WIRING INSTRUCTION: includes 1 motor  (hinge motor) and 1 sensor.
    
    
    
    
    pin 8: hinge motor direction pin
    pin 11: hinge motor speed pin (PWM)
    sensor 1 pin a: pin A0
    
    */
    #include <TimerOne.h>
    #include <avr/sleep.h>
    #include <avr/power.h>
    #include <avr/wdt.h>
    #include <SPI.h>
    #include <Wire.h>
    
    
    
    #define BRAKE1 12
    #define BRAKE2 7
    
    #define sensor1 A0  //Purple cable
    #define motor_speed 750  //default motor speed @ 0.3rpm
    #define array_size 30  //10 samples
    
    
    
    
    volatile long data1 = 0;
    volatile int check_counter = 0;
    volatile int execute_counter = 0;
    volatile int motor_time_counter = 0;
    volatile byte check_flag = 0;
    volatile byte time_out_flag = 0;
    volatile byte motor_time_flag = 0;
    
    char upperthres = 40;  //CW tolerance, upper threshold
    char lowerthres = 17;  //CCW tolerance, lower threshold
    int sensor1_data_hinge[array_size];
    int planned_motor1 = 0;  //Planned motion: 0-no rotation; 1-CW; 2-CCW
    int lightLevel;
    
    
    /* SENSOR PROCESSING */
    int readSensor1()
    {
      //  interrupts();
      int avg = 0;
      /*SHIFT DATA*/
      for (int i = 0; i < array_size; i++)
      {
        avg = avg + sensor1_data_hinge;
        sensor1_data_hinge = sensor1_data_hinge[i+1];
      }
    
      /*ACCEPT NEW READING*/
      sensor1_data_hinge[array_size-1] = analogRead(sensor1);
      avg = avg/array_size;
    
      // noInterrupts();
      return avg;
    }
    
    ///
    
    /*MOTOR CONTROL*/
    
    void hingeCW ()    //turn RIGHT
    {
      digitalWrite(8, HIGH);  //set direction for hinge motor
      analogWrite(11, motor_speed);   //set speed for hinge motor
    }
    
    void hingeCCW ()    //turn LEFT
    {
      digitalWrite(8, LOW);  //set direction for hinge motor
      analogWrite(11, motor_speed);  //set speed for hinge motor
    }
    
    void stopHingeMotor ()
    {
      analogWrite(11, 0);  //set 0 speed for hinge motor
    }
    
    //-------------MOTOR 1 Operations-------------
    void check_motor1()
    {
      //read sensor
      data1 = readSensor1();
      //plan which movement to take
      if (data1 >= upperthres)
      {
        planned_motor1 = 1;
      }
    
      else if (data1 <= lowerthres)
      {
        planned_motor1 = 2;
      }
      else planned_motor1 = 0;
    }
    
    //wait for a bit
    //delay(2000);  //MAYBE SPLIT THE PROCEDURE INTO 2 PHASES: CHECKING AND EXECUTING
    
    
    void execute_motor1()
    {
      //read sensor again
      data1 = readSensor1();
      //check if planned movement is still correct after waiting
      if (data1 >= upperthres && planned_motor1 == 1)
      {
        //enable motor timer
        motor_time_flag = 1;
        hingeCW();
        //continually check sensor and count down to stop motor
        while (data1 >= upperthres && time_out_flag == 0)
        {
          data1 = readSensor1();
        }
        motor_time_counter = 0;
        motor_time_flag = 0;
        time_out_flag = 0;
        stopHingeMotor();
      }
      else if (data1 <= lowerthres && planned_motor1 == 2)
      {
        //enable motor timer
        motor_time_flag = 1;
        hingeCCW();
        //continually check sensor and count down to stop motor
        while (data1 <= lowerthres && time_out_flag == 0)
        {
          data1 = readSensor1();
        }
    
        //reset timer  parameters incase the loop exits because hinge reaches correct position
        motor_time_counter = 0;
        motor_time_flag = 0;
        time_out_flag = 0;
        stopHingeMotor();
      }
    
      //if planned movement does not match, reset everything
      else planned_motor1 = 0;
    }
    
    
    /*END OF MOTOR CONTROL*/
    
    ISR(WDT_vect)
    {
      check_counter++;
      if (check_counter == 2)
      {
        check_counter = 0;
        check_flag = 1;
      }
    }
    
    void timerIsr()
    {
      if (motor_time_flag == 1)
      {
        motor_time_counter++;
        //Motor rotation time out parameter
        if (motor_time_counter == 45)  //15 ~ 1 second
        {
          motor_time_counter = 0;
          motor_time_flag = 0;
          time_out_flag = 1;
        }
      }
    }
    
    void enterSleep(void)
    {
     set_sleep_mode(SLEEP_MODE_PWR_DOWN);   /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
      sleep_enable();
    
      /* Now enter sleep mode. */
      sleep_mode();
    
      /* The program will continue from here after the WDT timeout*/
      sleep_disable(); /* First thing to do is disable sleep. */
    
      /* Re-enable the peripherals. */
      power_all_enable();
    }
    
    
    void setup()
    {
      pinMode(8, OUTPUT);         //hinge direction pin
      pinMode(11, OUTPUT);         //hinge speed pin
      Serial.begin (9600);
    
      Timer1.initialize(100000);              // 100000 = 100ms
      Timer1.attachInterrupt( timerIsr );
    
      MCUSR &= ~(1<<WDRF);
    
      /* In order to change WDE or the prescaler, we need to
       * set WDCE (This will allow updates for 4 clock cycles).
       */
      WDTCSR |= (1<<WDCE) | (1<<WDE);
    
      /* set new watchdog timeout prescaler value */
      WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */
    
      /* Enable the WD interrupt (note no reset). */
      WDTCSR |= _BV(WDIE);
    
      //initiate sensor data
      for (int i = 0; i < 20; i++)
      {
        data1 = readSensor1();
      }
    }
    
    void loop()
    {
      if (check_flag == 1 && (analogRead(sensor1) >= 5))
      {
        //=====Track hinge======
        check_motor1();
        delay(200);
        execute_motor1();
      }
      lightLevel = analogRead(A0);
      Serial.println(lightLevel, DEC);
      //Serial.println("sleep active");
      Serial.println("sleep active");
      delay(50);
      enterSleep();
      Serial.println("wake up");
      //execute_motor1();
      delay(50);
    }
     
    Last edited by a moderator: Jun 11, 2015
  2. Harald Kapp

    Harald Kapp Moderator Moderator

    9,548
    1,972
    Nov 17, 2011
    Welcome to electronicspoint. I took the liberty to clean up your post a tiny bit by putting the sample code in a code box.
     
  3. Bojan Andonovski

    Bojan Andonovski

    4
    0
    Jun 11, 2015
    thanks
     
  4. Harald Kapp

    Harald Kapp Moderator Moderator

    9,548
    1,972
    Nov 17, 2011
    First, this bit of code looks suspicious:
    Code:
      for (int i = 0; i < array_size; i++)
      {
        avg = avg + sensor1_data_hinge;
        sensor1_data_hinge = sensor1_data_hinge[i+1];
      }
    
    • sensor1_data_hinge is an array, therefore "sensor1_data_hinge" is an adddress but you surely do not want to add an address to the average value.
    • Also since "sensor1_data_hinge" is an adddress, the assignment "sensor1_data_hinge = sensor1_data_hinge[i+1];" will try to change the address, not the value as expected.
    • for i==(array_size-1), the last value for i within the for loop, "sensor1_data_hinge[i+1]" is an invalid reference since the index [i+1] lies outside the array boundaries [0...array-size-1].
    I suggest the following changes:
    Code:
      for (int i = 0; i < array_size; i++)
      {
        avg = avg + sensor1_data_hinge[i];
        if (i < (array_size-1))
            sensor1_data_hinge[i] = sensor1_data_hinge[i+1];
      }
    

    There may be more similar issues, this is just the first I came across.

    As a note on the side: imho it is good practice to use capital letters for defines to discern them clearly from variables. Therefore I suggest you write
    Code:
    #define SENSOR1 A0  //Purple cable
    #define MOTOR_SPEED 750  //default motor speed @ 0.3rpm
    #define ARRAY_SIZE 30  //10 samples
    etc. for bettter clarity. This will have no influence on the compiled code, however.
     
  5. Bojan Andonovski

    Bojan Andonovski

    4
    0
    Jun 11, 2015
    thanks. But that code was already in my original version. I dont understand why now after your changers appears different
     
  6. BobK

    BobK

    7,671
    1,681
    Jan 5, 2010
    The square brackets were interpreted as bb-code commands.

    Bob
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-