Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] solar tracking system using PIC 16f877A

Status
Not open for further replies.

hasithgayan

Newbie level 5
Joined
Nov 16, 2015
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
78
i looking for make solar tracking system using pic 16f877a.i wrote code as follow but when it simulate
using proteus.it only change rotation direction not stop at given range.please help to slove.


Code C - [expand]
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Servo definition and variables
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 20
#define CW_ROTATION MAX_VALUE - 10
#define STOP_ROTATION MAX_VALUE
 
unsigned char pulse_max=0;
unsigned char pulse_top=0;
unsigned char top_value = 0;
static void interrupt (void)
{
  if(T0IF) {                // TIMER0 Interrupt Flag
    pulse_max++;            // Pulse Max Increment
    pulse_top++;            // Pulse Top Increment
 
    /* MAX_VALUE=200 turn off the pulse */
    if (pulse_max >= MAX_VALUE) {
      pulse_max=0;
      pulse_top=0;
      PORTB.B1=0;                // Turn off RC2
    }
 
    /* top_value = MAX_VALUE - n, n=10: 10 x 0.1ms = 1.0ms, n=20: 20 x 0.1ms = 2.0ms */
    /* 2ms -> CCW Rotation, 1ms -> CW Rotation */
    if (pulse_top == top_value) {
      PORTB.B1=1;                // Turn On RC2
    }
    TMR0 = 156;             // Initial Value for 0.1ms Interrupt
    T0IF_bit = 0;           // Clear TIMER0 interrupt flag
  }
}
void main() {
  /* Init Servo Pulse */
  pulse_max=0;
  pulse_top=0;
  top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop
  
  OPTION_REG = 0b00000000; // 1:2 Prescaller
  TMR0=156;            // Interupt every 0.1 ms
  T0IE_bit = 1;            // Enable interrupt on TMR0 overflow
  GIE_bit = 1;
               // Global interrupt enable
TRISB=0x00;
PORTB=0x00;
TRISC=0x00;
PORTC=0x00;
ADC_Init();
PWM1_Init(1000);
 
while (1)
{
 unsigned int ldr_left;
 unsigned int ldr_right;
 signed int ldr_diff;
 ldr_left=ADC_Read(0);
 ldr_right=ADC_Read(2);
 
 ldr_left=ldr_left*0.488;
 ldr_right= ldr_right*0.488;
 
 ldr_diff=ldr_left - ldr_right;
 
 
if((ldr_diff >= -50) && (ldr_diff <= 50))
             {top_value = MAX_VALUE;     // Stop the Servo Motor
             }
 else if(ldr_diff > 50)  //ccw
  { top_value = CCW_ROTATION;
 }
 else   //ccw
   {
        top_value = CW_ROTATION;   // Clockwise Rotation
      }
}
}

 
Last edited by a moderator:

Hi,

you should give more information.
Schematic. Functional description. Error description.
What have you tested so far? What is working like expected? Where exactely does it not work like expected?00

Klaus
 
Also, you are altering the 'pulse_max' and 'pulse_top' variables within the ISR and so they should be declared as volatile.
In the ISR your code updates RB1 to 0 but the comments mentions RC2. Are you updating the correct pin?
When you reset the timer value, is it absolutely critical that you trigger the ISR every mSec? If so, you may need to account for the number of timer pulses that have occurred after the timer roles over form 0xff until your code resets the TMR2 register. That time requires the interrupt to be acknowledged by the hardware (basically the next instruction), the ISR to be called, the ISR pre-able code to be executed and whatever code you have written before the assignment occurs. One way of doing this is to subtract the (then) current TMR2 value from your calculated value (or possible 1 or 2 less to account for the subtraction itself) and write that back.
On the other hand if you can tolerate the slight variance, then carry on the way you are.
On the face of it, I can't see what effect your timer ISR is having on the rest of the program.
Also be careful with the rounding you will get when you multiply by 0.488 when the compiler will convert the ADC value from int to float, perform the floating point multiply (which can be slow on those devices) and then convert back to integer. You might be better off saving the ADC value into a long int variable and then multiplying by 500 and dividing by 1024 (or using the shift operator to avoid the division) - .488 = 499.7/1024.
Susan
 
