Jump to content
Sign in to follow this  
mark0

NOOB: Code review and feedback - chicken coop door and solar tracker

Recommended Posts

Hi everyone,

I've recently starting playing around with and learning with the launchpad, having fun but finding fault finding a bit frustrating!

 

I've looked at the various examples and used what I learnt there to build my project. Apart from some tuning issues (like setting the LDR trigger value with the actual circuit) is is working OK. I am having problems with the pushbutton failing to make the door change positions. This was working with a test setup i had with the launchpad, and worked intermittently with a previous code version.

 

I understand the blinking LED parts are a bit messy, I plan to remove/reduce these later when it works

 

I've not built the hardware for the solar tracker, so I used the boolean 'solar' to ignore that code until I do. Not a high priority. I have used the servo sweep example to prove (to myself) that I could drive the servos.

 

Using the launchpad rev 1.5, energia ...16, win 8.1 64bit

 

The hardware setup is:

  • MSP430G2553 in a purpose built circuit, one on board LED for flashing indication of anything happening.
  • LDR with dropping resistor
  • 10 channel relay board. (i only need 2 channels and will probably down size later on). Effectively a high current H bridge, each channel makes the motor turn one direction.
  • a car windscreen wiper motor, guillotine style door (up/down action)
  • 2x limit switches with 47k, 120k, 100nF hardware debounce
  • 2x momentary buttons, one for reset, one to trigger the door to move (if up then go down and vice versa). same hardware debounce setup.

 

Problems

  • the push button (pb) doesnt trigger the door to move. Manually activating the relay moves the door correctly. I havent checked if the output does actually go low, as I can't tell when to test at this stage. The door has gone up and down succesfully with previous code versions,
  • the code is getting quite large and I feel like the breakout into separate functions will keep it tidy. but I don't know (and couldn't find any info on whether these are sequential or parallel to the main loop, and whether I'd be creating racing or other issues
  • I'd like to have the program store the current LDR value to the LDR_trigger variable on a long press of the pushbutton pb. In a small code test, this caused the interrupt to fail completely. I've deleted the code now, but basically checked if the button was still pressed after some delay. if not, then it was a short press (different flag to a long press), otherwise a long press.

 

I'd love the feedback, but please be gentle :P

 

Mark

/*
Code to control a chicken coop door, using a light dependent resistor, some relays, and limit switches. The microprocessor has not RTC so that is out of the question. 
 Included a dual axis solar tracker, awaiting two servo motors to arrive to complete. Need to build mechanism. 
 
 Testing area:
 - dual axis solar tracker code included. Looks like the servo library needs the MSP430G2553.
 - night mode for solar tracker, inhibits movement at night.
 - learning function for solar tracker, remembers the morning position. Still looks for LDR balance after this.
 
 Recently tested OK:
 - most of the code reworked to suit dedicated coop door board. Limit switches now have hardware debouncing.
 - having a few problems getting the push button to work correctly, changed the PB flags around and seems to be working OK.
 - upper limit switch issue. Conflicting IO address with blinky LED. pin was setup as output after the input setup. 
 
 
 Areas for improvement: 
 - include WiFi connection and ability to send emails. Might be possible looking at the included examples with Energia.
 - include code to remember the morning position and return there.
 */

#include <Servo.h> 
Servo Xservo;  // Xservo controls the azimuth (angle from North) 
Servo Yservo; // Yservo controls the inclination angle (angle from horizontal)

// GPIO Pin Designation
// analog read is available on pins P1_0 to P1_7, P2_0
const int LDR = P1_0; // the original LDR pin from the coop door
const int LDR_TLpin= P1_0; // four LDRs, top left, top right, bottom left, bottom right
// P1_1 and P1_2 required for UART
const int LDR_TRpin= P1_3;
const int LDR_BLpin= P1_4;
const int LDR_BRpin= P1_5;
const int Xservopin=P1_6; //Xservo pin
const int Yservopin=P1_7; //Yservo pin
const int pb = P2_0; // button to change position of the door.
const int lim_up =P2_1;
const int lim_down = P2_2;
const int blinky = P2_3; //simple LED for a status indication
int mtr_up = P2_4;
int mtr_down = P2_5;

