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

Controlling two motors using UART

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



Joined: 01 May 2015
Posts: 1

View user's profile Send private message

Controlling two motors using UART
PostPosted: Sat May 02, 2015 12:10 am     Reply with quote

Hey,

I am trying to make a PID control of 2 hacked servo motors (the control circuit is removed) wirelessly. The TX PIC16F877a is receiving the reference data from 2 potentiometers using the ADC and send it to the RX PIC18F4431 which calls a method that calculates the error, etc... and then drives the motors using the Power PWM Module.

First of all when I am sending data for only 1 motor it works really well. However when I also send the data for the second motor problems arise.

I feel I have something wrong with the logic I am using to send the data. I first send the first potentiometer reading, and immediatly send a character of number '1'. Then I send the second potentiometer reading, and immediately send a character of number '2'. On the RX side I receive the reading, then receive the number. I check which number that was and then call the necessary functions for the corresponding motor.

The simulation (Proteus) showed the motors not moving at all. I played around a bit and noticed that if I add a delay of 2 ms between each putc() the motors start moving. However, the problem is that the motors aren't acting properly. When I try sending data for 1 motor only it works properly. However when I send data for 2 motors, the second motor for some reason sometimes follows the first (it should potentiometer).


TX

Code:
#include <16f877a.h>
#DEVICE ADC=8;
#fuses  PUT, HS, NOWDT, NOLVP, NOBROWNOUT
#use delay (crystal=4000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, errors)

unsigned int Desired1;
unsigned int Desired2;
//unsigned int Desired3;

unsigned int counter=1;

void main() {
   
   setup_adc(ADC_CLOCK_DIV_8);
   setup_adc_ports(ALL_ANALOG);
   
   while (TRUE) {
   
      //Read first potentiometer
      set_adc_channel(0);
      delay_us(20); // Delay needed for the channel selection to settle
      Desired1 = read_adc();
     
      delay_ms(2);
     
      putc(Desired1);
      output_d(Desired1); // Display the reading to check
     
      delay_ms(2);
     
      putc(1); // First Reading
      delay_us(100);


      //Read first potentiometer
      set_adc_channel(1);
      delay_us(20); // Delay needed for the channel selection to settle
      Desired2 = read_adc();
 
      delay_ms(2);
     
      putc(Desired2);
      output_d(Desired2); // Display the reading to check
     
      delay_ms(2);
     
      putc(2); // Second Reading
      delay_us(100);

       
}
}



RX
Code:
#include <18f4431.h>
#DEVICE ADC=8;
#fuses  PUT, HS, NOWDT, NOLVP, NOBROWNOUT
#use delay (crystal=4000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS)
//#use pwm(PWM1,FREQUENCY=5000) // TODO - Fix freq

#define PORTD0 PIN_D0
#define PORTD1 PIN_D1
#define PORTD2 PIN_D2
#define PORTD3 PIN_D3
#define PORTD4 PIN_D4
#define PORTD5 PIN_D5

#define PORTB7 PIN_B7

unsigned int  Desired;
unsigned int Desired1;
unsigned int Actual1;
unsigned int Desired2;
unsigned int Actual2;

//unsigned int  Desired3;
//unsigned int Actual3;

unsigned int n;


float epsilon = 0.01;
float PWM_signal;

float dt =0.01;
float  Kp = 0.6;
float  Kd =0.2;
float  Ki =0.5;

void outputset(unsigned int port,unsigned int val){

               
                    // Adjusts motor direction


}

float PIDcal(unsigned int Desired,unsigned int Actual, unsigned int in2 ,unsigned int in1){


                        //Calculate PID


}

void main() {

   setup_adc(ADC_CLOCK_DIV_2);
   setup_adc_ports(sAN0|sAN1|sAN2|sAN3||sAN4|sAN5);
   setup_power_pwm_pins(PWM_BOTH_ON, PWM_BOTH_ON, PWM_BOTH_ON, PWM_BOTH_ON);
   setup_power_pwm(PWM_CLOCK_DIV_4|PWM_FREE_RUN, 1, 0, 199, 0, 1, 0); // 4Mhz: 2499 for 400Hz, 199 for 4000Mhz
   
   while (TRUE) {
   
     if (kbhit()) {
         Desired = getc(); // Recieve reading
     }
     
      if (kbhit()) {
         n = getc(); // Recieve number
     }
     
     
     if(n==1){ // First potentiometer - motor1
   
         Desired1 = Desired;
         set_adc_channel(0);
         delay_us(10); // Delay needed forthe channel selection to settle
         Actual1 = read_adc();
         
         PWM_signal= PIDcal(Desired1,Actual1, 0, 1);
         set_power_pwm0_duty(PWM_signal);
     }
     
     
     if(n==2){ // Second potentiometer - motor1
     
         Desired2= Desired;
         
         set_adc_channel(1);
         delay_us(10); // Delay needed for the channel selection to settle
         Actual2 = read_adc();
         
         PWM_signal= PIDcal(Desired2,Actual2, 2, 3);
         set_power_pwm2_duty(PWM_signal);
     }
     

 }   
     
     
   }
}


In short:
Is the logic I am using to transmit the data here wrong ? Maybe the data is being lost in the middle ?

Thanks.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat May 02, 2015 1:52 am     Reply with quote

You mention Proteus.

Do you have real hardware?

Mike
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat May 02, 2015 3:08 am     Reply with quote

Code:
   while (TRUE) {
   
     if (kbhit()) {
         Desired = getc(); // Recieve reading
     }
     
      if (kbhit()) {
         n = getc(); // Recieve number
     }
Try changing to:
Code:
   while (TRUE) {
   
     if (kbhit()) {
         Desired = getc(); // Receive reading
         n = getc(); // Receive number
     }
You want to make sure you have received the whole message before processing the received data. In your original version it is very likely that when you have received the reading, that the next character with the number has not arrived yet. This means you will skip the second getc() call and repeat the loop again. Only by luck, one in thousand times, you will enter the second getc() call.

Another improvement would be that you start your message always with a known character. Just in case your master and slave get out of sync, this is a method for your slave to detect which received byte is the start of a new message.
temtronic



Joined: 01 Jul 2010
Posts: 9246
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat May 02, 2015 6:20 am     Reply with quote

In any form of 'serial communications' with the PICs UART it is necessary to use an 'interrupt driven buffer'. Look at the CCS supplied example 'ex_sisr.c'.
Well maybe not necessary but to get reliable communications !

Jay
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