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 CCS Technical Support

Problem with serial transmit and receive...
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
soong2020



Joined: 13 Feb 2008
Posts: 25

View user's profile Send private message

PostPosted: Fri Apr 25, 2008 1:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Apr 25, 2008 1:27 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Apr 25, 2008 10:47 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 26, 2008 10:59 am     Reply with quote

Looking for help here. Anyone can offer some advice on how to solve this problem?
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Sat Apr 26, 2008 4:48 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 26, 2008 9:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 26, 2008 9:26 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 26, 2008 9:46 pm     Reply with quote

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 Smile
soong2020



Joined: 13 Feb 2008
Posts: 25

View user's profile Send private message

PostPosted: Sun Apr 27, 2008 5:59 am     Reply with quote

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
PostPosted: Sun Apr 27, 2008 9:11 am     Reply with quote

tray adding this line

#use fixed_io(C_OUTPUTS=PIN_C7)
soong2020



Joined: 13 Feb 2008
Posts: 25

View user's profile Send private message

Re: rs232 ambiguiti
PostPosted: Sun Apr 27, 2008 8:40 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Apr 27, 2008 9:02 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Apr 27, 2008 9:57 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Apr 27, 2008 11:02 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 28, 2008 2:33 am     Reply with quote

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.
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 Previous  1, 2, 3  Next
Page 2 of 3

 
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