|
|
View previous topic :: View next topic |
Author |
Message |
mpingu
Joined: 28 Jul 2013 Posts: 6 Location: Malaysia
|
Solar tracking mechanism PIC16F877A |
Posted: Sun Jul 28, 2013 5:21 am |
|
|
Hello guys. I'm doing a project about solar tracking mechanism and used PIC16F877A as my microcontroller. But I have troubles on the programming part.
Code: |
#include <16F877A.h> //Include all the necessary variables available for PIC16F877A.
#device ADC=8 //Set the ADC as 8bit.
#fuses XT,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000) //As we are using 4MHz clock oscillator.
//#use fixed_io(b_outputs = PIN_B0, PIN_B1) //Set Port B as the output.
char vthreshold = 1; //Declare threshold value for voltage read from both LDR.
char readValue_0();
char readValue_1();
void main()
{
char call_A0, call_A1;
setup_adc_ports(ALL_ANALOG); //Set the ports to read analog input.
setup_adc(ADC_CLOCK_INTERNAL); //Declared as we are using external clock.
while(1) //To make an eternal loop.
{
call_A0 = readValue_0();
call_A1 = readValue_1();
char sbtrc = call_A0-call_A1; //Subtraction value.
if(call_A0 >= call_A1)
{
if(sbtrc <= vthreshold)
{
output_bit(PIN_B0,1); //The motor will
output_bit(PIN_B1,0); //move clockwise.
}
else
output_bit(PIN_B0,1); //The motor will
output_bit(PIN_B1,0); //move clockwise.
}
else if(call_A0 <= call_A1)
{
output_bit(PIN_B0,0); //The motor will
output_bit(PIN_B1,1); //move counterclockwise
}
else
{
output_bit(PIN_B0,0);
output_bit(PIN_B1,0);
}
}
}
readValue_0()
{
unsigned int8 adcValue; //Declare the variables.
set_adc_channel(0); //Get the readings from the port connected to LDR1.
delay_us(50); //Delay to give the circuit some buffer time to operate.
adcValue = read_adc();//Read the voltage value from the LDR1.
char adcV1 = (adcValue*5)/255; //Convert the digital value to analog.
return adcV1;
}
readValue_1()
{
unsigned int8 adcValue; //Declare the variables.
set_adc_channel(1); //Get the readings from the port connected to LDR1.
delay_us(50); //Delay to give the circuit some buffer time to operate.
adcValue = read_adc(); //Read the voltage value from the LDR1.
char adcV2 = (adcValue*5)/255; //Convert the digital value to analog.
return adcV2;
}
|
I was hoping that the voltage value that the PinA0 and A1 read will act as the manipulative variable so that the output of Pin B0 and B1 will give high or low output. But unfortunately when I try it on my board, the output it gave is just the same, which is the Pin B0 will always be high no matter how much I vary the voltage value from Pin A0 and A1. Btw, I also not sure if how I read the input and output value is correct. So I'm hoping you guys can help me out on this. Thanks in advance![/code] |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sun Jul 28, 2013 6:00 am |
|
|
You really don't need this line and it's mate...
char adcV1 = (adcValue*5)/255; //Convert the digital value to analog
...
Play 'computer' and see what happens when the adcValue is greater than say 52 bits.
Stick with the raw ADC data.You're only comparing which is bigger,so no 'fancy math' is reqired AND consider what happens when call_A0=call_A1 !
You should 'printout' the numbers to a PC or LCD if possible to give you feedback that the program is working as expected (or not).
Also be sure that the 'mechanical/electrical' section ( the LDR units) are reasonably 'matched' to give a proper response.
hth
jay |
|
|
mpingu
Joined: 28 Jul 2013 Posts: 6 Location: Malaysia
|
|
Posted: Sun Jul 28, 2013 6:48 am |
|
|
temtronic wrote: | You really don't need this line and it's mate...
char adcV1 = (adcValue*5)/255; //Convert the digital value to analog
...
Play 'computer' and see what happens when the adcValue is greater than say 52 bits.
Stick with the raw ADC data.You're only comparing which is bigger,so no 'fancy math' is reqired AND consider what happens when call_A0=call_A1 !
You should 'printout' the numbers to a PC or LCD if possible to give you feedback that the program is working as expected (or not).
Also be sure that the 'mechanical/electrical' section ( the LDR units) are reasonably 'matched' to give a proper response.
hth
jay |
thanks for the help jay
How do I print it actually? Coz I won't be using LCD for the project & I don't quite sure how to printout the output value to the PC. And also then, my threshold value should be in binary number? |
|
|
mpingu
Joined: 28 Jul 2013 Posts: 6 Location: Malaysia
|
|
Posted: Sun Jul 28, 2013 6:52 am |
|
|
Also, do I require this line? What is the effect of having this line actually?
Code: | //#use fixed_io(b_outputs = PIN_B0, PIN_B1) //Set Port B as the output. |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sun Jul 28, 2013 7:04 am |
|
|
Do not use 'fixed_io...' unless you're a really good programmer !
Let the compiler handle what direction the I/O pins need to be for your programs.That's one of the great features of CCS C compiler..it'll do all the 'hidden' details for you.
If you improperly code an I/O pi for input when it's supposed to be an output, you will not get the result you're expecting.
For 'printing to a PC', just look at the 'help' files( press F11 when project is open) and lookup 'printf'. Also, check some of the example programs CCS supplies. TONS of great information on how to do it!
Yes, it'll take a bit of time to scan and read, but you'll be a better programmer that just 'cutandpaste'.
hth
jay |
|
|
mpingu
Joined: 28 Jul 2013 Posts: 6 Location: Malaysia
|
|
Posted: Sun Jul 28, 2013 7:55 am |
|
|
temtronic wrote: | Do not use 'fixed_io...' unless you're a really good programmer !
Let the compiler handle what direction the I/O pins need to be for your programs.That's one of the great features of CCS C compiler..it'll do all the 'hidden' details for you.
If you improperly code an I/O pi for input when it's supposed to be an output, you will not get the result you're expecting.
For 'printing to a PC', just look at the 'help' files( press F11 when project is open) and lookup 'printf'. Also, check some of the example programs CCS supplies. TONS of great information on how to do it!
Yes, it'll take a bit of time to scan and read, but you'll be a better programmer that just 'cutandpaste'.
hth
jay |
Thank you very much for your help jay, it worked! |
|
|
mpingu
Joined: 28 Jul 2013 Posts: 6 Location: Malaysia
|
|
Posted: Sun Jul 28, 2013 11:41 am |
|
|
ok, now i've encountered another problem. I'm expecting it to stop when input the value from Pin A0 and A1 is equal but it doesn't stop. What should I do? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Jul 29, 2013 7:04 am |
|
|
your code...
Code: |
if(call_A0 >= call_A1) ////// !!!!!
{
if(sbtrc <= vthreshold)
{
output_bit(PIN_B0,1); //The motor will
output_bit(PIN_B1,0); //move clockwise.
}
else
output_bit(PIN_B0,1); //The motor will
output_bit(PIN_B1,0); //move clockwise.
}
else if(call_A0 <= call_A1) ////// !!!!!
{
output_bit(PIN_B0,0); //The motor will
output_bit(PIN_B1,1); //move counterclockwise |
'play computer'...
what happens when call_A0 = call_A1 ???
what will the PIC do when this condition is true ???
answer...
the PIC will command the motor to go cw, then ccw, cw, then ccw, as long as the condition is met.
possible cure...
one is to have 3 conditions, a0<a1, a0>a1, a0=a1 setting motor control bits as required.
also..
you should add some 'hysterisis' to your conditions, something like ...
if a0<a1-2 then move cw
if a0>a1+2 then move ccw
this allows for a smoother response to the inputs, reduces motor 'jerk',etc.
what value (2 in this example) you use is best determined in 'real life' testing, a bit depends upon the 'damping' of the photocell output and desired response time.
hth
jay |
|
|
mpingu
Joined: 28 Jul 2013 Posts: 6 Location: Malaysia
|
|
Posted: Tue Jul 30, 2013 5:24 am |
|
|
thanks again jay! that really help.
Also, for my code, I done some backup programming using PIC16F84A (which does not have the ADC function) just in case, and I wanted it to work exactly like how the PIC16F877A do, but it didn't work.
Here's the code.
Code: | #include <16F84A.h>
#device ADC=8
#fuses XT,NOWDT,NOPROTECT,NOPUT
#use delay(clock=4000000)
#include <stdlib.h>
char vthreshold = 1; //Declare threshold value for voltage read from both LDR.
char readValue_0();
char readValue_1();
void main()
{
set_tris_a(0x0f); //set as input
set_tris_b(0x00); //set as output
char call_A0, call_A1;
call_A0 = readValue_0();
call_A1 = readValue_1();
while(1) //To make an eternal loop.
{
char sbtrc = call_A0-call_A1; //Subtraction value.
if(abs(sbtrc) < vthreshold) //When the absolute value of the subtraction is higher than threshold value.
{
output_low(PIN_B0); //The motor will
output_low(PIN_B1); //not move.
}
else if(abs(sbtrc) > vthreshold) //When the absolute value of the subtraction is lower than threshold value.
{
if(call_A0 > call_A1)
{
output_high(PIN_B0); //The motor will
output_low(PIN_B1); //move clockwise.
}
else
{
output_low(PIN_B0); //The motor will
output_high(PIN_B1); //move counterclockwise
}
}
else
{
output_low(PIN_B0); //The motor will
output_low(PIN_B1); //not move.
}
}
}
readValue_0()
{
unsigned int8 Value0; //Declare the variables.
delay_us(50); //Delay to give the circuit some buffer time to operate.
Value0 = input(PIN_A0); //Read the voltage value from the LDR1.
return(Value0);
}
readValue_1()
{
unsigned int8 Value1; //Declare the variables.
delay_us(50); //Delay to give the circuit some buffer time to operate.
Value1 = input(PIN_A1); //Read the voltage value from the LDR1.
return(Value1);
} |
Just ignorre the if else statement, I haven't updated it yet coz I can do it later. I would very much appreciate if you guys can help me to fix this thing. Thanks in advance guys |
|
|
|
|
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
|