// User Variables (inputs)
int LDR_trigger = 100; //raw ADC value to lower/raise door 0 to 1023 (high number is low light)
const long mtr_timeout = 10*1000; //time in milliseconds to allow door to run
const long loopsleep = 15*60; //time in seconds to sleep if no LDR trigger found
const boolean lim_act_level = LOW; // door limits are pulled up, so will read low when active.
const boolean serial = true; //serial comms for debugging - not available on the integrated board.
const boolean mtr_on = LOW; // set the motor on level, for use with relay boards with LOW = ON
const boolean blinky_on =LOW; //allow for different ON logic levels
boolean learn = true; // learn the morning position for the solar tracker.
boolean solar =false; //enable solar tracker


int Xservostep=2; //set the initial size of the step to take. This is adjusted automagically later.
int Yservostep=2;
int maxservostep=10; // limit the maximum step. Also limits current draw
int Xservoposmorn=50; // set the initial morning position
int Yservoposmorn=50;
int Xservopos = Xservoposmorn; //set the initial tracker position
int Yservopos = Yservoposmorn;
int LDRtol = 10; // set the difference required between min and max LDR to enable movement. ie >10, move = true, else move = false
int Xservodir = 1; //assumed left is positive, change to -1 to swap direction
int Yservodir = 1; // assumed top is positive

const int dot = 400;
const int dash = 3* dot;
const int wordspace = 7*dot;


// system variables, not set by user
int LDR_TLval= 0;
int LDR_TRval= 0;
int LDR_BLval= 0;
int LDR_BRval= 0;
int maxLDR = 0;
int maxLDR2 = 0;
int minLDR = 0;
int minLDR2 = 0;
boolean move = false;
boolean day = true;
boolean day2 = true;

long LDRread;
long LDRread2;
volatile boolean door_up =false;
volatile boolean door_up_last =false;
volatile boolean door_down =false;  
volatile boolean door_down_last =false;
volatile boolean door_on = false;
volatile boolean door_up_on = false;
volatile boolean door_down_on = false;
long time_on;
volatile boolean PB=false; // a flag for the interrupt pushbutton
int a =0;
int b= 0;
int count =0;

void setup()
{
  //initiliase serial comms
  Serial.begin(9600);
  delay(250);
  Serial.println("Begin...");

  Xservo.attach(Xservopin);  // attaches the servo pin to the servo object 
  Yservo.attach(Yservopin); // attaches the servo pin to the servo object 

  // digital input should be pulled away from the active logic level. So if active low, pull up OR active high, pull down.

  if(!solar)
    pinMode(LDR,INPUT);
  else{
    pinMode(LDR_TLpin,INPUT);
    pinMode(LDR_TRpin,INPUT);  
    pinMode(LDR_BLpin,INPUT);
    pinMode(LDR_BRpin,INPUT);
  }
  pinMode(pb, INPUT); // digital inputs are all setup as falling edge. THe input is pulled up and debounced by hardware
  attachInterrupt(pb, pusher, FALLING);

  pinMode(lim_up,INPUT); //external pull up, falling
  attachInterrupt(lim_up, stopper, FALLING); 

  pinMode(lim_down,INPUT); //external pull up
  attachInterrupt(lim_down, stopper, FALLING);

  pinMode(mtr_up,OUTPUT);
  digitalWrite(mtr_up, !mtr_on);

  pinMode(mtr_down,OUTPUT);
  digitalWrite(mtr_down, !mtr_on);

  pinMode(blinky,OUTPUT);

  digitalWrite(blinky,!blinky_on);
  delay(50);
  digitalWrite(blinky,blinky_on);
  delay(50);
  digitalWrite(blinky,!blinky_on);
  delay(50);
  digitalWrite(blinky,blinky_on);
  delay(50);
  digitalWrite(blinky,!blinky_on);


  door_up = false;
  door_down = false;

  if(digitalRead(lim_up) == lim_act_level) { // door limits are pulled up, so will read low when active.
    door_up = true;
    Serial.print("Up: ");
    Serial.print(door_up);
    Serial.print('\n');
  }
  if(digitalRead(lim_down) == lim_act_level) {
    door_down = true;
    Serial.print("Down: ");
    Serial.print(door_down);
    Serial.print('\n');
  }

  if(!door_up && !door_down){
    Serial.println("Door position not found. Lowering");
    digitalWrite(mtr_down,mtr_on);     //door position not found, lower door
    door_on=true ;
    door_down_on=true;
    door_up_on=!true;
  }

  Serial.println("Finished Setup");
  delay(1000);

  readLDRs();
}

