佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

楼主: crazybear

要如何同时控制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 编辑 ]
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 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 | 显示全部楼层
原帖由 fritlizt 于 5-4-2009 10:01 PM 发表


用别个port.port a default给adc.你没有configure 成digital.当然不能。刚看你之前的code.也是用porta.我就不知道为什么可以了。 lol
很靠近了。
现在你generate 1.5ms high, 18.5ms low.
delay 1second,
1m ...


做到了。。

  1. #include <16F877A.h>                           
  2. #use delay(clock=20000000)
  3. #fuses HS,NOWDT,NOPROTECT,NOLVP

  4. int16 highvalue, lowvalue;

  5. void main()
  6. {   setup_timer_1 (T1_INTERNAL|T1_DIV_BY_4);
  7.    enable_interrupts(GLOBAL);
  8.    enable_interrupts(INT_TIMER1);
  9.    set_timer1(60536);         //interrupt at 1ms
  10.    output_high(PIN_B0);
  11.    
  12.    while(1)
  13.    {
  14.    highvalue=63661;            //1.5ms
  15.    lowvalue=42411;             //18.5ms
  16.    delay_ms(1000);
  17.    
  18.    highvalue=64286;            //1ms
  19.    lowvalue=41786;             //19ms
  20.    delay_ms(1000);
  21.    
  22.    highvalue=63036;            //2ms
  23.    lowvalue=43036;             //18ms
  24.    delay_ms(1000);
  25.    }
  26. }


  27. #INT_TIMER1
  28. void timer1_interrupt ()
  29. {
  30.    if(input_state(PIN_B0))
  31.    {
  32.    output_low(PIN_B0);
  33.    set_timer1(lowvalue);
  34.    }
  35.    else
  36.    {
  37.    output_high(PIN_B0);
  38.    set_timer1(highvalue);
  39.    }
  40.    clear_interrupt(INT_TIMER1);
  41. }
复制代码


2ms

1ms

1.5ms

评分

参与人数 1积分 +10 收起 理由
fritlizt + 10

查看全部评分

回复

使用道具 举报

发表于 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。。。

  1. #include <16F877A.h>                           
  2. #use delay(clock=20000000)
  3. #fuses HS,NOWDT,NOPROTECT,NOLVP

  4. int16 highvalue, lowvalue;

  5. void main()
  6. {  
  7.    SET_TRIS_B( 0x00 );
  8.    setup_timer_1 (T1_INTERNAL|T1_DIV_BY_4);
  9.    enable_interrupts(GLOBAL);
  10.    enable_interrupts(INT_TIMER1);
  11.    
  12.    while(1)
  13.    {
  14.    highvalue = 63661;            //1.5ms
  15.    lowvalue = 49911;             //12.5ms
  16.    }

  17. }


  18. #INT_TIMER1
  19. void timer1_interrupt ()
  20. {
  21.    if(input_state(PIN_B0))
  22.    {
  23.    output_low(PIN_B0);
  24.    output_high(PIN_B1);
  25.    set_timer1(highvalue);
  26.    }
  27.    
  28.    else if (input_state(PIN_B1))
  29.    {
  30.    output_low(PIN_B1);
  31.    output_high(PIN_B2);
  32.    set_timer1(highvalue);
  33.    }
  34.    
  35.    else if (input_state(PIN_B2))
  36.    {
  37.    output_low(PIN_B2);
  38.    output_high(PIN_B3);
  39.    set_timer1(highvalue);
  40.    }
  41.    
  42.    else if (input_state(PIN_B3))
  43.    {
  44.    output_low(PIN_B3);
  45.    output_high(PIN_B4);
  46.    set_timer1(highvalue);
  47.    }
  48.    
  49.    else if (input_state(PIN_B4))
  50.    {
  51.    output_low(PIN_B4);
  52.    set_timer1(lowvalue);            
  53.    }
  54.    
  55.    else
  56.    {
  57.    output_high(PIN_B0);
  58.    set_timer1(highvalue);
  59.    }
  60.    
  61.    clear_interrupt(INT_TIMER1);
  62. }
复制代码


回复

使用道具 举报

发表于 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 编辑 ]
回复

使用道具 举报

Follow Us
 楼主| 发表于 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 跑掉,影响并不大。
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 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 | 显示全部楼层
原帖由 crazybear 于 6-4-2009 11:53 AM 发表


有人有用真的SERVO MOTOR试过吗?
当PERIOD跑掉的事后,SERVO MOTOR的反应会怎样的?


program你有了。 你可以自己试试看。当跑掉1个period会发生什么情况
能的话哦拍video youtube上来, 效果很更好。别人也可以参考参考。
回复

使用道具 举报

 楼主| 发表于 6-4-2009 05:00 PM | 显示全部楼层
