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

Real-time DC motor control using RS232 serial interface

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



Joined: 11 Sep 2011
Posts: 1
Location: İstanbul

View user's profile Send private message Send e-mail MSN Messenger

Real-time DC motor control using RS232 serial interface
PostPosted: Sun Sep 11, 2011 6:49 pm     Reply with quote

Hello everyone;

As I mentioned above i am trying to control a dc motor (12 V, brushed, 30 rpm). I designed a PID controller in simulink, matlab. I have a closed-loop control which has a feedback from potentiometer. (I glued commutator with potentiometer). In my circuit I have pic 16f877a, L293D and max232 (of course). At first I did speed control and I successfully control (as open loop) the motor. I gave a constant to "packet output standard devices block" and I get the information from "packet input standard devices block". I was working 8 bit range so my inputs are between 0-255. If the number is bigger than 127 motor switches side and starts to return. I think there must be a threshold value, because motor did not start to move until I gave the values more than 50 or -50.

Now, I am trying to control position of the motor, I am trying to control with 10 bits but i couldn't send 10 bits to my PIC, so i send 16 bits datas to the pic... As i read threads and topics about sending 10 bits to PIC, I tried to write set_pwm1_duty(xL)...but it didn't work because my pwm duty cycle is not a constant, it changes when potentiometer is moving. So I couldn't go further on my project. Here is my code:

Code:

#include <16F877A.H>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=20000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, stop=1, parity=N, bits=8)

unsigned int8 bilgi;
unsigned int8 a,b;
unsigned int16 c,d,e;

#int_rda
void kesme()

a=getc();
c=a<<8;
b=getc();
d=c&b;

if (d<=511)
 {
  set_pwm1_duty(d);
  output_high(pin_d1);
  output_low(pin_c3);
 }
else
 {
  e=1024-d;
  set_pwm1_duty(e);
  output_high(pin_c3);
  output_low(pin_d1);
 }
}

void main()
{
setup_psp(PSP_DISABLED);
setup_timer_1(T1_DISABLED);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(ALL_ANALOG);
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_OFF);
setup_timer_2(T2_DIV_BY_1,255,1);
enable_interrupts(GLOBAL);
enable_interrupts(int_rda);

while(1)
{
set_adc_channel(0);
delay_us(20);
bilgi=read_adc();
delay_us(20);
putc(bilgi);
output_high(pin_b0);
delay_ms(20);
}
}

The version of the compiler is PCW 4.093
and there are few pictures of the circuit,
http://imageshack.us/photo/my-images/198/07092011488.jpg/
http://imageshack.us/photo/my-images/339/07092011487.jpg/
http://imageshack.us/photo/my-images/690/07092011484.jpg/
http://imageshack.us/photo/my-images/832/10092011491.jpg/
http://imageshack.us/photo/my-images/163/10092011490.jpg/
Also simulink model of PID controller (I changed the degree values to the radian).
http://imageshack.us/photo/my-images/27/pidsimulink.png/
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Sep 12, 2011 3:02 am     Reply with quote

Quote:
it didn't work because my pwm duty cycle is not a constant, it changes when potentiometer is moving

Seems quite normal for a controller, isn't it? You didn't clarify the actual problem.

It would be interesting to know, how the L293 is exactly wired to the PIC.

Code:
a=getc();
c=a<<8;
b=getc();
d=c&b;

Doesn't seem like the right way to assemble two bytes to a word. What's the purpose of the bitwise and? Perhaps you should stay with 8-bit pwm control for the time being.

Otherwise, you have to think of a reliable method to transmit two bytes, still knowing, which is meant to be the high byte. It doesn't work the way you do.

As you are only utilizing 10 bits of 16, a slightly different coding can easily achieve an unequivocal byte assignment. Just think a bit.

P.S.: The ADC is operated in 10 bit mode, but you are only reading 8 bit result.
temtronic



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

View user's profile Send private message

PostPosted: Mon Sep 12, 2011 5:24 am     Reply with quote

quick comments

1 You should always add 'errors' to the USE RS232(..) options

2 Look at the use of buffered serial input( ex_sisr.c) in the examples folder

3 Hardcode a series of 10bit values and run a test to see the results eliminating the serial part of this program. By breaking the program into workable segments you'll find the area that's causing you the problem.
asmboy



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

View user's profile Send private message AIM Address

PostPosted: Mon Sep 12, 2011 10:45 am     Reply with quote

and this:
FIRST
I would NOT do my PWM manipulation inside the receive data interrupt
routine, all while ints were still off.

SECOND you have a GREAT way to hang yourself in that INT service block too.

Please think of about what happens if if only ONE character is sent to your handler?

The int handler will trigger on 'a' BUT you have a hard code expectation that you WILL get 2 chars on ONE int call. (but ints are still OFF as soon as you enter for char 'a' ... hmmmm )

If only ONE comes in - you will hang forever as you will be stuck on the code line

b=getc();


PLUS at low baud rates - you can do a LOT of other potentially valuable processing while WAITING for that second char to arrive.

and THEN assemble your int16 data value in MAIN(), set PWMs etc.

Think more in the time domain of whats going on and WHEN.

A rule of thumb: when inside an interrupt handler - do simple jobs ,fast,
and watch for any unanticipated delays.
asmboy



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

View user's profile Send private message AIM Address

PostPosted: Mon Sep 12, 2011 2:03 pm     Reply with quote

BTW: do you have a SCHEMATIC of your circuit you can post ??
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 12, 2011 4:46 pm     Reply with quote

What is the format of the numbers that you are sending from MATLAB
to the PIC ? Is it ASCII, or raw binary ?

For example, if MATLAB sends the number 1023 to the PIC, does it send:
31 30 32 33
These are the ASCII numbers (in hex) for 1, 0, 2, 3
And is there a terminator byte, such as a carriage return (0x0D) ?

Or does it send thse two bytes:
FF 3F
These are the raw hex values (not ASCII), in "LSB first" format.
Or maybe the bytes are in some other format, or byte order.

The first thing you need to determine is what the transmission format is.
Then you can write PIC code to receive it and decode it.
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