CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Solar tracking problem with codes
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

Solar tracking problem with codes
PostPosted: Tue Mar 27, 2007 6:26 pm     Reply with quote

Hi
I am using LDR,S FOR TRACKING THE SUN, The motor i am using is a bipolar stepper motor, I am using pic to read the values of three ldr.and since i have caliberated my ldr,s The first two i am using for rotating my motor. If the difference between the voltages read from these ldr's is greater than 0.5v. I am giving the signal to rotate the motor by one step(1.8). I have written down the codes but I am not getting the required results. Can some one please check my codes and help me out with any problem with it.
The first two ldrs are on the either sides of a thin sheet as the sun moves one of the ldr comes in shade there by increasing the resistance. The third ldr is used for detecting the night condition. It is always in light . Below are my codes

#include <16f876.h>
#use delay(Clock=4000000)
#fuses XT, NOWDT, NOPROTECT, NOPUT, NOBROWNOUT

float mean_adc(byte channel) // Reads the adc port 30 times and gives the mean value
{

int i,mean_total = 30;
float mean = 0,mean1 = 0;

set_adc_channel(channel);
delay_us(100);
for (i=1; i<=mean_total; i++)
{
mean =mean + read_adc();
delay_us(100);
mean1=(mean/mean_total);
}
return(mean1);
}

void stepper_motor_sequence(count)
{
byte const step_motor_state[4]={0b00001001,0b00001010,0b00000110,0b00000101};// stepper motor bipolar states
int j;
int current_step;
int current_step1;
current_step=count+1;

for (j=count;j<current_step;j++)
{
current_step1 = j%4;
output_b(step_motor_state[current_step1]);
}
}

void stepper_motor_sequence_reverse(count)
{
int k;
byte const step_motor_state[4]={0b00000101,0b00000110,0b00001010,0b00001001};
for (k=count;k<=1;k--)
{
int current_step1_reverse;
current_step1_reverse=k%4;
output_b(step_motor_state[current_step1_reverse]);
delay_ms(250);
}
}