void loop()
{
  readLDRs();  // read light dependent resistors and door limit switches
  readLimits();


  if (PB && door_up){ 
    PB = false;
    digitalWrite(mtr_down,mtr_on);
    door_on=true ;
    door_down_on=true;
    door_up_on=!true;
    time_on=millis();
    Serial.println("Door lowering pushbutton");
  }
  else if (PB && door_down){
    PB = false;
    digitalWrite(mtr_up,mtr_on);
    door_down_on = !true;
    door_up_on = true;
    time_on=millis();
    door_on=true;

    Serial.println("Door raising pushbutton");
  }
  else if (PB)
    PB=false;
  // ignores any presses during the door movement and resets flag

  Serial.print("loop...");

  //only allow servo movement after a tolerance/hysteresis value, and sun is still up.
  if (((maxLDR - minLDR) > LDRtol) && solar)
    move = true; //this flag is probably redundant, when solar tracker called as a function like this. 
  else if (solar)
    //either the panel is close enough to sun, or it is night time.
    move = false;
  if ((maxLDR > LDR_trigger) && solar){
    //either the panel is close enough to sun, or it is night time.
    day2 = day;
    day = true;
  }
  else if (solar){
    day2 = day;
    day = false;
  }

  if (move && solar){ 
    solartracker();
  }

  //LDRread = analogRead(LDR);

  Serial.print("LDR: ");
  Serial.print(LDRread);
  Serial.print("LDR 2: ");
  Serial.print(LDRread2);
  Serial.print("\n");
  if (door_up)
    Serial.println("Door Up");
  else if (door_down)
    Serial.println("Door Down");


  if ((LDRread < LDR_trigger) && (LDRread2 < LDR_trigger) && door_up && !PB){
    digitalWrite(mtr_down,mtr_on);
    door_on=true ;
    door_down_on=true;
    door_up_on=!true;
    time_on=millis();
    Serial.println("Door lowering LDR");
  }
  else if ((LDRread > LDR_trigger) && (LDRread2 > LDR_trigger) && door_down  && !PB){
    digitalWrite(mtr_up,mtr_on);
    door_on=true ;
    door_down_on=!true;
    door_up_on=true;
    time_on=millis();
    Serial.println("Door raising LDR");
  }  

  while (door_up_on || door_down_on){
    if (millis() > (time_on + mtr_timeout)){
      // door has timed out. Stop door and flash SOS.
      digitalWrite(mtr_up, !mtr_on); //stop the door immediately
      digitalWrite(mtr_down, !mtr_on);

      while (true) { // flash the onboard LED in SOS pattern.
        //S
        for (int count = 0; count < 3; count++){
          digitalWrite(blinky,blinky_on);
          sleep(dot);
          digitalWrite(blinky,!blinky_on);
          sleep(dot);
        }
        //O
        for (int count = 0; count < 3; count++){
          digitalWrite(blinky,blinky_on);
          sleep(dash);
          digitalWrite(blinky,!blinky_on);
          sleep(dot);
        }
        //S
        for (int count = 0; count < 3; count++){
          digitalWrite(blinky,blinky_on);
          sleep(dot);
          digitalWrite(blinky,!blinky_on);
          sleep(dot);
        }
        sleepSeconds(15);
      }
    }
  }
  sleepSeconds(loopsleep);
}
// this interrupt needs to stay small. So we use a flag 'PB' to complete the action in loop().
// this might need hardware debouncing.
// this might be subject of interference from motor switching.
void pusher()
{
  wakeup();
  PB=true;
}

void stopper(){
  digitalWrite(mtr_up, !mtr_on); //stop the door immediately
  digitalWrite(mtr_down, !mtr_on);
  
  if ((door_down_on && (digitalRead(lim_up) == lim_act_level)) || (door_up_on && (digitalRead(lim_down) == lim_act_level))){ //check for direction error
    a=mtr_up;
    mtr_up=mtr_down;
    mtr_down=a;
  }
  door_up_on = false; //reset flags and end
  door_down_on = false;
}


void readLimits()
{
//read limits
  if (digitalRead(lim_up) == lim_act_level){
    door_up = true;
    door_down = !true; 
  }
  else if (digitalRead(lim_down) == lim_act_level){
    door_up = !true;
    door_down = true;
  }
  else{
    door_up = !true;
    door_down = !true;
  }
}

