View previous topic :: View next topic |
Author |
Message |
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Fri Apr 25, 2008 1:04 pm |
|
|
RLScott wrote: | soong2020 wrote: |
Hi Scott, I have tried removing the other char inputs except for one and it still behaves the same. Still I'm getting values displayed on PC but can't send in command from PC. |
OK, so you have a failure when sending a single character from the PC. The next step is to find out where that failure is taking place. Here is how you do it:
1. Add code to serial_isr so that an unused output is toggled every time you enter serial_isr. Watch that output on a scope to see if that output toggles when the PC sends the 'q' character.
2. Assuming the previous step went OK, next change serial_isr so that the unused output is toggled only if the received character is a 'q'. Put the code after case 'q': Then see if that output is toggled when the PC sends a 'q'.
3. Assuming the previous step went OK, then we know that fl_right1 must be getting set. So now see if fl_right1 is getting recognized by btn1_check(). Add code to bn1_check() so that it toggles an unused output every time it detects fl_right1 == TRUE. See if that output toggles when the PC sends a 'q'.
4. Assuming the previous step went OK, then I have to ask why you think the PIC is not receiving commands from the PC? Your answer will determine where to go from here.
Robert Scott
Real-Time Specialties |
So far i used back the original code, modified it into using an LED as the unused output cos i dont have a scope here. The code is reduced to only recognize 'q' character. Here is what i obtained:
1. The LED blinks each time the code enters serial_isr. Managed to send in data from PC into the PIC but had to press and hold onto the 'q' button continuously. The servo moves inconsistently as each 'q' is supposed make it turn a small step. But the signal that got through is inconsistent as the servo can turn once in every approx 0.5sec or it can move 2 steps in quick succession. Its just inconsistent.
2. The LED blinks every time the 'q' button is hit. The inconsistency is almost the same as the results in no.1
3. The LED blinks every time the 'q' is hit. But the inconsistency is reduced a lot. Success rate of the motor moving on every 'q' is approx 7/10 tries.
So I'm really at a lost here as to why is it behaving as such? |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Fri Apr 25, 2008 1:27 pm |
|
|
soong2020 wrote: |
3. The LED blinks every time the 'q' is hit. But the inconsistency is reduced a lot. Success rate of the motor moving on every 'q' is approx 7/10 tries.
|
OK, so now we see that your original report was misleading when you said:
Quote: |
...which means the PIC can't read the characters sent from the PC...
|
So now we understand that the PIC is able to read characters from the PC just fine. The real problem is that the servo is not moving correctly. But you are not showing us any code that moves a servo. I guess it has something to do with setting width01 and similar variables, but again, you are not showing us the code where the problem is.
Robert Scott
Real-Time Specialties |
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Fri Apr 25, 2008 10:47 pm |
|
|
RLScott wrote: |
So now we understand that the PIC is able to read characters from the PC just fine. The real problem is that the servo is not moving correctly. But you are now showing us any code that moves a servo. I guess it has something to do with setting width01 and similar variables, but again, you are not showing us the code where the problem is.
Robert Scott
Real-Time Specialties |
I was surprised that by adding the LED toggle command at each flag = TRUE, the motor is able to receive datas randomly. I've tried adding the toggle line to btn2_check and btn3_check flags and it somehow reduces the sensitivity. By doing so, the success rate of the char being put through is approx 3/10 only. No where near as responsive as working with only one flag.
Could it be the timing between the PIC sending out the data and the PIC receiving data are clashing?
By the way, here is my interrupt routine which supplies PWM to servos. Got the idea from PCM thru searching.
Code: |
#INT_TIMER2 //////*************************************************************
void TIMER2_isr(void)
{
if(--loop1 == 0 )
{
loop1 = LOOPCNT1; //LOOPCNT1 = 390, each int approx 0.05ms
pulse1 = width01; //0.05 * 390 = almost 20ms period....
pulse2 = width02; //each pulse represents signal to one servo
pulse3 = width03;
pulse4 = width04;
}
if(pulse1>0)
{
output_high(PWM_PIN1);
pulse1--;
}
if(pulse1<=0)
{
output_low(PWM_PIN1);
}
if(pulse2>0)
{
output_high(PWM_PIN2);
pulse2--;
}
if(pulse2<=0)
{
output_low(PWM_PIN2);
}
if(pulse3>0)
{
output_high(PWM_PIN3);
pulse3--;
}
if(pulse3<=0)
{
output_low(PWM_PIN3);
}
if(pulse4>0)
{
output_high(PWM_PIN4);
pulse4--;
}
if(pulse4<=0)
{
output_low(PWM_PIN4);
}
}
|
|
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Sat Apr 26, 2008 10:59 am |
|
|
Looking for help here. Anyone can offer some advice on how to solve this problem? |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Sat Apr 26, 2008 4:48 pm |
|
|
Does any other code set width01 besides the btn1_check()? Perhaps some code that you are not showing?
Robert Scott
Real-Time Specialties |
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Sat Apr 26, 2008 9:04 pm |
|
|
The only thing left that sets width01 is in the main() function which sets it by default into its home position. Here it is:
Code: |
void main()
{
init_main();
Initialize_INT();
widthL = 14; //0.7 ms duty cycle
widthC = 30; //1.5 ms duty cycle
widthR = 46; //2.3 ms duty cycle
widthL2 = 14; //shoulder config
widthR2 = 30;
widthL3 = 14; //elbow config
widthR3 = 30;
width01 = widthC;
width02 = widthC;
width03 = widthC;
width04 = widthC;
while(1)
{
output_low(PIN_C5); // the LED indicator pin
btn1_check();
btn2_check();
btn3_check();
btn4_check();
adc_shoulder();
//adc_elbow();
}
}
|
I guess that's all for functions that sets the width01 value. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Sat Apr 26, 2008 9:26 pm |
|
|
So, let's see how this works. Every time the PIC receives a 'q', it sets fl_right1. The next time the main loop gets around to calling btn1_check, that function will set width01 to a higher value wait 50 msec., and then set width01 back to what it was. During the time that width01 was set to a higher value, it is very likely that the Timer 2 interrupt got loop1 to count all the way down to zero exactly once. When loop1 counts down to zero, it starts over again at LOOPCNT1, and pulse1 is set to width01. This causes PWM_PIN1 to go high for a longer time as Timer 2 continues to count down pulse1. I suppose that the longer pulse on PWM_PIN1 is what causes the servo to move. Is that right?
Since width01 is at the larger value for 20 msec. and Timer 2 counts loop1 down to zero every 19.5 msec, it is possible for two Timer 2 counts to get the same width01 before btn1_check puts it back down again. Is that the inconsistency that you refer to? Exactly what does PWM_PIN1 appear to do?
Robert Scott
Real-Time Specialties |
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Sat Apr 26, 2008 9:46 pm |
|
|
It is actually supposed to work like this. When power is turned on, the servos move to their home positions, or lets just focus on only one servo. The output pin which provides the PWM signal is PWM_PIN1 assigned to PIN_C0.
Timer2 - Serves to constantly pull the pin to highs and lows by counting down loop1. It is set to 390 in which after every full count of 390 it resets the pulse1 to width01 value again. This is to update the position of the servo as the command 'q' might be sent to increment the width01 value. Then, it pulls high the pin and decrements the value pulse1 (set to width01 value) until it reaches zero. It pulls the pin low after it reaches zero. By constantly repeating to pull high and low, it will generate a PWM signal.
Width01 - A variable which serves to update the value pulse1 as the fl_right is checked in btn1_check() function. It can be increased or decreased.
Timer1 - To allow the PIC to run the ADC once every second and printf it out onto the PC. It also acts to check for push button inputs for the servo to move. It also works by checking if there's a button input, the flag is set to TRUE.
Regarding the inconsistency, i can't figure out where did it come from. I'm just suspecting the #INT_TIMER2, #INT_TIMER1 and #INT_RDA are clashing against each other.
If it is not troublesome for you to help me troubleshoot it, i can anytime PM to you and send in the complete code. Really sincerely appreciate all the comments and advice you're giving |
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Sun Apr 27, 2008 5:59 am |
|
|
I've tried take out the lines and slowly run one by one to find out the problem. I found out that its the printf line that is causing the PIC to behave weird when receiving input char. Is there better way to put it instead of printf?
Code: |
void adc_shoulder()
{
if(fl_shoulder==TRUE)
{
set_adc_channel( 0 );
temp0=read_adc() ;
temp0=temp0+1;
actual0=temp0 * 135 / 512;
printf("\n%Ld",actual0); // everything was ok until i include this line.
fl_shoulder = FALSE;
}
}
|
|
|
|
ahsameh Guest
|
rs232 ambiguiti |
Posted: Sun Apr 27, 2008 9:11 am |
|
|
tray adding this line
#use fixed_io(C_OUTPUTS=PIN_C7) |
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
Re: rs232 ambiguiti |
Posted: Sun Apr 27, 2008 8:40 pm |
|
|
ahsameh wrote: | tray adding this line
#use fixed_io(C_OUTPUTS=PIN_C7) |
Hi, I have tried it and it did not make a difference. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 27, 2008 9:02 pm |
|
|
If you want us to work on the problem, then post a short program that
shows the problem. The program must be compilable without errors.
For example, your existing program has 4 PWM channels. If you can
demonstrate the problem with a program that only has 1 channel, then
post that program. Delete all code for the other 3 channels.
Remove all code that is not needed to show the problem. For example,
suppose you have code to setup the A/D converter, but if you delete that
code, you can still show us the problem. Then delete it. Do that with
all unnecessary code in your program.
We don't want to look at 1000 lines of code. Maybe at most, we want
to look at 100 lines of code. Show us the problem with that amount
of code. Compile it and confirm that it shows the problem, and then
post it. Also post your compiler version. |
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Sun Apr 27, 2008 9:57 pm |
|
|
Thanks for the pointers PCM. Sorry for did not posting up a shorter and compilable version. I've reduced the length into just for one channel, one character input with one channel of ADC. Hope it is still not too long.
The problem is my PIC can't receive character input from PC thru RS-232 consistently. Out of 10 'q' button hits, the success rate is approx 6/10 if there is only one character to be detected. If i include the other characters, the success rate is very low, approx 2/10 attempts. I'm just suspecting the printf function is causing this problem as after i removed the printf, it receives character properly.
Code: |
#include <16F877A.h>
#device ADC=10
#include <string.h>
#include <stdlib.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT, NOLVP
#use delay(clock = 20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS, PARITY=N)
#define PWM_PIN1 PIN_C0
#define LOOPCNT1 390
#define LOOPCNT2 10
int16 widthC, widthL, widthR;
int16 temp0,actual0;
int16 width01,i;
int step=1;
int16 loop1 = LOOPCNT1, loop2 = LOOPCNT2;
int16 pulse1;
char rec;
unsigned int fl_cen1, fl_right1, fl_left1, fl_pulse1;
unsigned int fl_shoulder;
//---------------------------------------------------------------------------
void init_main()
{
fl_cen1 = FALSE;
fl_right1 = FALSE;
fl_left1 = FALSE;
fl_pulse1 = 0;
fl_shoulder = FALSE;
}
//***************************************************************************
void Initialize_INT(void)//////////*********************************************
{
setup_adc_ports( RA0_RA1_RA3_ANALOG );
setup_adc( ADC_CLOCK_INTERNAL );
setup_timer_1( T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
setup_timer_2(T2_DIV_BY_1,255,1);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
}
//==================================================================================================
void btn1_check()
{
if(fl_left1 == TRUE)
{
output_high(PIN_C1);
fl_left1 = FALSE;
width01=width01-step;
delay_ms(50);
if(width01<widthL)
{
width01=width01+step;
delay_ms(50);
}
}
}
//========================================================
void adc_shoulder()
{
set_adc_channel( 0 );
temp0=read_adc() ;
temp0=temp0+1;
actual0=temp0 * 135 / 512;
printf("\n%Ld",actual0);
fl_shoulder = FALSE;
}
//=========================================================================================
void main()
{
init_main();
Initialize_INT();
widthL = 14; //0.7 ms duty cycle
widthC = 30; //1.5 ms duty cycle
widthR = 46; //2.3 ms duty cycle
width01 = widthC;
while(1)
{
output_low(PIN_C1); // LED indicator
btn1_check();
if(fl_shoulder == TRUE)
adc_shoulder();
}
}
//==============================================
#INT_TIMER2
void TIMER2_isr(void)
{
if(--loop1 == 0 )
{
loop1 = LOOPCNT1;
pulse1 = width01;
}
if(pulse1>0)
{
output_high(PWM_PIN1);
pulse1--;
}
if(pulse1<=0)
{
output_low(PWM_PIN1);
}
}
//========================================================
#INT_TIMER1
void TIMER1_isr(void)
{
if(--loop2 == 0)
{
loop2 = LOOPCNT2;
fl_shoulder = TRUE;
}
}
//==================================================
#INT_RDA
void serial_isr()
{
rec=getc();
switch(rec)
{
case 'q':
fl_right1 = TRUE;
break;
default:
break;
}
}
//**********************************************************************
|
My compiler version is 4.017 with a crystal of 20MHz. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 27, 2008 11:02 pm |
|
|
Are you sure that you have 4.017 ? It's not actually 4.071 ?
If no one helps you before then, I'll test your code in hardware tomorrow. |
|
|
soong2020
Joined: 13 Feb 2008 Posts: 25
|
|
Posted: Mon Apr 28, 2008 2:33 am |
|
|
Yeah its version 4.017. I'm doing this in a lab computer so i don't think i'm allowed to update the versions without the staff permissions.
Thanks a lot for willing to help. Really in need of help here. |
|
|
|