hi mr.KlausST
thanks for reply.
when two ldrs change servo rotate ccw and cw but its not stop when the illumination between 50 and -50 as in the code,
there is no error except eeprom errors in proteus.i think there is some error in code.please fixed it sir
 

thankx mr Aussie,
im new for mikroc and i took those codes from blog and change them as my knowledge,
my project is drive servo ccw and cw ldr_diff > 50 and ldr<-50 its work ok,but it does not stop between 50 and -50
can you change the code for that process,
 

Can you put a breakpoint on line 65 in your code in the first post? Does the breakpoint ever get called?
As you are changing the values read in by the ADC, are you getting the correct value from your calculations for ldr_diff?
What is the difference between 'pulse_max' and 'pulse_top'? AS far as I can see, both will always have the same value as they are both initialised (lines 34 and 35) and reset (lines 18 and 19) at the same time, ind incremented (lines 13 and 14) together.
You don't ever seem to refer to PWM1 except to initialise it. There seems to be a number of lines of code that are not really useful so I'd recommend that you strip things down to the minimum until you are sure that each part is working correctly and build up from there.
For example, I'd remove everything except for the timer setup and ISR. Then you can check that the timer is running correctly and that the ISR is being called at the correct times.
Then you can add in the ADC and make sure that you are reading in the correct values as you change the appropriate analog input and that your calculation is actually generating the value you expect.
Susan
 
thank susan;
i got codes from this blog
http://www.ermicro.com/blog/?p=771
then change for pic 16f877a.

Code:
// Servo definition and variables
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 20
#define CW_ROTATION MAX_VALUE - 10
#define STOP_ROTATION MAX_VALUE
volatile pulse_max=0;
volatile pulse_top=0;
unsigned char top_value = 0;
static void interrupt (void)
{
if(T0IF) {                    // TIMER0 Interrupt Flag
    pulse_max++;            // Pulse Max Increment
    pulse_top++;            // Pulse Top Increment

    /* MAX_VALUE=200 turn off the pulse */
    if (pulse_max >= MAX_VALUE) {
      pulse_max=0;
      pulse_top=0;
      PORTB.B1=0;                // Turn off RC2
    }

    /* top_value = MAX_VALUE - n, n=10: 10 x 0.1ms = 1.0ms, n=20: 20 x 0.1ms = 2.0ms */
    /* 2ms -> CCW Rotation, 1ms -> CW Rotation */
    if (pulse_top == top_value) {
      PORTB.B1=1;                // Turn On RC2
    }
    TMR0 = 156;             // Initial Value for 0.1ms Interrupt
    T0IF_bit = 0;                // Clear TIMER0 interrupt flag
  }
}
void main() {
  /* Init Servo Pulse */
  pulse_max=0;
  pulse_top=0;
  top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop

  OPTION_REG = 0b00000000; // 1:2 Prescaller
  TMR0=156;            // Interupt every 0.1 ms
  T0IE_bit = 1;                       // Enable interrupt on TMR0 overflow
  GIE_bit = 1;
                         // Global interrupt enable
TRISB=0x00;
PORTB=0x00;
TRISC=0x00;
PORTC=0x00;
ADC_Init();

while (1)
{
 unsigned int ldr_left;
 unsigned int ldr_right;
int ldr_diff;
 ldr_left=ADC_Read(0);
 ldr_right=ADC_Read(2);

 ldr_left=ldr_left*499.7;
 ldr_right= ldr_right*499.7;

 ldr_diff=ldr_left - ldr_right;


if(ldr_diff < 50)  //ccw
  { PORTB.B1=0;
 }
 else   //ccw
   {
        top_value = CW_ROTATION;   // Clockwise Rotation
      }
}
}
I try my best for this to work but can not done,if you have time please fixed the codes.i change codes as you tell earliyer.im using mikroc pro for this,
 

You are still only telling us that you code does not work but not what is wrong.
Have you tried any of the suggestions I made earlier (stripping the code back, setting breakpoints etc.).
I'm happy to help you understand the code but I'm not going to do your work/assignment for you. You need to study the code and understand what it is doing yourself.
Susan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top