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 support@ccsinfo.com

PIC to PIC communication (wireless)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ali_P



Joined: 18 Oct 2011
Posts: 7
Location: Pakistan

View user's profile Send private message ICQ Number

PIC to PIC communication (wireless)
PostPosted: Tue Oct 18, 2011 7:44 am     Reply with quote

Hi everyone I'm making a project which involves two PICs (16F876A) to communicate using RS232 interface(half duplex). The Tx is attached with a remote controller (AN0,AN1,AN2) 3 channels of ADC with the PIC and sending a string of char (long int values) to the xbee and then on the Rx i have to drive 3 servos. I can transmit and receive the int values in the Rx using sisr, but processing them to drive the servos is problematic.
Although i have processed one channel (AN0) using atol() function, but if another channel is used then things go wrong. Help needed ! Crying or Very sad

Code:

//=============TX CODE===============
#include <16F876A.h>
#device adc=10
#include <stdio.h>
#include <STDLIB.H>
#include <string.h>
#fuses HS,NOWDT,PROTECT,PUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)

// TX CODE INVOLVING 3 VARIABLE ROLL,PITCH,YAW
void main(void)
{
 unsigned long value1,sum1,value2,sum2,value3,sum3,ex=233;
 unsigned long roll[10],pitch[10],yaw[10];   //average reading of 10 values from remote (analogue)
 int out1,out2,out3;
 char string [11];
 char string2 [5];

 SETUP_ADC_PORTS(ALL_ANALOG);
 setup_adc( ADC_CLOCK_INTERNAL );

   while(TRUE)
    {
      for (out1=0;out1<10;out1++) //pitch
        {
      set_adc_channel( 0 );
       delay_us (100);
      value1 = Read_ADC();
        pitch[out1] = value1;
        }

       for (out1=0;out1<10;out1++)
       
         sum1 += pitch[out1];
          sum1 = sum1/10;

       for (out2=0;out2<10;out2++) //roll
         {
           set_adc_channel( 1 );
            delay_us (100);
          value2 = Read_ADC();
            roll[out2] = value2;
         }

       for (out2=0;out2<10;out2++)
       
         sum2 += roll[out2];
          sum2 = sum2/10;


       for (out3=0;out3<10;out3++) //yaw
         {
           set_adc_channel( 2 );
           delay_us (100);
          value3 = Read_ADC();
            yaw[out3] = value3;
         }

       for (out3=0;out3<10;out3++)

         sum3 += yaw[out3];
          sum3 = sum3/10;

         sprintf(string,"*%lu",sum1); //converting long int value to string (pitch and roll)
        sprintf(string2," #%lu",sum2); //* identifier for pitch # identifier for roll

       strcat(string,string2); //using two values for testing only; combining two
                               //string to form single string to be transmitted

     printf(string);          //transmitting string (combined)


         sum1 = 0;         //clearing values
         sum2 = 0;
         sum3 = 0;

 delay_ms(50);

      }
     }

//======================RX CODE================
#include <16F876A.h>
#device adc=10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS) // Stream for remote
#include <input.c>

#define LEFT_SERVO_PIN   PIN_B4
#define RIGHT_SERVO_PIN  PIN_B5

//sisr
//problem in converting data to long int values (although pitch is converted using atol())
// RX CODE TO READ AND REACT THE SERVOS, although im receiving data
//but i cannot initialize timer1 intrpt in the servos.c utility also and

#include <servos.c> // utility to drive 2 servos (not working with the rx code)

#define BUFFER_SIZE 10

BYTE buffer[BUFFER_SIZE];

BYTE next_in = 0;
BYTE next_out = 0;

init_servos();

#int_rda
void serial_isr() {   //interupt service routine, serial

   int t,v,x;
  char pitch[5];
  char roll[5] ;
  unsigned long p_c=0, r_l=0;


   buffer[next_in]=getc();
   t=next_in;

 if (buffer[0] == '*');                //string indentifier for pitch
   {
  for (x=0;x<3;x++)
   pitch[0+x] = buffer[1+x];
    }

        if (buffer[4] == '#')           //string identifier for roll
         {
         for(v=0;v<3;v++)
          roll[0+v] = buffer[4+v];      //end of data
           }
                                        //converting data to int16
             p_c = atol (pitch);
             r_l = atol (roll);

            printf ( "\r %lu  ", p_c);
           printf ( "      %lu  ", r_l);

           p_c = 0;                      // clearing data
             r_l = 0;

   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;// Buffer full !!
         }


#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

