|
要如何同时控制5个servo motor?? (全部解决了,谢谢大家的帮忙)
[复制链接]
|
|
发表于 5-4-2009 10:01 PM
|
显示全部楼层
原帖由 crazybear 于 5-4-2009 07:56 PM 发表
我想应该是这样吧!
但是那input_state() function好像没有做用这样的。
那OUTPUT ALWAYS HIGH
#include
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP
...
用别个port.port a default给adc.你没有configure 成digital.当然不能。刚看你之前的code.也是用porta.我就不知道为什么可以了。 lol
很靠近了。
现在你generate 1.5ms high, 18.5ms low.
delay 1second,
1ms high, 19ms low.
delay 1 second
2ms high, 18ms low.
结果告诉我。
[ 本帖最后由 fritlizt 于 5-4-2009 10:16 PM 编辑 ] |
|
|
|
|
|
|
|
楼主 |
发表于 5-4-2009 10:08 PM
|
显示全部楼层
原帖由 fritlizt 于 5-4-2009 10:01 PM 发表
用别个port.port a default给adc.你没有configure 成digital.当然不能。
很靠近了。
现在你generate 1.5ms high, 18.5ms low.
delay 1second,
1ms high, 19ms low.
delay 1 second
2ms high, 18ms low.
结 ...
换去PORT b 可以了。
以下是RESULT。。。
|
|
|
|
|
|
|
|
楼主 |
发表于 5-4-2009 10:33 PM
|
显示全部楼层
|
|
|
|
|
|
|
发表于 5-4-2009 10:40 PM
|
显示全部楼层
原帖由 crazybear 于 5-4-2009 10:33 PM 发表
做到了。。
#include
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP
int16 highvalue, lowvalue;
void main()
{ setup_timer_1 (T1_INTERNAL|T1_DIV ...
很好。 其实这个program就是control 一个servo 的例子。
你已经过第一关了。恭喜恭喜。
接下来。 来high一点的。 直接控制5个servo.
给你一点hints.
pin1,2,3,4,5 low.
用interrupt一直做
pin1 high 1.5ms.
pin1 off, pin2 high 1.5ms
pin2 off, pin3 high 1.5ms.
pin3 off, pin4 high 1.5ms.
pin4 off, pin5 high 1.5ms
pin5 off 12.5ms |
|
|
|
|
|
|
|
楼主 |
发表于 5-4-2009 11:20 PM
|
显示全部楼层
原帖由 fritlizt 于 5-4-2009 10:40 PM 发表
很好。 其实这个program就是control 一个servo 的例子。
你已经过第一关了。恭喜恭喜。
接下来。 来high一点的。 直接控制5个servo.
给你一点hints.
pin1,2,3,4,5 low.
用interrupt一直做
pin1 high ...
做到了。。希望你看得明白RESULT。。。
- #include <16F877A.h>
- #use delay(clock=20000000)
- #fuses HS,NOWDT,NOPROTECT,NOLVP
- int16 highvalue, lowvalue;
- void main()
- {
- SET_TRIS_B( 0x00 );
- setup_timer_1 (T1_INTERNAL|T1_DIV_BY_4);
- enable_interrupts(GLOBAL);
- enable_interrupts(INT_TIMER1);
-
- while(1)
- {
- highvalue = 63661; //1.5ms
- lowvalue = 49911; //12.5ms
- }
- }
- #INT_TIMER1
- void timer1_interrupt ()
- {
- if(input_state(PIN_B0))
- {
- output_low(PIN_B0);
- output_high(PIN_B1);
- set_timer1(highvalue);
- }
-
- else if (input_state(PIN_B1))
- {
- output_low(PIN_B1);
- output_high(PIN_B2);
- set_timer1(highvalue);
- }
-
- else if (input_state(PIN_B2))
- {
- output_low(PIN_B2);
- output_high(PIN_B3);
- set_timer1(highvalue);
- }
-
- else if (input_state(PIN_B3))
- {
- output_low(PIN_B3);
- output_high(PIN_B4);
- set_timer1(highvalue);
- }
-
- else if (input_state(PIN_B4))
- {
- output_low(PIN_B4);
- set_timer1(lowvalue);
- }
-
- else
- {
- output_high(PIN_B0);
- set_timer1(highvalue);
- }
-
- clear_interrupt(INT_TIMER1);
- }
复制代码
|
|
|
|
|
|
|
|
发表于 5-4-2009 11:25 PM
|
显示全部楼层
不错。 如果有proteus v7会更好。 4channel oscilloscope.更了解现在做的是什么。
对了。 希望你解释解释这个代表什么。
如果我想要pin1, high 1ms, pin2, 1.2ms, pin3 1.4ms, pin4 1.6ms, pin5 1.8ms.
该怎么做?
[ 本帖最后由 fritlizt 于 5-4-2009 11:28 PM 编辑 ] |
|
|
|
|
|
|
|
楼主 |
发表于 5-4-2009 11:36 PM
|
显示全部楼层
原帖由 fritlizt 于 5-4-2009 11:25 PM 发表
对了。 希望你解释解释这个代表什么。
如果我想要pin1, high 1ms, pin2, 1.2ms, pin3 1.4ms, pin4 1.6ms, pin5 1.8ms.
该怎么做?
就是算1ms, 1.2ms, 1.4ms, 1.6ms, 1.8ms 所需要 INTERRUPT 的时间
最后用20 - (1.2+1.4+1.6+1.8) = 减出来的就是我们需要OUTPUT LOW的时间了。
从这方式中我发现到一个漏洞,那就是说,如果全部HIGH的时间都是2ms,然后突然第二CHANNEL的OUTPUT变1.4ms了,那下一个CYCLE时,那CHANNEL2的20ms PERIOD会跑了。
就是说多过20ms了。
或者说如果全部HIGH的时间都是1ms,然后突然第二CHANNEL的OUTPUT变1.5ms了,那下一个CYCLE时,那CHANNEL2的20ms也是PERIOD会跑。就是说少过20ms了。 |
|
|
|
|
|
|
|
发表于 6-4-2009 11:29 AM
|
显示全部楼层
原帖由 crazybear 于 5-4-2009 11:36 PM 发表
从这方式中我发现到一个漏洞,那就是说,如果全部HIGH的时间都是2ms,然后突然第二CHANNEL的OUTPUT变1.4ms了,那下一个CYCLE时,那CHANNEL2的20ms PERIOD会跑了。
就是说多过20ms了。
或者说如果全部HIGH的时间都是1ms,然后突然第二CHANNEL的OUTPUT变1.5ms了,那下一个CYCLE时,那CHANNEL2的20ms也是PERIOD会跑。就是说少过20ms了。
之前我和 fritlizt 大大讨论时说到:
而且当你换其中一个 channel 的 pulse width 时,后面的 channel 会有一个 cycle 的 period 跑掉。
就是这个意思。但是一个 cycle 的 period 跑掉,影响并不大。 |
|
|
|
|
|
|
|
楼主 |
发表于 6-4-2009 11:53 AM
|
显示全部楼层
原帖由 waiweng83 于 6-4-2009 11:29 AM 发表
之前我和 fritlizt 大大讨论时说到:
就是这个意思。但是一个 cycle 的 period 跑掉,影响并不大。
有人有用真的SERVO MOTOR试过吗?
当PERIOD跑掉的事后,SERVO MOTOR的反应会怎样的? |
|
|
|
|
|
|
|
发表于 6-4-2009 01:55 PM
|
显示全部楼层
|
|
|
|
|
|
|
楼主 |
发表于 6-4-2009 05:00 PM
|
显示全部楼层
请帮我看看我的SETUP ADC 写对吗?
我打算拿完5个ADC READING后SEND那些READING去一个FUNCTION做CALCULATION。
- #include <16F877A.h> // preprocessor directive that selects the chip PIC16F877A
- #device ADC=10 //10bit ADC
- #use delay(clock=20000000)
- #fuses HS,NOWDT,NOPROTECT,NOLVP
- int16 value1, value2, value3, value4, value5;
- void main()
- {
- setup_adc_ports(AN0_AN1_AN2_AN3_AN4);
- setup_adc(ADC_CLOCK_INTERNAL );
- setup_timer_1 (T1_INTERNAL|T1_DIV_BY_1);
- enable_interrupts(GLOBAL);
- enable_interrupts(INT_TIMER1);
-
- while(1){
- set_adc_channel(0);
- delay_us(10);
- value1 = read_adc();
-
- set_adc_channel(1);
- delay_us(10);
- value2 = read_adc();
-
- set_adc_channel(2);
- delay_us(10);
- value3 = read_adc();
-
- set_adc_channel(3);
- delay_us(10);
- value4 = read_adc();
-
- set_adc_channel(4);
- delay_us(10);
- value5 = read_adc();
-
- }
- }
复制代码 |
|
|
|
|
|
|
|
发表于 6-4-2009 07:07 PM
|
显示全部楼层
原帖由 crazybear 于 6-4-2009 05:00 PM 发表
请帮我看看我的SETUP ADC 写对吗?
我打算拿完5个ADC READING后SEND那些READING去一个FUNCTION做CALCULATION。
#include // preprocessor directive that selects the chip PIC16F877A
#device ADC=10 ...
既然你会用proteus,为何不自己试试看, 然后再上来和我们分享呢?
这样的话你会学到更多。servo motor试了吗? |
|
|
|
|
|
|
|
楼主 |
发表于 7-4-2009 02:50 PM
|
显示全部楼层
当我COMPILE时,它出现WARNING说unsigned variable is never less than zero.
unsigned variable就是指我的servo1post, servo2post......
以下是我的PROGRAM。
- #include <16F877A.h> // preprocessor directive that selects the chip PIC16F877A
- #device ADC=10 //10bit ADC
- #use delay(clock=20000000)
- #fuses HS,NOWDT,NOPROTECT,NOLVP
- int16 value1, value2, value3, value4, value5;
- int16 t1high, t2high, t3high, t4high, t5high, tlow;
- int16 t1hvalue, t2hvalue, t3hvalue, t4hvalue, t5hvalue, tlowvalue;
- int servo1post, servo2post, servo3post, servo4post, servo5post;
- void servopostcal(value1, value2, value3, value4, value5)
- {
- servo1post=(((value1-164)/709)*180);
- if(servo1post<0){
- servo1post=0;
- }
- else if(servo1post>180){
- servo1post=180;
- }
- else{
- servo1post=servo1post;
- }
-
- servo2post=(((value2-164)/711)*180);
- if(servo2post<0){
- servo2post=0;
- }
- else if(servo2post>180){
- servo2post=180;
- }
- else{
- servo2post=servo2post;
- }
-
- servo3post=(((value3-156)/714)*180);
- if(servo3post<0){
- servo3post=0;
- }
- else if(servo3post>180){
- servo3post=180;
- }
- else{
- servo3post=servo3post;
- }
-
- servo4post=(((value4-160)/721)*180);
- if(servo4post<0){
- servo4post=0;
- }
- else if(servo4post>180){
- servo4post=180;
- }
- else{
- servo4post=servo4post;
- }
-
- servo5post=(((value5-166)/721)*180);
- if(servo5post<0){
- servo5post=0;
- }
- else if(servo5post>180){
- servo5post=180;
- }
- else{
- servo5post=servo5post;
- }
-
- timervalue(servo1post, servo2post, servo3post, servo4post, servo5post);
- }
- void main()
- {
- 。
- 。
- 。
- 。
- 。
- }
复制代码 因为servo1post的VALUE不会超过255,所以我只是用INT,不是INT16。
那个WARNING会影响的吗?
[ 本帖最后由 crazybear 于 7-4-2009 02:52 PM 编辑 ] |
|
|
|
|
|
|
|
发表于 7-4-2009 05:04 PM
|
显示全部楼层
请问 int 默认是 unsigned 的吗?
如是,那问题应该是在
if(servo1post<0){
servo1post=0;
}
因为 servo1post 永远不会 < 0。 |
|
|
|
|
|
|
|
楼主 |
发表于 7-4-2009 05:51 PM
|
显示全部楼层
还有一个问题就是为什么MCU只那小数点前的号码来乘。
- servo1=((value1-164)/709);
- servo1post=servo1*180;
复制代码
如果我的value1=900那servo1应该有1.03808,可是MCU只拿小数点前的号码来乘180。
就是说servo1post是180,不是186.8547
如果我的value1=500那servo1应该有0.4739,可是MCU只拿0来乘180,而不是0.4739*180。
就是说servo1post是0,不是85.3032 |
|
|
|
|
|
|
|
楼主 |
发表于 7-4-2009 05:57 PM
|
显示全部楼层
原帖由 waiweng83 于 7-4-2009 05:04 PM 发表
请问 int 默认是 unsigned 的吗?
如是,那问题应该是在
if(servo1post
我只是放int罢了,没指定说是unsigned还是signed。
那如果我的servo1post的VALUE是NEGATIVE的话那MCU会怎样处理?
会影响我的PROGRAM的吗?
如果我换去signed int16的话,能不能解决掉那问题? |
|
|
|
|
|
|
|
发表于 8-4-2009 10:53 AM
|
显示全部楼层
原帖由 crazybear 于 7-4-2009 05:57 PM 发表
我只是放int罢了,没指定说是unsigned还是signed。
那如果我的servo1post的VALUE是NEGATIVE的话那MCU会怎样处理?
会影响我的PROGRAM的吗?
如果我换去signed int16的话,能不能解决掉那问题?
你的function有点奇怪。 可以这样写的吗?我没试过
void servopostcal(value1, value2, value3, value4, value5)
value1, value2, value3, value4, value5是你要pass进去的argument.
不过没有declare data type.
同时间也是你的global variable.
直接void掉它吧。改成void servopostcal(void) 看可以吗。
=〉如果我换去signed int16的话,能不能解决掉那问题?
你试比我试来得快。 我还得create project.你就那几个字而已。 |
|
|
|
|
|
|
|
楼主 |
发表于 8-4-2009 12:18 PM
|
显示全部楼层
原帖由 fritlizt 于 8-4-2009 10:53 AM 发表
你的function有点奇怪。 可以这样写的吗?我没试过
void servopostcal(value1, value2, value3, value4, value5)
value1, value2, value3, value4, value5是你要pass进去的argument.
不过没有declare data type ...
Function那里我写的方式是行不通的,所以我直接void掉它(谢谢fritlizt兄的指点)。
现在没有问题了。
我改去 signed int16后,PROGRAM没有出现WARNING了,也RUN到很顺。
至於除那里我还想不到原因,所以我换那FORMULA的方式,就是改去没有用到除法。
就象 (a*(1/b)-(c/b))*180,就没有问题了,那1/b跟c/b是用计算机算了放进去的VALUE。 |
|
|
|
|
|
|
|
发表于 9-4-2009 01:11 PM
|
显示全部楼层
|
|
|
|
|
|
|
楼主 |
发表于 10-4-2009 02:14 AM
|
显示全部楼层
不懂什么事情,我用PROTUES来跑时没有问题,当我BURN进PIC的时候却不能走。
不懂是COMPILER的问题还是我CODE的问题,我SETUP ADC的CODE就在第51#。 |
|
|
|
|
|
|
| |
本周最热论坛帖子
|