void readLDRs()
{
  if (!solar){
    LDRread2 = LDRread;
    LDRread = analogRead(LDR);
  }
  else{
    LDR_TLval= analogRead(LDR_TLpin);
    LDR_TRval= analogRead(LDR_TRpin);
    LDR_BLval= analogRead(LDR_BLpin);
    LDR_BRval= analogRead(LDR_BRpin);
    maxLDR2 = maxLDR;
    minLDR2 = minLDR;
    maxLDR =max(max(LDR_TLval,LDR_TRval),max(LDR_BLval,LDR_BRval));
    minLDR =min(min(LDR_TLval,LDR_TRval),min(LDR_BLval,LDR_BRval));  
    LDRread2 = LDRread;
    LDRread = maxLDR;
  }
}

void solartracker()
{
  // Solar tracker section

  if (day && !day2 && !learn){
    // it is morning! day = true, day2 = false, learn = false (ie MC has already learnt the position we want, doesnt work on day 1 obviously)
    // go to morning position
    Xservo.write(Xservoposmorn);
    delay(100);

    Yservo.write(Yservoposmorn);
    delay(100);
    day2=day; // change day2 to prevent coming back here again.
  }

  while (move && day){
    readLDRs();
    if ((maxLDR-minLDR)< LDRtol){
      if (learn){
        learn = false; // if we are within the tolerance, quit the learn cycle and remember the position. Any power cycle/chip reset will reset the learn flag
        Xservoposmorn = Xservopos;
        Yservoposmorn = Yservopos;
      }
      move = false; // if we are within the tolerance, quit the move cycle
    }
    if (LDR_TLval == maxLDR){
      // move toward the top left
      // assume positive toward top, and toward left, can change using servodir variable
      // val = map(val, 0, 1023, 0, 179); 
      Xservostep = map((LDR_TLval - LDR_TRval), 0, 1023, 0, maxservostep);
      Xservopos = Xservopos + (Xservodir*Xservostep);
      Yservostep = map((LDR_TLval - LDR_BLval), 0, 1023, 0, maxservostep);
      Yservopos = Yservopos + (Yservodir*Yservostep);
    }
    else if (LDR_TRval == maxLDR){
      // move toward the top right
      // assume positive toward top, and toward left, can change using servodir variable
      Xservostep = map((LDR_TRval - LDR_TLval), 0, 1023, 0, maxservostep);
      Xservopos = Xservopos + (Xservodir*Xservostep);
      Yservostep = map((LDR_TRval - LDR_BRval), 0, 1023, 0, maxservostep);
      Yservopos = Yservopos - (Yservodir*Yservostep);
    }
    else if (LDR_BRval == maxLDR){
      // move toward the top right
      // assume positive toward top, and toward left, can change using servodir variable
      Xservostep = map((LDR_BRval - LDR_BLval), 0, 1023, 0, maxservostep);
      Xservopos = Xservopos - (Xservodir*Xservostep);
      Yservostep = map((LDR_BRval - LDR_TRval), 0, 1023, 0, maxservostep);
      Yservopos = Yservopos - (Yservodir*Yservostep);
    }
    else if (LDR_BLval == maxLDR){
      // assume positive toward top, and toward left, can change using servodir variable
      Xservostep = map((LDR_BLval - LDR_BRval), 0, 1023, 0, maxservostep);
      Xservopos = Xservopos + (Xservodir*Xservostep);
      Yservostep = map((LDR_BLval - LDR_TLval), 0, 1023, 0, maxservostep);
      Yservopos = Yservopos - (Yservodir*Yservostep);
    }

    Xservopos = min(max(Xservopos, 0), 179); //stay within the limit of motion
    Yservopos = min(max(Yservopos, 0), 179); //stay within the limit of motion

    Xservo.write(Xservopos);
    delay(100);
    Yservo.write(Yservopos);
    delay(100);
  } //end of while(move && day) loop
} //end of function solartracker

 

 

 

 

 

 

 

coop20150730_ST.ino

Interrupts.ino

Read.ino

SolarTracker.ino

Share this post


Link to post
Share on other sites

You do know that it's really hard to mash though a lump of code this size and seek for errors without feedback on any other thing in the system?

I'll try to look into your code, but don't expect miracles. For a better feedback, try to slim down your code, test that the problem still occurs, then post the slimmed down code and explain the exact sequence of events that lead to the incorrect behaviour.