void main() {
   enable_interrupts(int_rda);
   #if defined(__PCD__)
   enable_interrupts(intr_global);
   #else
   enable_interrupts(global);
   #endif

   printf("\r\n\Running...\r\n");

   do {
     delay_ms(50);
      while(bkbhit)
        putc( bgetc() );
   } while (TRUE);
}

The problem is also for the driving of servos. Can anyone please suggest a code for Rx receiving with servo drive?
Thank you very much.
_________________
Ali
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Tue Oct 18, 2011 8:27 am     Reply with quote

I think you are trying to do too many things a the same time...

Start small.

First, read one ADC channel, and controll a Servo with that data, on the SAME PIC.

Second, read one ADC channel, and send the data to another PIC through WIRED serial, and control the servo using the data on the second pic.

Third, same as above but replace wired serial with Wireless module.

Once you got that working... you can expand to more servos.

The 16f876a has 2 PWM channels... you are trying to control 3 servos... thus you need a Software PWM routine for the third servo, or all three.

Your PWM needs to be set to the right FREQUENCY... which may vary among servo manufacturers slighly... if memory is right its about 1ms pulse max rotation to one side, and 2ms pulse max rotation to the other side... with a center position of 1.5ms ... and refresh rate should be every 20ms.... (old/non-digital futaba at least... correct me if im wrong).

Your adc channel reading should control the DUTY CYCLE only.
You might need to scale the value before feeding it to the duty cycle control function.


Start small. Test code blocks rather a whole program.

PIC#1: read adc values, and print to serial.

PIC#2: read serial buffer, adjust pwm duty cycles.

From your variable names... i see you might be trying to build you own RC plane remote...Cool.
I am more of a Oldschool U/C plane guy.

I don't think you need to average that many readings ... if any at all actually... as you are constanly moving your fingers thus changing the ADC values... (if you are making a remote control for a plane).

Also... if you are going to average values... take 10 readings, eliminate the highest and lowest, and then do a bitshift x8.... its faster check out the filter threads here.
_________________
CCS PCM 5.078 & CCS PCH 5.093
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Tue Oct 18, 2011 8:39 am     Reply with quote

Furthermore:

Code:
sprintf(string,"*%lu",sum1); //converting long int value to string (pitch and roll)
sprintf(string2," #%lu",sum2); //* identifier for pitch # identifier for roll

strcat(string,string2); //using two values for testing only; combining two
//string to form single string to be transmitted

printf(string); //transmitting string (combined)


Why are you doing this?... just send the 3 ADC bytes in a row, as hex values...
no need to combine them into anything....

You need to have a circular buffer that holds 4 characters... (Start identifier,roll, pitch, yaw).

Your receiver checks this buffer constantly... if the buffer contains all 4 bytes in the right order, save them in their appropiate duty cycle variables, and clear the buffer.... repeat.


Your Serial ISR is HUGE.... it should only save data on a buffer... and process everthing on the main function.

IRS=Get in, service, Get out - QUICKLY.
_________________
CCS PCM 5.078 & CCS PCH 5.093
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Oct 18, 2011 5:45 pm     Reply with quote

Post servos.c

Otherwise I have to take your word for there being no
unintended function interdependence.
Ali_P



Joined: 18 Oct 2011
Posts: 7
Location: Pakistan

View user's profile Send private message ICQ Number

PostPosted: Tue Oct 18, 2011 9:49 pm     Reply with quote

Thank you Gabriel for your reply yes you guessed it right, I'm a R/C plane guy Wink

Well the problem was that I was previously sending int16 values directly, using printf function,
Code:

printf ("*%lu,%lu,%lu",pitch,roll.yaw);

I was able to receive all three values but was not able to process/apply mathematical operations because it was just mere characters and atol() function was not working. But then I tried sprintf function which changes the int format to a string of char to be sent from Tx, that worked and I was able to process data from the buffer[], atol () was working then, the problem came when the 2nd variable arrived.
Do I have to change the #rs232 to give hex directly? I'll try that.
I did first in the main(), but I don't know it was not working somehow?
I'm new to ccs c, could you suggest me a code for driving servos using software pwm and receiving data ? That will be helpful really.
Yes you are right but the servos data: high time: 1-2ms freq:50/60Hz/20ms Pulse
I have yet another variable "throttle" I'm just avoiding it for a time being, first let the 3 variable run Smile
I know my isr is huge but don't have any choice then. Rolling Eyes
_________________
Ali
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Wed Oct 19, 2011 7:56 am     Reply with quote

PSEUDO Code.....


