0
\$\begingroup\$

I am trying to make a serial servo controller using pic18f4550 microcontroller.

following if the complete code that i've tried..

please note that i'm currently sending 8bit hex to control only one servo. i'm sending this data from one pic to another..

#define FREQ 20000000
#define baud 9600
#define spbrg_value (((FREQ/64)/baud)-1)


unsigned char rx_data(void);
void tx_data(unsigned char);


void main()
{
int i;
double state;
int ip1=0;
SPBRG=spbrg_value;      // Fill the SPBRG register to set the Baud Rate
RCSTA.SPEN=1;           // To activate Serial port (TX and RX pins)
TXSTA.TXEN=1;           // To enable transmission
RCSTA.CREN=1;           // To enable continuous reception

TRISB.RB0=0;

while(1)
{
    ip1=rx_data();    // Receive data from PC

    //this part doesn't gets executed!!
    state=max((ip1/4)+1,12);
    LATB.LATB0=1;

    for (i=0;i<state;i++)
       delay_us(10);

    LATB.LATB0=0;

    for (i=0;i<200-state;i++)
       delay_us(1);
}
}


void tx_data(unsigned char data1)
{
TXREG=data1;                                     // Store data in Transmit register
while(PIR1.TXIF==0);                             // Wait until TXIF gets low
}


unsigned char rx_data(void)
{
while(PIR1.RCIF==0);                           // Wait until RCIF gets low
return RCREG;                                 // Retrieve data from reception register
}

i've made sure that proper data is being sent by the master pic by hooking up to the PC's serial port and observe output..

as stated in code the part after ip1=rx_data(); doesn't gets executed.

i've also confirmed by commenting out the ip1=rx_data(); part and then replacing ip1 variable with an int value... then the servo moves to the proper position according to the value instead of ip1(which ranges from 0 to 255).

any help?

UPDATE:

with the suggestions given in the answers i've cross checked the following.

1.Both PICs running on 20mhz so frequency is correct.

2.serial data format is correct. i am receiving the proper data to the PC.

3.Wiring checked.

4.decoupling( plz explain how to do proper decoupling).

5.power supply. ( both running of a 5v 1 amp wall chargers).

so the most probable problem (other than the software) may be the improper decoupling. can anyone explain this to me?

\$\endgroup\$
  • \$\begingroup\$ Your question has nothing to do with servo control. I suggest renaming it, and removing the tag. \$\endgroup\$ – Scott Seidman Dec 19 '14 at 18:56
  • \$\begingroup\$ Decoupling: a capacitor (typically 0.1uF) connected directly across the MCU power pins. \$\endgroup\$ – Bruce Abbott Dec 19 '14 at 20:29
1
\$\begingroup\$

Firstly, Your code is blocking. That's not the way to wait for serial data. You will have to monitor the RX interrupt flag from the main loop and if set do the ip1=rx_data(); to get the data. In your case, if your wiring of the UART pins are wrong or there is no data from the master MCU, the line while(PIR1.RCIF==0); is an infinite loop. That explains why the rest of your code doesn't work.

Second thing I noticed is that you are giving the servo only one pulse per control signal. Most hobby RC servo motors expect at least 3 such pulses to reliably position the horn.

\$\endgroup\$
  • \$\begingroup\$ Not just 3. RC servos will slack off if it stops receiving pulses. So you need to continuously send pulses at a rate of 20 per second to hold the horn position. \$\endgroup\$ – slebetman Dec 19 '14 at 7:18
  • \$\begingroup\$ That is true if there is load on the servo horn trying to move it. If there is no load or a small load, 3 pulses is enough to put it at the right potion. \$\endgroup\$ – Siddharth Dec 19 '14 at 7:38
  • \$\begingroup\$ 3 pulses may not be enough. A Hitec HS-325HB that I tested needed 13~14 consecutive pulses to move from the 1ms to 2ms position. \$\endgroup\$ – Bruce Abbott Dec 19 '14 at 20:46
0
\$\begingroup\$

Your code appears to be working fine, so if it's sticking in rx_data() then either the PIC is running on the wrong frequency, the serial data format is incorrect, or you have a hardware problem (wiring error, inadequate decoupling, bad power supply etc.).

To get sufficient clock accuracy you should be using a crystal or ceramic resonator, and the configuration bits must be set to HS oscillator. Also check that the master PIC is sending serial data with the same format and baud rate (accurate to better than 2%). Just because your PC can read it does not prove that it is correct!

Another possible issue is that your code only produces one servo pulse for each serial byte received. If you intend to send a byte every 20ms or so then that's fine, but be aware that the servo may not work properly if the pulse repetition rate is too low or too high.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.