请帮我看看我的SETUP ADC 写对吗?
我打算拿完5个ADC READING后SEND那些READING去一个FUNCTION做CALCULATION。

  1. #include <16F877A.h> // preprocessor directive that selects the chip PIC16F877A
  2. #device ADC=10                  //10bit ADC
  3. #use delay(clock=20000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP  

  5. int16 value1, value2, value3, value4, value5;


  6. void main()
  7. {

  8.    setup_adc_ports(AN0_AN1_AN2_AN3_AN4);
  9.    setup_adc(ADC_CLOCK_INTERNAL );

  10.    setup_timer_1 (T1_INTERNAL|T1_DIV_BY_1);
  11.    enable_interrupts(GLOBAL);
  12.    enable_interrupts(INT_TIMER1);
  13.    
  14.    while(1){
  15.    set_adc_channel(0);
  16.    delay_us(10);
  17.    value1 = read_adc();
  18.    
  19.    set_adc_channel(1);
  20.    delay_us(10);
  21.    value2 = read_adc();
  22.    
  23.    set_adc_channel(2);
  24.    delay_us(10);
  25.    value3 = read_adc();
  26.    
  27.    set_adc_channel(3);
  28.    delay_us(10);
  29.    value4 = read_adc();
  30.    
  31.    set_adc_channel(4);
  32.    delay_us(10);
  33.    value5 = read_adc();
  34.       
  35.    }

  36. }
复制代码
回复

使用道具 举报

发表于 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。

  1. #include <16F877A.h> // preprocessor directive that selects the chip PIC16F877A
  2. #device ADC=10                  //10bit ADC
  3. #use delay(clock=20000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP  

  5. int16 value1, value2, value3, value4, value5;
  6. int16 t1high, t2high, t3high, t4high, t5high, tlow;
  7. int16 t1hvalue, t2hvalue, t3hvalue, t4hvalue, t5hvalue, tlowvalue;
  8. int servo1post, servo2post, servo3post, servo4post, servo5post;
  9. void servopostcal(value1, value2, value3, value4, value5)
  10. {
  11.       servo1post=(((value1-164)/709)*180);
  12.       if(servo1post<0){
  13.       servo1post=0;
  14.       }
  15.       else if(servo1post>180){
  16.       servo1post=180;
  17.       }
  18.       else{
  19.       servo1post=servo1post;
  20.       }
  21.       
  22.       servo2post=(((value2-164)/711)*180);
  23.       if(servo2post<0){
  24.       servo2post=0;
  25.       }
  26.       else if(servo2post>180){
  27.       servo2post=180;
  28.       }
  29.       else{
  30.       servo2post=servo2post;
  31.       }
  32.       
  33.       servo3post=(((value3-156)/714)*180);
  34.       if(servo3post<0){
  35.       servo3post=0;
  36.       }
  37.       else if(servo3post>180){
  38.       servo3post=180;
  39.       }
  40.       else{
  41.       servo3post=servo3post;
  42.       }
  43.       
  44.       servo4post=(((value4-160)/721)*180);
  45.       if(servo4post<0){
  46.       servo4post=0;
  47.       }
  48.       else if(servo4post>180){
  49.       servo4post=180;
  50.       }
  51.       else{
  52.       servo4post=servo4post;
  53.       }
  54.       
  55.       servo5post=(((value5-166)/721)*180);
  56.       if(servo5post<0){
  57.       servo5post=0;
  58.       }
  59.       else if(servo5post>180){
  60.       servo5post=180;
  61.       }
  62.       else{
  63.       servo5post=servo5post;
  64.       }
  65.       
  66.       timervalue(servo1post, servo2post, servo3post, servo4post, servo5post);
  67. }

  68. void main()
  69. {





  70. }
复制代码
因为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只那小数点前的号码来乘。

  1.       servo1=((value1-164)/709);
  2.       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的话,能不能解决掉那问题?
回复

使用道具 举报


ADVERTISEMENT

发表于 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 | 显示全部楼层
原帖由 crazybear 于 8-4-2009 12:18 PM 发表


Function那里我写的方式是行不通的,所以我直接void掉它(谢谢fritlizt兄的指点)。
现在没有问题了。

我改去 signed int16后,PROGRAM没有出现WARNING了,也RUN到很顺。

至於除那里我还想不到原因,所以我 ...


project做完后就上来update 一下。
1. project description: 你的目标和用途
2.你面对到什么问题。 :servo control, servo post calculation等
3.什么方法解决。


希望你以后回流cari.让cari 电子hot一点。 呵呵呵呵。
回复

使用道具 举报

 楼主| 发表于 10-4-2009 02:14 AM | 显示全部楼层
不懂什么事情,我用PROTUES来跑时没有问题,当我BURN进PIC的时候却不能走。
不懂是COMPILER的问题还是我CODE的问题,我SETUP ADC的CODE就在第51#。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 29-3-2024 07:07 PM , Processed in 0.074014 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表