Code:
Void Main()
{
   
   Set_ADC_Channel(0);   //set ADC Channel
   Delay_US(20);             //small delay for sample capacitor to charge
   Elevator=Read_ADC();  //read and store value

   Set_ADC_Channel(1);
   Delay_US(20);
   Alerons=Read_ADC();

   Set_ADC_Channel(2);
   Delay_US(20);
   Rudder=Read_ADC();

   Printf("*");                  // start character (ascii)
   Printf(Elevator);           // straight hex...
   Printf(Alerons);
   Printf(Rudder);

}



... if you print your values to terminal, if your analog readings are:
elevator=0x31
Aleron=0x32
rudder=0x33

you will see "*123" thats because your raw hex values are the same as the ascii values for 1,2&3....hyperterminal wont know the diference...
us SIOW.... it shows you both hex value and ascii....
the same applys for other values.... i think this is why you thought you needed to convert your values to somthing else and used Sprint

you dont need much more than that on your Transmitter...
asuming you are using 8bit ADC, with a variable resistor on each Analog input...

check out the Printf details... you can print all 4 characters in a single line... i just used 4 separate lines to be clearer.



on you receiver end... things are a bit different...

you need to scale the received values for elevator, alerons, and rudder properly....

your servos should be centered when your values for Elevator, aleron and rudder are 0x7F (Decimal 127)

read up on Circular buffers.... (hint: this should be the only thing in your ISR)


G.
_________________
CCS PCM 5.078 & CCS PCH 5.093
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Wed Oct 19, 2011 8:01 am     Reply with quote

one last thing...

I believe you can update servos faster than 20ms. They just use more current because they are constantly updating their position.

You could set up a square wave with a period of 3ms.

50% duty cycle will be 1.5ms which would be Center position.
_________________
CCS PCM 5.078 & CCS PCH 5.093
Ali_P



Joined: 18 Oct 2011
Posts: 7
Location: Pakistan

View user's profile Send private message ICQ Number

PostPosted: Thu Oct 20, 2011 1:26 am     Reply with quote

Thank you Gabriel for your reply. Actually my problem is mostly solved Smile You are right about sending hex values, and HT was not able to distinguish b/w the raw hex and char values (1,2,3) I sent. I have almost done my both rx and tx coding, the rx problem is mostly solved. Actually I got help in it by a sample program which ran 6 servo from the usart slave. I'm using 10 bit ADC, hmm will definitely try updating servos faster than 20ms period, but I guess this will cause jitter among the servos ?
The other thing was, as the HW PWM of pic minimum freq is 244hz it cannot be used as R/C servo use, limited for motor control use (I don't know if anyone has added a frequency divider at the HW PWM for 50Hz servo control? That would be worth a try for me). Now I am relying on software pwm and timer0 interrupt, things in the simulation seems working, though I have already sent and received data using Xbees wireless mod earlier. I have scaled 10 bit ADC to have 50 values (servo positions: 1023/50=20), that will give me a center position of 25 (1.5ms)(0-----25-----50). This scaling should also work well for throttle position (the fourth channel). I'll be uploading my Tx/Rx code shortly. There was a problem with controlling more than 2 servos, but I'll try to fix it.
Thanks alot.
_________________
Ali
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Thu Oct 20, 2011 10:00 am     Reply with quote

I just saw the servo code posted on the library. I immediately thought of your problem.

Actually you don't need to do anything now.

Just copy that program in your RX... add a RF receiver, and make your TX send the appropriate strings... you have a six channel remote!

Ailerons, elevator, rudder, throttle, flaps and gears!

Updating servos faster will cause jitter unless the position pulse is exactly the same and the internal position trimpot reads exactly the same.... which will never happen IMO... which means Jitter.

But you do gain Torque when the servo is updating its position the little motor inside is on.. applying force on the control surfaces its attached.

If you update every 20ms as required you have ~18ms of the motor being off... thus no force being applied to the control surfaces its attached to.

Digital servos use this to their advantage.

Seems you have all you need.
_________________
CCS PCM 5.078 & CCS PCH 5.093
olivier



Joined: 08 Apr 2010
Posts: 11

View user's profile Send private message

this is very excellent info exchange
PostPosted: Wed Oct 26, 2011 6:34 pm     Reply with quote

Gabriel and Ali,
thank you very much for posting info. I am in the process of doing something similar to your and I don't know where to start. I bought an small RC plan other day and want to modify it but still thinking of what to do. You both give me courage to start.
thanks. Hope that I get somewhere in near future Smile
Ali_P



Joined: 18 Oct 2011
Posts: 7
Location: Pakistan

View user's profile Send private message ICQ Number

PostPosted: Tue Nov 01, 2011 8:24 am     Reply with quote

Olivier, good luck for your project. I'll be posting my tx/rx code shortly as
soon as I get time, it may help you and others as well, and let us be informed too. Smile

Regards.
_________________
Ali
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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