main()
{
int ldr_low=51; // voltage equivalent to 0.5v
float diff;
int count=0;
float ldr_1,ldr_2,ldr;
const byte ldr_1_chanel=0,ldr_2_chanel=2,ldr_chan=1;
set_tris_b(0xf0);

while(true)
{
ldr_1=mean_adc(ldr_1_chanel);
ldr_2=mean_adc(ldr_2_chanel);
ldr=mean_adc(ldr);
diff = ldr_1-ldr_2;// difference of ldr1 and ldr2

if(diff<ldr_low>=153 && diff<=26)// this is to check the night conditon and rotate the motor in reverse direction at the end of day
{
stepper_motor_sequence_reverse(count);
}
}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 27, 2007 6:51 pm     Reply with quote

Quote:
if(diff<ldr_low>=153 && diff<=26)

See this post which explains how to disable HTML when you make
a post. You need to do that. (Look the line from your posted code).
http://www.ccsinfo.com/forum/viewtopic.php?t=30264&start=1
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

PostPosted: Tue Mar 27, 2007 7:11 pm     Reply with quote

Hi
As u said I have updated my profile and posting the codes again
#include <16f876.h>
#use delay(Clock=4000000)
#fuses XT, NOWDT, NOPROTECT, NOPUT, NOBROWNOUT

float mean_adc(byte channel) // Reads the adc port 30 times and gives the mean value
{

int i,mean_total = 30;
float mean = 0,mean1 = 0;

set_adc_channel(channel);
delay_ms(100);
for (i=1; i<=mean_total; i++)
{
mean =mean + read_adc();
delay_us(100);
mean1=(mean/mean_total);
}
return(mean1);
}

void stepper_motor_sequence(count)
{
byte const step_motor_state[4]={0b00001001,0b00001010,0b00000110,0b00000101};// stepper motor bipolar states
int j;
int current_step;
int current_step1;
current_step=count+1;

for (j=count;j<current_step;j++)
{
current_step1 = j%4;
output_b(step_motor_state[current_step1]);
}
}

void stepper_motor_sequence_reverse(count)
{
int k;
byte const step_motor_state[4]={0b00000101,0b00000110,0b00001010,0b00001001};
for (k=count;k<=1;k--)
{
int current_step1_reverse;
current_step1_reverse=k%4;
output_b(step_motor_state[current_step1_reverse]);
delay_ms(250);
}
}

main()
{
int ldr_low=51; // voltage equivalent to 0.5v
float diff;
int count=0;
float ldr_1,ldr_2,ldr;
const byte ldr_1_chanel=0,ldr_2_chanel=2,ldr_chan=1;
set_tris_b(0xf0);

while(true)
{
ldr_1=mean_adc(ldr_1_chanel);
ldr_2=mean_adc(ldr_2_chanel);
ldr=mean_adc(ldr);
diff = ldr_1-ldr_2;// difference of ldr1 and ldr2

if(diff<=ldr_low)
{
count=count+1;
stepper_motor_sequence(count);
delay_ms(250);
output_b(0xf0);
}
else if (ldr>=153 && diff<=26)// this is to check the night conditon and rotate the motor in reverse direction at the end of day
{
stepper_motor_sequence_reverse(count);
}
}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 27, 2007 8:50 pm     Reply with quote

Quote:
I have written down the codes but I am not getting the required results

1. What results are you getting ?

2. What results do you want to get ?


Also, your #fuses statement doesn't have NOLVP in it. Are you using
an LVP programmer ? Less than 1% of all people use one. If not, then
add the NOLVP fuse as shown below. This alone, could be the reason
why your program doesn't work properly.
Quote:
#include <16f876.h>
#use delay(Clock=4000000)
#fuses XT, NOWDT, NOPROTECT, NOPUT, NOBROWNOUT, NOLVP
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 1:51 am     Reply with quote

When posting code please use the 'code' buttons to preserve the layout of your code.

Code:
void stepper_motor_sequence(count)
Specify the type for the function parameters. It might be true that the CCS compiler defaults to int8 (as in K&R C) but try to use the ANSII C syntax where possible as it is allows for type checking.
Code:
void stepper_motor_sequence(int8 count)


Code:
ldr=mean_adc(ldr);
Passing a calculated float value as the channel number??? I'm sure this is not what you intended to do.
With the above mentioned ANSII C syntax for function parameters a good compiler would have warned you here.

Code:
void stepper_motor_sequence(count)
{
  byte const step_motor_state[4]={0b00001001,0b00001010,0b00000110,0b00000101};// stepper motor bipolar states
  int j;
  int current_step;
  int current_step1;
  current_step=count+1;

  for (j=count;j<current_step;j++)
  {
    current_step1 = j%4;
    output_b(step_motor_state[current_step1]);
  }
}
Sometimes introducing a new variable can make code easier to read but in your case you are introducing unneeded new variables with confusing names making your code harder to read.

I rewrote your code to show what it is doing:
Code:
void stepper_motor_sequence(int8 count)
{
  byte const step_motor_state[4]={0b00001001,0b00001010,0b00000110,0b00000101};// stepper motor bipolar states
  int current_step;

  current_step = count%4;
  output_b(step_motor_state[current_step]);
}
I guess this is not what you had in mind... Up to you to fix it.

Code:
 for (k=count;k<=1;k--)
change to
Code:
 for (k=count;k>=1;k--)


After calling stepper_motor_sequence_reverse() you don't reset count to zero.
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 5:58 am     Reply with quote

Hi
Thanks I have made alterations as you have said, but I could not get what you meant by
"After calling stepper_motor_sequence_reverse() you don't reset count to zero"

As when the night conditon is detected I have to rotate the motor back to its original positon ie facing towards the east.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 8:36 am     Reply with quote

quium wrote:
Thanks I have made alterations as you have said, but I could not get what you meant by
"After calling stepper_motor_sequence_reverse() you don't reset count to zero"


Change
Code:
{
  stepper_motor_sequence_reverse(count);
}
to
Code:
{
  stepper_motor_sequence_reverse(count);
  count = 0;
}
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 9:33 am     Reply with quote

Thanks, I have changed it.
I will check the codes tomorrow hopefully they should be working.

Thanks
Ttelmah
Guest







PostPosted: Wed Mar 28, 2007 10:01 am     Reply with quote

Let me make some other comments. You only need one table of stepper 'states'. Is your motor powerful enough to make the movement with no reduction?. Typically, reduction ratios of thouands to one are used on steppers trying to do this sort of job, unless a very high torque motor is used...
Take this:
mean1=(mean/mean_total);
outside the sample loop. At present, you recalculate the average 30 times, and only return with the last value. A lot of wasted work.
Your 'end of day' test is screwy. '<', and '>=', have the same precedence, so evaluate left to right. So diff is compared with ldr_low, and this returns a logical value, which is then compared with 153. You need to use brackets to force the evaluation to be in the required order. Then move 'to' the overnight position (probably a count like '0'), and stay in this position, till the light rises to a suitable level to start moving again.

This is part cut out of some code used in another astronomical application, to move a stepper - you will have to put your own data definitions, and select the port etc., to suit your application. It is cut down to only use an 8bit 'position' value - originally the position was an int32, to handle many hundreds of thousands of steps/rev:
[code]
int8 position; //curent motor position

//Motor drive patterns
const int drivebits[]= { 0x03,0x06,0x0C,0x09 };
//Change to suit your stepper hardware

//Output the required drive pattern to the motor
#define drive(position) output_b(drivebits[position & 3])
//Change to suit required port

void move_to(int8 required) {
if (position<required) {
while (position<required) {
position++'
drive(position);
delay_ms(1);
}
else {
while (position>required) {
position--;
drive(position);
delay_ms(1);
}
}
}
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 10:08 am     Reply with quote

Quote:
//Output the required drive pattern to the motor
#define drive(position) output_b(drivebits[position & 3])
//Change to suit required port

Can you please explain this a bit in detail
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 10:15 am     Reply with quote

I am having a small solar panel with 1.5kg weight and I am using 1200mNm stepper motor, The panel is mounted on a disc which is rotating on motor shaft.
Ttelmah
Guest







PostPosted: Wed Mar 28, 2007 12:12 pm     Reply with quote

#define drive(position) output_b(drivebits[position & 3])

Imagine you have 'positions' called 0,1,2,3,4.... etc..
You have stepper code 'patterns' of:
0b00000101,0b00000110,0b00001010,0b00001001

You need to output the first pattern for the first position, the second pattern for the second, third for third, fourth for fourth, then go back to the first for the fifth position. To 'step' the motor from position 5, to position 3, the patterns would be the first, then the fourth, then then third. The operation '&', performs a bitwise '&' on the 'position' value.
For values of:
Code:

value     value & 3
0               0
1               1
2               2
3               3
4               0
5               1
6               2
...

This then gives the right number to select the motor drive required for a given position.
It is impossible to know whether the motor will do what is needed on it's own, without knowing the drag of the bearings, how far the mass is from the axis etc. etc.. You should be testing a simple movement on it's own first, without trying to track the light. Only once you have the movement working, start to build the second 'tracking' component.
You should also think about how the system will handle wind for example.
As it stands, to 'hold' the panel, requires current to be permanently supplied to the motor. A worm drive, will remove this need, and instead the sequence could be:
Apply last power pattern,
Wait a moment.
Step to next position.
Turn off power.

Which will waste a lot less power.

Best Wishes
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 12:34 pm     Reply with quote

Yeah I have got it, But one more thing, If i want to rotate it by one step and then wait for my ldr values to show some difference, In that case between these two intervals the time might be half an hour or more In that case as per my codes do I have to set the output to zero every time i rotate by one step

Many Thanks
quium



Joined: 19 Jan 2007
Posts: 27

View user's profile Send private message

PostPosted: Wed Mar 28, 2007 1:15 pm     Reply with quote

The dimensions of my solar panel are 416mmx235mm. I am keeping the tilt angle fixed to 33.23 degree. And I am having a base unit that is attached or mounted on to the motor The circular disc which is rotating on the shaft of the motor is having wheels that rotate on the base unit. The radius of the circular disc is 168mm which gives me an angle of 66.23. The centre of mass of the panel comes exactly on the axis of motor rotation. This design is based on the uk geographical location
Ttelmah
Guest







PostPosted: Wed Mar 28, 2007 2:38 pm     Reply with quote

The only way to find out what will happen, without a _lot_ of maths (how much drag do your wheels involve, will this change with temperature etc. etc.), is to actually try moving the device. A simple test program that moves it, is a good place to start.
You leave the 'count' at the last position, and turn off the actual drive. Then before moving, turn the drive back on, at the same 'count'. However on a direct drive, _beware_ of doing this. The stepper will display residual magnetism, and is pretty sure to move when you do this. It is really only practical on a worm driven system. Remember also that wind is almost certain to give an assymetric load on the system (wind speeds higher up the panel will tend to be higher).
Since th system should only ever need to turn forwards (except for the 'night' triggered reverse, the algorithm need only look for a forward movement, and when it is required, turn on the drive, move the mount forwards, then switch off till a forward movement is requred. I'd really suggest having a detector, at due east, and moving the system back to this overnight, which will correct for any errors in the stepping.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group