Help with a sample code of sun tracking

Discussion in 'Programmer's Corner' started by astronaut71, Jun 11, 2015.

  1. astronaut71

    Thread Starter New Member

    Jun 11, 2015
    6
    0
    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?

    /*
    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);
    }
     
  2. WBahn

    Moderator

    Mar 31, 2012
    17,736
    4,789
    Do you REALLY expect strangers to go through over 200 lines of unformatted code that has almost no commenting and no schematic or other description of the system and find your bug?
     
  3. NorthGuy

    Active Member

    Jun 28, 2014
    603
    121
    You don't normally write code like this. You do something simple, say make sure that you can move the motor in one direction. Then, you add the opposite direction. In such way, adding little pieces one by one, you create working code. If something goes wrong, you know that it is your last little tiny addition to blame and you can easily locate the problem. When you have the whole code and don't know where to look for errors, it's tough - not an easy task for the beginner.
     
  4. MikeML

    AAC Fanatic!

    Oct 2, 2009
    5,450
    1,066
    I am curious what you are using as a sun sensor? Post a schematic of the hardware. Forget the code until the hardware works.
     
Loading...