Share this post


Link to post
Share on other sites

Hi @@mark0

 

I notice this is your first post - welcome! This will be a cool project when you are finished.

 

As @@roadrunner84 says, your code is difficult to debug by another party due to length/organization and not being able to observe the hardware while the code runs. Some suggestions:

 

* have you flowcharted it and is it following the flowchart?

* consider breaking it down further into functions associated with flowchart - simplify your setup() and loop() by calling functions

* debug the functions and add them one at a time to the main structure only after they are debugged

* reduce/simplify your setup(), loop() and functions down to the very minimum needed to reproduce the problem when requesting help

* work one problem at a time

 

You have LED indication and serial monitor output. Is that working as you expect? If so, what have you done to assure it isn't a hardware problem or hardware interface?

Share this post


Link to post
Share on other sites

EDIT: thinking about this again, the incorrect flags mentioned below would send the code into the timeout loop, and since they are never reset, the while(true) timeout loop just runs forever.  I will put this onto the MC this afternoon and hopefully that works.  :)

 

 

 

@@roadrunner84 Thanks, I'm not expecting you to get into the detail of the code. Please don't feel like you must!

 

I am more interested in the high level, stylistic review of the code. I have no microcontroller experience, so wasnt sure if i was doing something which is considered bad practice, or just won't work.

 

I found a few errors last night (door_up_on and door_down_on in the motor timeout loop). I had been playing around with the stopper function. It originally was polling the limit switches as I couldn't get interrupts to work, but now with hardware debouncing limit switch interrupts are working OK.

 

I did try adding an LED flash to the pusher interrupt to check that the button was calling the interrupt. This worked. So perhaps my problems is in the reset of the 'PB' flag. This might be in the wrong spot.

Looking at it now, on a push button event, the flag will reset at the start of loop() and then the loop 'should' enter the light dependent resistor check further into the loop. This is not what I want, should I do a simple 'PB = false;' as the final line before sleepseconds?

 

@@Fmilburn, the LED is working as expected. I tried to connect the UART pins on chip to the same pins on the launchpad (the MSP430G2553 is embedded on the purpose built circuit board, in a socket) but this didnt work. Are there any of the other J3 jumpers required for serial comms?

 

 

Thanks very much for helping out guys.

 

Mark

Share this post


Link to post
Share on other sites

I was curious how you planned on handling the solar tracking portion of your project when you got around to it. I've given this some thought myself. Since we're completely off-grid, and largely powered via solar + a decently sized battery bank. One problem for us however, is that we can get winds upwards of 80MPH once or twice a year . . . which could be a serious problem for anything non stationary. The wind in this area has actually destroyed more than it's fair share of wind turbines.

 

Anyway, I was thinking that the actual tracking algorithm would have to be "throttled" in some way in order to keep the tracker from constantly trying to move. Maybe some sort of timer interval. a minute, 5, 10 - whatever it took. Another aspect I've thought about a bit, was how to correctly track the sun. Many people seem to be using various different kinds of LEDs, but it dawned on me that all you really need is the panel(s) you have at work already. If you could somehow find a way to "track" it's power curve in software. Then perhaps have some "algorithm" to work around shading ( clouds etc ). A timer interval would help some here I'd think, but for shading that lasted longer than ones timer interval - The tracker might needlessly track out of the best "peak" currently available.

Share this post


Link to post
Share on other sites

 

@Fmilburn, the LED is working as expected. I tried to connect the UART pins on chip to the same pins on the launchpad (the MSP430G2553 is embedded on the purpose built circuit board, in a socket) but this didnt work. Are there any of the other J3 jumpers required for serial comms?

 

Actually I have never tried to do that until now but here is what I figured out....

 

Consider the little schematic below taken from the MSP-EXP430G2 Hardware Design Files:

post-45284-0-76918300-1438310592.jpg

 

This is J3 which I presume you are using to program your external MSP430G2553.  Now, think about how the jumpers are arranged when using a LaunchPad with Energia.  P1.1 is shorted to BTXD and P1.2 is shorted to BRXD.

 

So, the trick is to connect P1.1 on your board directly to BTXD on the LaunchPad and connect P1.2 directly to BRXD (note that BRXD is labelled TXD on the LaunchPad).  You will have P1.2 on the "wrong" side of J3 from all the other pins.

