![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Egemen
Joined: 11 Sep 2011 Posts: 1 Location: İstanbul
|
Real-time DC motor control using RS232 serial interface |
Posted: Sun Sep 11, 2011 6:49 pm |
|
|
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/ |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Sep 12, 2011 3:02 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Mon Sep 12, 2011 5:24 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Sep 12, 2011 10:45 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Sep 12, 2011 2:03 pm |
|
|
BTW: do you have a SCHEMATIC of your circuit you can post ?? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 12, 2011 4:46 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|