Share this post


Link to post
Share on other sites

RE: Solar Tracking

 

I would think that the easiest way to do this would be with an equatorial mount and a stepper motor.  E.G. set the stepper to rotate at one revolution per day but instead of going a complete revolution stop at the time of sunset on the longest day of the year and then return to the starting place.  You would need a real time clock and logic to handle loss of power.  While the declination of the sun changes throughout the year I wouldn't have thought that would matter too much...

Share this post


Link to post
Share on other sites

@@yyrkoon I have included a variable LDRtol, this prevents movement unless the (maxLDR - minLDR) >LDR tol. This will reduce the 'hunting' of the system, but a similar time based system would also work. The problem with using the panel output directly is that the tracker will struggle to find the correct position in shade conditions. Finding the correct position using the panel output will be similar to a perturb-observe MPPT algorithm (with all the problems of that). Consider the case if it is overcast, and the panel is in motion. If the cloud then clears, the panel output will rise, regardless of if the orientation was correctly adjusted (might have gone the wrong direction for example). The voltage-current curve of the solar panel complicates this further, if the load changes it could throw off the position adjustment.

 

The solar tracking code is included in the opening post. In short, read the four LDRs, find the maximum and move the panel toward that LDR. The overall level isn't important, just the relative levels of the four LDRs. This is better than the perturb-observe method and it's only the cost of four LDRs and resistor pairs. There is also some code in there to make the tracker 'learn' the first position in the morning, so it can head straight there before checking the LDRs.

 

my tracker will look something like this: http://www.instructables.com/id/DIY-Solar-Tracker/

 

But first to get the door working... :(

Tonight I found that I had a chip socket with a poor connection socket to chip, and a poor solder joint. I've fixed those and the door seems to be working. A few days of testing will be good.
 

@@Fmilburn I tried the jumper cables to J3 pins tonight, in many positions. I think the easiest way is to leave the normal jumpers in place at J3, but connect P1.1 to P1.1 and P1.2 to P1.2 on the two boards. Then I don't have to worry too much about where PCB tracks go to. I was not able to get this working though! serial monitor works fine in the launchpad but it's getting lost somewhere along the line.

 

 

Anyone know if the pushbutton interrupt with a long or short press can be done? My small scale test failed to trigger either case. Probably due to delay() not working in interrupts

void pusher()
{
  delay(1000);
  if (digitalRead(pb) == lim_act_level){
    // a long button press
    PBlong=true;
  }
  else {
    wakeup();
    PB=true;
  }
}

Share this post


Link to post
Share on other sites

delay is using interrupts itself, so, no, you cannot use it inside interrupts.Move this check to your loop and use millis() to check for the expiration of 1000ms instead of the blocking delay() function.

The Launchpad is sporting at 3.6V, not 3.3V nor 3.0V. So you probably have to run your system at 3.6V too to have a good working system. Alternatively use a separate UART cable instead of the Launchpad to communicate, those are most times more tolerant.

Share this post


Link to post
Share on other sites

 

@Fmilburn I tried the jumper cables to J3 pins tonight, in many positions. I think the easiest way is to leave the normal jumpers in place at J3, but connect P1.1 to P1.1 and P1.2 to P1.2 on the two boards. Then I don't have to worry too much about where PCB tracks go to. I was not able to get this working though! serial monitor works fine in the launchpad but it's getting lost somewhere along the line.

The arrangement that I described above is working for me.  I am powering the external board from, and grounding it to, the LaunchPad.  The leads are fairly short.  This addresses the potential problem that roadrunner84 described.  Hope this helps...

Share this post


Link to post
Share on other sites

 

@@yyrkoon I have included a variable LDRtol, this prevents movement unless the (maxLDR - minLDR) >LDR tol. This will reduce the 'hunting' of the system, but a similar time based system would also work. The problem with using the panel output directly is that the tracker will struggle to find the correct position in shade conditions. Finding the correct position using the panel output will be similar to a perturb-observe MPPT algorithm (with all the problems of that). Consider the case if it is overcast, and the panel is in motion. If the cloud then clears, the panel output will rise, regardless of if the orientation was correctly adjusted (might have gone the wrong direction for example). The voltage-current curve of the solar panel complicates this further, if the load changes it could throw off the position adjustment.

 

The solar tracking code is included in the opening post. In short, read the four LDRs, find the maximum and move the panel toward that LDR. The overall level isn't important, just the relative levels of the four LDRs. This is better than the perturb-observe method and it's only the cost of four LDRs and resistor pairs. There is also some code in there to make the tracker 'learn' the first position in the morning, so it can head straight there before checking the LDRs.

 

my tracker will look something like this: http://www.instructables.com/id/DIY-Solar-Tracker/

 

But first to get the door working... :(

Tonight I found that I had a chip socket with a poor connection socket to chip, and a poor solder joint. I've fixed those and the door seems to be working. A few days of testing will be good.

 

Well Mark, I have a lot to say on this matter ( solar tracking ), and yes I've thought about many of the different aspects. But perhaps not all. Your "concerns" with my idea I believe can be mitigated . . . But I'm not trying to convince anyone so much as perhaps just wanting to discuss my idea. Then perhaps I come out with an idea that's full of holes . . .holes that I had not considered.

 

Anyway, perhaps your post here is not the proper place to discuss all this. I do not wish to Hijack your post . .

Share this post


Link to post
Share on other sites

@@yyrkoon Not saying that using the panel as you sensor wont work, just that there are problems. I'd be interested to see it working if you do pursue it.

 

 

@@Fmilburn regarding the UART comms to MSP430G2553 not in the launchpad, I was finally successful getting comms out of the chip.

I leftthe J3 jumpers in place, connected the UART pins and Reset pin between the boards.

Also important is earth! I was just getting garbled rubbish without the earth. The MSP430 has it's own power supply, and the laptop obviously separate. So some potential difference between the two circuits.

I received no communications at all without reset pin connected. Test pin not required. And with the separate power supply, programming can't be done in place.

 

@@roadrunner84 Thanks for the tip on VCC. I have it set at 3.3V with a buck converter and seems to be working. With the check for a long button push inside loop(), if the button was pushed during a loop, then it could miss the button press. With the long loop that I have, I think the times could be affected?.

Perhaps a complimentary rising edge interrupt, setting another variable to millis. (i.e. time_released = millis() ;) Then the loop could compare two millis stamps regardless of whether the button was still depressed. My loop has a long sleep, sleepSeconds(15*60), so the function might not execute until the sleep expires. Maybe a if pushbutton is pressed, sleepSeconds is skipped?

 

Like this:

void setup()
{
//lines of setup code... 
 attachInterrupt(pb, pusher, FALLING);
  attachInterrupt(pb, push_rel, RISING);
//....
} 

void loop()
{
//lines of code before
  if ((time_rel >0) && (time_push > 0))
    SetLDR();
//lines after
}

void pusher()
{
  digitalWrite(blinky,blinky_on);
  wakeup();
  time_push=millis();
}

void push_rel()
{
  digitalWrite(blinky,!blinky_on);
  wakeup();
  time_rel=millis();
}

void SetLDR()
{
  if ((time_rel - time_push)>1000) 
  {
    LDR_trigger = analogRead(LDR);
    PB = false;  
  }
  else if ((time_rel - time_push)<=1000) 
    PB=true;
  else
    PB=false;

  time_rel = 0;
  time_push = 0;

}

Share this post


Link to post
Share on other sites

I finally got the code working. I used a different LDR between breadboarding and the final build, and it's has different light/resistance properties.

I havent yet got the short/long button push working.

 

Serial comms seems temperamental, I'm not sure why.

 

 

I've added a few photos of the physical setup, now that i've tidied some of the wiring up.

 

 

Thanks for all the help!

post-46698-0-76480800-1438670068_thumb.jpg

post-46698-0-39278100-1438670269_thumb.jpg

post-46698-0-38161400-1438670351_thumb.jpg

post-46698-0-61196200-1438670488_thumb.jpg

Share this post


Link to post
Share on other sites

Do the 3rd, 4th and 5th wire on the IC foot not touch each other? They seem very close together.

You cut holes in your casing to attach the relay board, does that not pose for water damage when it would rain?

If you really need two different button presses, why not use two buttons instead? If you're short on pins, you could either hack the reset pin to be used for this (when you put that pin in NMI mode it acts as a floating input with trigger) or set the input pin in analog read mode (will require polling) and feed different voltages into it depending on which button is/are pressed.

You could even share a pin between the LED and a button, though you'll have to switch between polling the button and powering the LED every 20-100ms or so to make the LED seem on instead of blinking.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×