搜索
bottom↓
回复: 345

[开源]阿莫蜘蛛进度报告[2015-02-15更新]

  [复制链接]

出0入296汤圆

发表于 2014-8-3 14:59:22 | 显示全部楼层 |阅读模式
本帖最后由 Gorgon_Meducer 于 2015-2-15 22:31 编辑


此贴专门用于阿莫蜘蛛项目进度报告







傻孩子工作室作品

STAFF

   
    Hardware Design           yiming988
    Driver Design                y574924080
    Movement Design         qufuta    sunfulong
    Mechanical Designing     老陈
    Production                   老陈

    Architecture Design Gorgon_Meducer



SPONSOR               

    amobbs, Freescale

ACKNOWLEDGE
   
    Armok
   




- 2015-2-15
    a. 更新Joint类,增加Time属性可以控制动作在指定的时间内精确的完成,大幅度提升蜘蛛舞蹈的时间精度。

    工程模板需要在IAR7.x下编译,单击这里下载:
        特别说明,工程文件在“SpiderRobot_Template\application\template\build_iar”下面

- 2015-2-04
    a. 更新第一版舞蹈
        http://v.youku.com/v_show/id_XODg2MDIwOTA0.html
        讨论在这里
        http://www.amobbs.com/forum.php? ... p;page=1#pid8405770

        感谢sunfulong的精彩作品!

- 2015-1-28
    a. 发布工程模板v1.4a
        - 提供宏模板,用以将指定的动作重复指定的次数,范例:

  1.         ACTION_REPEATE( REF_ACTION(Spider_Go_Front),    //!< target action
  2.                         10,                             //!< times
  3.                         REF_STATE(Spider_Action1));  
复制代码

        重复执行动作(Spider_Go_Front)10次,完成后直接切换到Spider_Action1状态

        - 提供宏模板,用以延时指定的时间(非阻塞延时),范例:

  1.         ACTION_DELAY_MS(4000,                           //!< delay time in ms
  2.                         REF_STATE(Spider_Action2));     //!< next state
复制代码

        延时4000ms,完成后直接切换到Spider_Action2状态

        - 提供脚本模式,并提供范例脚本,演示了重复前进10步,延时4秒,后退10步,前进一步的简单脚本

  1. /*! \brief play action script
  2. *! \param none
  3. *! \return access result
  4. */
  5. bool play_action_script(void)
  6. {
  7.     utilitis_init();

  8.     return NEW_FSM(SpiderPlay, REF_STATE(Spider_Init));
  9. }


  10. IMPLEMENT_FSM(SpiderPlay)

  11.     PRIVATE STATE(Spider_Init) BEGIN
  12.         
  13.         IO_CFG(
  14.             {PB20, IO_WORKS_AS_GPIO, IO_PULL_UP},
  15.         );
  16.         GSP_PORTB.DIR &= ~PB20_MSK;
  17.         
  18.         TRANSFER_TO_STATE(Spider_Wait_for_Trigger);
  19.         EXIT_STATE;
  20.     END


  21.     PRIVATE STATE(Spider_Wait_for_Trigger) BEGIN
  22.         
  23.         //! press key to start
  24.         if (!(GSP_PORTB.IN & PB20_MSK)) {
  25.             TRANSFER_TO_STATE(Spider_Play);
  26.         }

  27.         REFLEXIVE_STATE
  28.     END
  29.     PRIVATE STATE(Spider_Play) BEGIN
  30.         
  31.         ACTION_REPEATE( REF_ACTION(Spider_Go_Front),    //!< target action
  32.                         10,                             //!< times
  33.                         REF_STATE(Spider_Action1));  

  34.         EXIT_STATE;
  35.     END

  36.     PRIVATE STATE(Spider_Action1) BEGIN

  37.         ACTION_DELAY_MS(4000,                           //!< delay time in ms
  38.                         REF_STATE(Spider_Action2));     //!< next state
  39.         EXIT_STATE
  40.     END

  41.     PRIVATE STATE(Spider_Action2) BEGIN

  42.         ACTION_REPEATE(REF_ACTION(Spider_Go_Back), 10, REF_STATE(Spider_Action3));
  43.         EXIT_STATE
  44.     END


  45.     PRIVATE STATE(Spider_Action3) BEGIN

  46.         CALL_ACTION_EX( REF_ACTION(Spider_Go_Front),    //!< target action
  47.                         REF_STATE(Spider_Action4));     //!< next

  48.         EXIT_STATE
  49.     END

  50.     PRIVATE STATE(Spider_Action4) BEGIN

  51.         //! performance complete!!! wait for trigger again
  52.         TRANSFER_TO_STATE(Spider_Wait_for_Trigger);
  53.         EXIT_STATE
  54.     END
  55.    
  56. END_IMPLEMENT_FSM
复制代码


    b. 整理工程架构,提供动作模板和脚本模板
        
        这里actions文件夹保存了所有的单元动作脚本,你可以通过action_template.c作为模板建立新的单元动作。
        步骤如下:
        1. 复制action_template.c,并重新命名为action_xxxxxx.c,这里xxxxx是新单元动作的名字
        2. 利用action_xxxxxxx.c里面的模板完成动作的编写
        3. 再actions.h里面加入新动作的声明,例如:

  1. EXTERN_ACTION(Spider_Go_Front);
  2. EXTERN_ACTION(Spider_Go_Back);
  3. EXTERN_ACTION(Spider_XXXXX);
复制代码


        script.c就是我们编写舞蹈脚本的地方,里面已经放入了Demo的最简单脚本。所有在actions.h里面加入的
        动作在这里都可以直接使用。你可以方便的对某些动作进行重复,加入延时,等等。

    c. 修正了随机偶发的动作无法正确执行的错误
   
    d. 提供控制台模式
        - 用户可以通过控制台绕过上层系统直接对目标舵机进行控制
        

        -用户可以通过控制台对单个joint进行校准
        

        工程模板需要在IAR7.x下编译,单击这里下载:
        特别说明,工程文件在“SpiderRobot_Template\application\template\build_iar”下面

- 2015-1-4
    a. 完成硬件的基本调试。完成基本充放电循环测试。完成基本舵机负载测试。由于买骨架的时候忘记拍螺丝了,
       目前只能干瞪眼,哈哈哈……淘宝卖家说单独买螺丝要15RMB一包,且只能直接用支付宝转账……心头一丝
       疑虑,然后我有问,可否我拍下一个别的东西,然后你改下价格?对方说,我拍什么,仓库出什么……
       所以决定等老陈的蜘蛛骨架。
       感谢yiming988牺牲业余时间完成了新版蜘蛛的驱动电路。感谢老陈对硬件设计做出的指导。
       上图:
      

- 2014-12-29
    a. 拿到了完全重新设计的驱动电路PCB。新的PCB上加入了两并18650电池的可编程充电和保护电路,并
       直接使用mini USB进行充电,去掉了普通的DC电源接口,这样设计的目的是可以充分利用大家积攒在抽屉
       里的各种手机平板充电器,包括各类充电宝。我们在PCB背面加入了一个2并 电池盒的封装,从而将重心
      集中在蜘蛛的中轴上,从而平衡各个关节的受力,并尽可能降低重心,同时解决蜘蛛的供电问题。
      
      新的电路设计由老陈监督,即便如此,错误和 疏漏也可能在所难免,如果大家发现了问题,请及时帮助我们,
      我们有耐心,会坚持一版一版的加以改进。
      

- 2014-11-24
    a. 收到飞思卡尔官方寄回的改进版蜘蛛 V1 Plus 开源项目重启。
        通过这个改进版的蜘蛛,我们发现同样是10RMB的舵机……这品质差别咋就这么大捏~
        飞思卡尔委托第三方“剽窃者剽窃者剽窃者剽窃者剽窃者剽窃者剽窃者剽窃者剽窃者蓝宙”进行了骨架的细小改进,并修正了我们硬件上的错误。非常感谢。另外,这
        舵机……这尼玛舵机……真的是10RMB……真爽啊……哈哈哈哈,推荐莫老大搞一批咱们可以做活动了。

- 2014-9-3
    a. 更新cerebel
        1. 将cerebel抽象出来,剥离了与18舵机系统的强耦合,使其成为32以内舵机系统的通用控制服务模块
            对Joint的初始化和校准部分被从cerebel服务中剥离开来,放在templete.c中。
        2. 在cerebel内部加入了动作缓冲队列,用户通过CEREBEL.Move() 方法传入的Actions可以是栈分配的
           局部变量,也就是说使用ACTION宏的时候,填充的内容不必是编译时刻就确定了的常量,可以是变
           量,或者其它运行时刻经过计算获得的值。通过缓冲队列,用户可以源源不断的加入事先编排好的动
           作序列而不必等待先前加入的动作完成。
        
    b. 更新Joint
        增加了一个接口IsComplete

  1. //! \name joint interface
  2. //! @{
  3. DEF_INTERFACE(i_joint_t)

  4.     bool (*Init)                (joint_t *ptJoint, const joint_cfg_t *ptCFG);
  5.     void (*Finish)              (joint_t *ptJoint);
  6.     bool (*Start)               (joint_t *ptJoint);
  7.     bool (*Stop)                (joint_t *ptJoint);
  8.     const joint_cfg_t *(*Info)  (joint_t *ptJoint);
  9.     bool (*TurnTo)              (joint_t *ptJoint, int32_t nAngle, int32_t nSpeed);
  10.     bool (*TurnToInTime)        (joint_t *ptJoint, int32_t nAngle, uint32_t wTime);
  11.     struct {
  12.         bool    (*Set)          (joint_t *ptJoint, int32_t nAngle);
  13.         int32_t (*Get)          (joint_t *ptJoint);
  14.     } Angle;
  15.     struct {
  16.         bool    (*Set)          (joint_t *ptJoint, int32_t nSpeed);
  17.         int32_t (*Get)          (joint_t *ptJoint);
  18.     } AngularSpeed;

  19.     void                        (*TimerServiceRoutine)(void);

  20.     struct {
  21.         bool (*Register)        (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
  22.         bool (*Unregister)      (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
  23.         bool (*IsComplete)      (joint_t *ptJoint);
  24.     }ActionCompleteEvent;

  25. END_DEF_INTERFACE(i_joint_t)
  26. //! @}
复制代码


    工程模板需要在IAR7.x下编译,单击这里下载:
        特别说明,工程文件在“SpiderRobot_Template\application\template\build_iar”下面

- 2014-8-31
    a. 完成了时间插补算法,更新了Joint算法
    b. 增加了一个运动控制服务cerebel
         通过cerebel我们可以抽象出Action的概念。Action是多个舵机的在某个时刻的运动状态片段,就好比你通过
        摄像机拍摄高速运动的蜘蛛可以获得一系列的照片一样,在这个照片上,每个关节(Joint)都有对应的位置,
        而Action就是这样的照片。cerebel的思路是,我们只要给它提供一系列的照片,并告诉他播放照片的速度,
        cerebel就会自动的按照指定的时间播放动作,例如,下面就是一连串代表前进的动作:

  1.    ACTION_CFG(
  2.         
  3.         ACTION(
  4.             ALL_LEGS_MSK ,
  5.             true,                                   //!< start automatically
  6.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  7.             {
  8.                 [LEFT_FRONT_LEG_0] = 135,
  9.                 [LEFT_MIDDLE_LEG_0] = 180,
  10.                 [LEFT_BACK_LEG_0] = 225,
  11.                 [RIGHT_FRONT_LEG_0] = 45,
  12.                 [RIGHT_MIDDLE_LEG_0] = 0,
  13.                 [RIGHT_BACK_LEG_0] = 315,

  14.                 [LEFT_FRONT_LEG_1] = 200,
  15.                 [LEFT_MIDDLE_LEG_1] = 200,
  16.                 [LEFT_BACK_LEG_1] = 200,
  17.                 [RIGHT_FRONT_LEG_1] = 335,
  18.                 [RIGHT_MIDDLE_LEG_1] = 335,
  19.                 [RIGHT_BACK_LEG_1] = 335,

  20.                 [LEFT_FRONT_LEG_2] = 115,
  21.                 [LEFT_MIDDLE_LEG_2] = 120,
  22.                 [LEFT_BACK_LEG_2] = 115,
  23.                 [RIGHT_FRONT_LEG_2] = 65,
  24.                 [RIGHT_MIDDLE_LEG_2] = 65,
  25.                 [RIGHT_BACK_LEG_2] = 65,
  26.             }
  27.         ),

  28.         ACTION(
  29.             TRI_LEGS_L1_MSK | TRI_LEGS_L0_MSK | TRI_LEGS_R1_MSK | TRI_LEGS_R2_MSK,
  30.             true,                                   //!< start automatically
  31.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  32.             {
  33.                 [LEFT_FRONT_LEG_1] = 225,
  34.                 [LEFT_BACK_LEG_1] = 225,
  35.                 [RIGHT_MIDDLE_LEG_1] = 315,

  36.                 [LEFT_FRONT_LEG_0] = 135,
  37.                 [LEFT_BACK_LEG_0] = 180,
  38.                 [RIGHT_MIDDLE_LEG_0] = 23,

  39.                 [RIGHT_FRONT_LEG_1] = 0,
  40.                 [RIGHT_BACK_LEG_1] = 0,
  41.                 [LEFT_MIDDLE_LEG_1] = 180,

  42.                 [RIGHT_FRONT_LEG_2] = 90,
  43.                 [RIGHT_BACK_LEG_2] = 90,
  44.                 [LEFT_MIDDLE_LEG_2] = 90,
  45.             }
  46.         ),

  47.         ACTION(
  48.             TRI_LEGS_L1_MSK | TRI_LEGS_L2_MSK,
  49.             true,                                   //!< start automatically
  50.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  51.             {
  52.                 [LEFT_FRONT_LEG_1] = 180,
  53.                 [LEFT_BACK_LEG_1] = 180,
  54.                 [RIGHT_MIDDLE_LEG_1] = 0,

  55.                 [LEFT_FRONT_LEG_2] = 90,
  56.                 [LEFT_BACK_LEG_2] = 90,
  57.                 [RIGHT_MIDDLE_LEG_2] = 90,
  58.             }
  59.         ),

  60.         ACTION(
  61.             TRI_LEGS_L0_MSK | TRI_LEGS_R0_MSK,
  62.             true,                                   //!< start automatically
  63.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  64.             {
  65.                 [LEFT_FRONT_LEG_0] = 180 - 23,
  66.                 [LEFT_BACK_LEG_0] = 225,
  67.                 [RIGHT_MIDDLE_LEG_0] = 338,

  68.                
  69.                 [RIGHT_FRONT_LEG_0] = 0,
  70.                 [RIGHT_BACK_LEG_0] = 270,
  71.                 [LEFT_MIDDLE_LEG_0] = 225,
  72.             }
  73.         ),

  74.         ACTION(
  75.             TRI_LEGS_R0_MSK | TRI_LEGS_R1_MSK | TRI_LEGS_R2_MSK,
  76.             true,                                   //!< start automatically
  77.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  78.             {
  79.                 [RIGHT_FRONT_LEG_0] = 45,
  80.                 [RIGHT_BACK_LEG_0] = 350,
  81.                 [LEFT_MIDDLE_LEG_0] = 180 - 23,

  82.                 [RIGHT_FRONT_LEG_1] = 315,
  83.                 [RIGHT_BACK_LEG_1] = 315,
  84.                 [LEFT_MIDDLE_LEG_1] = 200,

  85.                 [RIGHT_FRONT_LEG_2] = 45,
  86.                 [RIGHT_BACK_LEG_2] = 45,
  87.                 [LEFT_MIDDLE_LEG_2] = 135,
  88.             }
  89.         ),


  90.         ACTION(
  91.             TRI_LEGS_R1_MSK | TRI_LEGS_R2_MSK,
  92.             true,                                   //!< start automatically
  93.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  94.             {
  95.                 [RIGHT_FRONT_LEG_1] = 0,
  96.                 [RIGHT_BACK_LEG_1] = 0,
  97.                 [LEFT_MIDDLE_LEG_1] = 180,

  98.                 [RIGHT_FRONT_LEG_2] = 90,
  99.                 [RIGHT_BACK_LEG_2] = 90,
  100.                 [LEFT_MIDDLE_LEG_2] = 90,
  101.             }
  102.         ),

  103.         ACTION(
  104.             TRI_LEGS_R0_MSK | TRI_LEGS_L0_MSK | TRI_LEGS_L1_MSK | TRI_LEGS_L2_MSK,
  105.             true,                                   //!< start automatically
  106.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  107.             {
  108.                 [LEFT_FRONT_LEG_0] = 135,
  109.                 [LEFT_BACK_LEG_0] = 180,
  110.                 [RIGHT_MIDDLE_LEG_0] = 23,

  111.                 [LEFT_FRONT_LEG_1] = 225,
  112.                 [LEFT_BACK_LEG_1] = 225,
  113.                 [RIGHT_MIDDLE_LEG_1] = 315,

  114.                 [LEFT_FRONT_LEG_2] = 135,
  115.                 [LEFT_BACK_LEG_2] = 135,
  116.                 [RIGHT_MIDDLE_LEG_2] = 45,

  117.                 [RIGHT_FRONT_LEG_0] = 0,
  118.                 [RIGHT_BACK_LEG_0] = 315,
  119.                 [LEFT_MIDDLE_LEG_0] = 180 + 22,
  120.             }
  121.         ),

  122.     );
复制代码

        这里ACTION_CFG和ACTION宏是对cerebel的封装,详细封装方法请参考cerebel.h。通过cerebel蜘蛛的运动
        就可以通过“照片”的方式描述下来,而照片与照片之间的部分则由cerebel和joint的时间插补算法自动处理,
        从而产生平滑的运动(运动的快慢由照片与照片之间的时间间隔来控制)。
        这里,我详细介绍下ACTION_CFG和ACTION的使用方法。
       首先,我们必须对整个蜘蛛建立一个统一的数学模型,不然我们就没有一个统一的标准来描述舵机的位置:

   

       根据这个位置,我们首先要完成对舵机的角度映射,这里我们要借助Joint类,Joint初始化中要根据图中标识
       的范围来设置角度的Offset,舵机的实际运动范围等等,下面,我们以右后腿为例,介绍Joint的初始化:
   

  1. JOINT_CFG(
  2.             this.ptJoints[RIGHT_BACK_LEG_0],
  3.             RIGHT_BACK_LEG_0,
  4.             225,                    //!< offset
  5.             0,                     //!< start angle
  6.             180,                    //!< end angle
  7.             180,                    //!< Max Angular Speed
  8.             315,                    //!< Reset Position
  9.             1024,                    //!< K
  10.         );
  11.      
复制代码

        结合上面的图,我们知道右后腿(RIGHT_BACK_LEG_0,这里的0,1,2表示每个腿由身体一次向外的3个关节),
        的运动范围是225°~45°的180度范围。所以,我们将offset配置为225。舵机的实际运动范围就是0°~180°。
        这里,我们还配置了最大的角速度为180°/s,关节复位时候关节的角度315°。关于起始角和终止角,这个实际
        上是用来限定舵机的安全运动范围的,比如虽然舵机可以0°~180°之间运动,但有时候,机械上并不允许这么
        大的运动范围,所以必须要限定一个起始角和终止角。以右后腿为例,为了防止右后腿和右中退产生碰撞,我
        们限定右后腿的实际运动范围是45°~135°(90°范围),修改后的初始化如下:
   

  1. JOINT_CFG(
  2.             this.ptJoints[RIGHT_BACK_LEG_0],
  3.             RIGHT_BACK_LEG_0,
  4.             225,                    //!< offset
  5.             45,                     //!< start angle
  6.             135,                    //!< end angle
  7.             180,                    //!< Max Angular Speed
  8.             315,                    //!< Reset Position
  9.             1024,                    //!< K
  10.         );
  11.      
复制代码

        不幸的是10块钱的舵机线性度太差,所以,我们需要根据安装的实际情况对舵机的角度进行两点矫正,矫正
     方法如下:
     1、首先将起始角和终止角分别设定为0°和180°,并通过复位位置将舵机运动到第一个点,比如270°的点
   

  1. JOINT_CFG(
  2.             this.ptJoints[RIGHT_BACK_LEG_0],
  3.             RIGHT_BACK_LEG_0,
  4.             225,                    //!< offset
  5.             0,                     //!< start angle
  6.             180,                    //!< end angle
  7.             180,                    //!< Max Angular Speed
  8.             270,                    //!< Reset Position
  9.             1024,                    //!< K
  10.         );
  11.      
复制代码

        修正offset使得关节物理上到达270°。我的舵机修正的结果如下:

  1. JOINT_CFG(
  2.             this.ptJoints[RIGHT_BACK_LEG_0],
  3.             RIGHT_BACK_LEG_0,
  4.             222,                    //!< offset
  5.             0,                     //!< start angle
  6.             180,                    //!< end angle
  7.             180,                    //!< Max Angular Speed
  8.             270,                    //!< Reset Position
  9.             1024,                    //!< K
  10.         );
复制代码

        每个舵机都是不同的,你需要自己校准。完成上述步骤后,计算出实际的起始角,并更新起始角和终止角的信
        息:start_angle = first_angle_point - offset。例如我们第一点是270°,offset是222度,那么起始角就是48°
       (48 = 270°- 222),更新配置如下:

  1. JOINT_CFG(
  2.             this.ptJoints[RIGHT_BACK_LEG_0],
  3.             RIGHT_BACK_LEG_0,
  4.             222,                    //!< offset
  5.             48,                     //!< start angle
  6.             180,                    //!< end angle
  7.             180,                    //!< Max Angular Speed
  8.             270,                    //!< Reset Position
  9.             1024,                    //!< K
  10.         );
复制代码

        修改复位值,使关节运动到下一个校准点,比如0°,这个时候,这里的K就发挥作用了,修改比例K来调整实际
        的物理位置,使关节运动到0°。至此,我们就完成了一个关节的校准,我的校准结果如下:

  1. JOINT_CFG(
  2.             this.ptJoints[RIGHT_BACK_LEG_0],
  3.             RIGHT_BACK_LEG_0,
  4.             222,                    //!< offset
  5.             48,                     //!< start angle
  6.             138,                    //!< end angle
  7.             180,                    //!< Max Angular Speed
  8.             315,                    //!< Reset Position
  9.             900,                    //!< K
  10.         );
复制代码

       也许你已经意识到了,这个校准真TMD的坑啊……18个舵机都要这么校准……而且离开量角器……用肉眼看角度有
       多苦逼你可以想象的吧?而且10块钱的舵机还有温票啊……温票啊……漂啊……啊……如果你和我一样处女座,喜
       欢精确——恭喜你……对了对了——忘记给你说了,机械上有个概念叫做回程差……也就是说,你从不同的方向运
      动到同一个角度实际上停下来的位置是不同的……这种情况下,你只能祈祷,舵机不要坏,我不用再换一个……

      到了这里,大约用了4个小时,你就可以完成全部18个舵机的校准。这下我们可以很开心的通过JOINT的接口来
      指挥关节运动到指定的角度了,这里的角度参考图上的坐标系,不用担心实际舵机自己的坐标系,接口如下:

  1. //! \name joint interface
  2. //! @{
  3. DEF_INTERFACE(i_joint_t)

  4.     bool (*Init)                (joint_t *ptJoint, const joint_cfg_t *ptCFG);
  5.     void (*Finish)              (joint_t *ptJoint);
  6.     bool (*Start)               (joint_t *ptJoint);
  7.     bool (*Stop)                (joint_t *ptJoint);
  8.     const joint_cfg_t *(*Info)  (joint_t *ptJoint);
  9.     bool (*TurnTo)              (joint_t *ptJoint, int32_t nAngle, int32_t nSpeed);
  10.     bool (*TurnToInTime)        (joint_t *ptJoint, int32_t nAngle, uint32_t wTime);
  11.     struct {
  12.         bool    (*Set)          (joint_t *ptJoint, int32_t nAngle);
  13.         int32_t (*Get)          (joint_t *ptJoint);
  14.     } Angle;
  15.     struct {
  16.         bool    (*Set)          (joint_t *ptJoint, int32_t nSpeed);
  17.         int32_t (*Get)          (joint_t *ptJoint);
  18.     } AngularSpeed;

  19.     void                        (*TimerServiceRoutine)(void);

  20.     struct {
  21.         bool (*Register)        (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
  22.         bool (*Unregister)      (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
  23.     }ActionCompleteEvent;

  24. END_DEF_INTERFACE(i_joint_t)
  25. //! @}

  26. extern const i_joint_t JOINT;
复制代码

      这里,我们可以直接用JOINT.TurnTo() 方法来将关节以指定的速度运动到指定的绝对角度;也可以使用
      JOINT.TurnToInTime()方法将关节在指定的时间内匀速的运动到指定的角度。这里的时间(wTime)单位
      是1/8秒。写8或者(1<<JOINT_TIME_UNIT_RESOLUTION) 就是1秒。另外,你也可以通过JOINT.Angle.Set()
      来指定关节的角度,通过JOINT.Angle.Get()来实时获取当前的角度。这里需要说明下,以上介绍的方法,
     并不会立即生效,一定要调用JOINT.Start() 让新的设置生效,当然你也可以随时调用JOINT.Stop()来个
      急刹车。
      最后,补充说明下JOINT.TurnTo()是速度插补算法,JOINT.TurnToInTime() 是时间插补算法,认真说来
      时间插补算法更有用,但实际上时间插补算法是建立在速度插补算法之上的,大家可以参考我的源代码。
      这里的速度插补算法产生的是匀速运动,如果你想产生一个S型加减速,可以自己实现一个,我个人觉得
      这对时间插补算法应该是没有影响的——如果你封装的好的话。

      好,言归正传,我们来说说cerebel咋用。首先你要定义18个Joint,然后通过CEREBEL_CFG对他们初始化,
      实际上,我们辛辛苦苦校准好的舵机信息就在cerebel服务的初始化函数里面:


  1. NO_INIT static joint_t s_tJoints[18];
  2. ...
  3. static void spider_init(void)
  4. {
  5.     //! initialize servo service
  6.     SERVO.Init ();
  7.     SERVO.Start ();
  8.    
  9.     //! initialize cerebel layer
  10.     CEREBEL_CFG(
  11.         s_tJoints,
  12.         UBOUND(s_tJoints),
  13.     );
  14.     ...
  15. }
复制代码

        接下来,我们就可以用ACTION_CFG和ACTION来设计舵机动作了,这里就着这两个宏的定义,介绍下各个参数
    的意义:

  1. #define ACTION(__MSK, __AUTO, __TIME, ...)                                      \
  2.         {                                                                       \
  3.             (__MSK),                                                            \
  4.             (__AUTO),                                                           \
  5.             (__TIME),                                                           \
  6.             .nAngles = __VA_ARGS__,                                             \
  7.         }

  8. #define ACTION_CFG(...)                                                         \
  9.         do {                                                                    \
  10.             static cerebel_action_t tActions[] = {__VA_ARGS__};                       \
  11.             CEREBEL.Action.Move(tActions, UBOUND(tActions));                    \
  12.         } while(false)
复制代码

        从代码里很容易知道ACTION_CFG并没有什么神秘的,只是用了C99对可变参数宏的一个技巧,也就是"..."对应
        __VA_ARGS__。这个宏定义了一个静态的照片(Actions)数组,并调用了CEREBEL.Action.Move方法。
        ACTION()有三个参数,分别是:
        __MSK:  用以指定后面的角度配置列表中哪些角度配置是有效的,具体参考template\interface.h里面的joint_msk_t
        __AUTO: 用以指定当前Action是否立即生效(true表示立即生效,false则要调用CEREBEL.Start()才会生效)
        __TIME: 时间插补算法参数,单位是1/8秒。简单说就是多长时间内匀速完成这个Action。
       ... : 这个就是具体的角度配置明细表了,我们看一个例子:

  1.     ACTION_CFG(
  2.         ACTION(
  3.             TRI_LEGS_L1_MSK | TRI_LEGS_L2_MSK,
  4.             true,                                   //!< start automatically
  5.             1 << JOINT_TIME_UNIT_RESOLUTION,        //!< Use 1s
  6.             {
  7.                 [LEFT_FRONT_LEG_1] = 180,
  8.                 [LEFT_BACK_LEG_1] = 180,
  9.                 [RIGHT_MIDDLE_LEG_1] = 0,

  10.                 [LEFT_FRONT_LEG_2] = 90,
  11.                 [LEFT_BACK_LEG_2] = 90,
  12.                 [RIGHT_MIDDLE_LEG_2] = 90,
  13.             }
  14.         ),
  15.     );
复制代码

       这个ACTION涉及到三条腿(左前,左后,右中三条腿组成的三角形,TRI_LEG_Ln, 这里n取0,1,2),动作立即
      生效,1秒钟内匀速完成。后面花括号里面是具体每个关节的角度信息,需要注意的是,这里的关节是与前面的MSK
      相对应的,例如TRI_LEGS_L1_MSK 和TRI_LEGS_L2_MSK的实际内容是:

  1. typedef enum {
  2.     ...
  3.     TRI_LEGS_L1_MSK                 = ( LEFT_FRONT_LEG_1_MSK    |
  4.                                         LEFT_BACK_LEG_1_MSK     |
  5.                                         RIGHT_MIDDLE_LEG_1_MSK  ),

  6.     TRI_LEGS_L2_MSK                 = ( LEFT_FRONT_LEG_2_MSK    |
  7.                                         LEFT_BACK_LEG_2_MSK     |
  8.                                         RIGHT_MIDDLE_LEG_2_MSK  ),
  9.     ...
  10. ) joint_msk_t;
复制代码
     
      OK,到了这里,小伙伴们,平台已经搭建完成,请愉(tong)快(ku)的(de)玩(bei)耍(nue)吧。硬件
      坏了,舵机烧了,我去愉快的画圈圈去了……我靠……^%^*+#€£><#{&$@

     工程模板需要在IAR7.x下编译,单击这里下载:
        特别说明,工程文件在“SpiderRobot_Template\application\template\build_iar”下面

- 2014-8-30
    a. 经过一天的冲刺,终于完成了蜘蛛每一个舵机的校准——真心累啊
        心得:10块钱的舵机,一致性真心差,还有温漂……你让他运动90度(不是运动到90度),不同的舵机会走出
        完全不同的角度来……不得不用了线性补偿算法,这是今天一天的成果……累死人啊……如果大家以后玩这个套
       件,每一套都要自己辛苦校准的。  

  1.     do {
  2.         NO_INIT static joint_t s_tJoint[18];
  3.         NO_INIT static DELEGATE_HANDLE s_tHandler;

  4. //        SERVO.Angle(RIGHT_BACK_LEG_2, 90);

  5.         JOINT_CFG(
  6.             s_tJoint[LEFT_BACK_LEG_2],
  7.             LEFT_BACK_LEG_2,
  8.             355,                    //!< offset
  9.             50,                     //!< start angle
  10.             140,                    //!< end angle
  11.             180,                    //!< Max Angular Speed
  12.             90,                     //!< Reset Position
  13.             680,                    //!< K
  14.         );

  15.         JOINT_CFG(
  16.             s_tJoint[LEFT_MIDDLE_LEG_2],
  17.             LEFT_MIDDLE_LEG_2,
  18.             353,                    //!< offset
  19.             52,                     //!< start angle
  20.             142,                    //!< end angle
  21.             180,                    //!< Max Angular Speed
  22.             90,                     //!< Reset Position
  23.             660,                   //!< K
  24.         );

  25.         JOINT_CFG(
  26.             s_tJoint[LEFT_FRONT_LEG_2],
  27.             LEFT_FRONT_LEG_2,
  28.             353,                    //!< offset
  29.             52,                     //!< start angle
  30.             142,                    //!< end angle
  31.             180,                    //!< Max Angular Speed
  32.             90,                     //!< Reset Position
  33.             680,                   //!< K
  34.         );


  35.         JOINT_CFG(
  36.             s_tJoint[RIGHT_BACK_LEG_2],
  37.             RIGHT_BACK_LEG_2,
  38.             355,                    //!< offset
  39.             50,                     //!< start angle
  40.             140,                    //!< end angle
  41.             180,                    //!< Max Angular Speed
  42.             90,                     //!< Reset Position
  43.             780,                    //!< K
  44.         );

  45.         JOINT_CFG(
  46.             s_tJoint[RIGHT_MIDDLE_LEG_2],
  47.             RIGHT_MIDDLE_LEG_2,
  48.             0,                      //!< offset
  49.             45,                     //!< start angle
  50.             135,                    //!< end angle
  51.             180,                    //!< Max Angular Speed
  52.             90,                     //!< Reset Position
  53.             860,                    //!< K
  54.         );

  55.         JOINT_CFG(
  56.             s_tJoint[RIGHT_FRONT_LEG_2],
  57.             RIGHT_FRONT_LEG_2,
  58.             354,                    //!< offset
  59.             51,                     //!< start angle
  60.             141,                    //!< end angle
  61.             180,                    //!< Max Angular Speed
  62.             90,                     //!< Reset Position
  63.             840,                    //!< K
  64.         );

  65.         JOINT_CFG(
  66.             s_tJoint[RIGHT_BACK_LEG_1],
  67.             RIGHT_BACK_LEG_1,
  68.             275,                    //!< offset
  69.             40,                     //!< start angle
  70.             180,                    //!< end angle
  71.             180,                    //!< Max Angular Speed
  72.             0,                    //!< Reset Position
  73.             1100,                   //!< K
  74.         );

  75.         JOINT_CFG(
  76.             s_tJoint[RIGHT_MIDDLE_LEG_1],
  77.             RIGHT_MIDDLE_LEG_1,
  78.             275,                    //!< offset
  79.             40,                     //!< start angle
  80.             180,                    //!< end angle
  81.             180,                    //!< Max Angular Speed
  82.             0,                    //!< Reset Position
  83.             1024,                   //!< K
  84.         );

  85.         JOINT_CFG(
  86.             s_tJoint[RIGHT_FRONT_LEG_1],
  87.             RIGHT_FRONT_LEG_1,
  88.             260,                    //!< offset
  89.             55,                     //!< start angle
  90.             180,                    //!< end angle
  91.             180,                    //!< Max Angular Speed
  92.             0,                    //!< Reset Position
  93.             970,                   //!< K
  94.         );


  95.         JOINT_CFG(
  96.             s_tJoint[RIGHT_BACK_LEG_0],
  97.             RIGHT_BACK_LEG_0,
  98.             222,                    //!< offset
  99.             48,                     //!< start angle
  100.             138,                    //!< end angle
  101.             180,                    //!< Max Angular Speed
  102.             315,                    //!< Reset Position
  103.             900,                    //!< K
  104.         );

  105.         


  106.         JOINT_CFG(
  107.             s_tJoint[RIGHT_MIDDLE_LEG_0],
  108.             RIGHT_MIDDLE_LEG_0,
  109.             260,                    //!< offset
  110.             55,                     //!< start angle
  111.             145,                    //!< end angle
  112.             180,                    //!< Max Angular Speed
  113.             0,                      //!< Reset Position
  114.             850,                    //!< K
  115.         );


  116.         JOINT_CFG(
  117.             s_tJoint[RIGHT_FRONT_LEG_0],
  118.             RIGHT_FRONT_LEG_0,
  119.             313,                    //!< offset
  120.             47,                     //!< start angle
  121.             137,                    //!< end angle
  122.             180,                    //!< Max Angular Speed
  123.             45,                     //!< Reset Position
  124.             920,                    //!< K
  125.         );


  126.         JOINT_CFG(
  127.             s_tJoint[LEFT_FRONT_LEG_0],
  128.             LEFT_FRONT_LEG_0,
  129.             40,                     //!< offset
  130.             50,                     //!< start angle
  131.             140,                    //!< end angle
  132.             180,                    //!< Max Angular Speed
  133.             135,                    //!< Reset Position
  134.             890,                    //!< K
  135.         );


  136.         JOINT_CFG(
  137.             s_tJoint[LEFT_MIDDLE_LEG_0],
  138.             LEFT_MIDDLE_LEG_0,
  139.             80,                     //!< offset
  140.             55,                     //!< start angle
  141.             145,                    //!< end angle
  142.             180,                    //!< Max Angular Speed
  143.             180,                    //!< Reset Position
  144.             920,                   //!< K
  145.         );

  146.         JOINT_CFG(
  147.             s_tJoint[LEFT_BACK_LEG_0],
  148.             LEFT_BACK_LEG_0,
  149.             142,                    //!< offset
  150.             38,                      //!< start angle
  151.             128,                    //!< end angle
  152.             180,                    //!< Max Angular Speed
  153.             225,                    //!< Reset Position
  154.             1130,                   //!< K
  155.         );

  156.         JOINT_CFG(
  157.             s_tJoint[LEFT_BACK_LEG_1],
  158.             LEFT_BACK_LEG_1,
  159.             105,                    //!< offset
  160.             20,                     //!< start angle
  161.             110,                    //!< end angle
  162.             180,                    //!< Max Angular Speed
  163.             180,                    //!< Reset Position
  164.             1100,                   //!< K
  165.         );

  166.         JOINT_CFG(
  167.             s_tJoint[LEFT_MIDDLE_LEG_1],
  168.             LEFT_MIDDLE_LEG_1,
  169.             90,                     //!< offset
  170.             45,                     //!< start angle
  171.             135,                    //!< end angle
  172.             180,                    //!< Max Angular Speed
  173.             180,                    //!< Reset Position
  174.             950,                   //!< K
  175.         );

  176.         JOINT_CFG(
  177.             s_tJoint[LEFT_FRONT_LEG_1],
  178.             LEFT_FRONT_LEG_1,
  179.             80,                     //!< offset
  180.             55,                     //!< start angle
  181.             145,                    //!< end angle
  182.             180,                    //!< Max Angular Speed
  183.             180,                    //!< Reset Position
  184.             850,                   //!< K
  185.         );

  186.     } while(false);

复制代码

    b. 终于能站起来了……发图庆贺
   
   
明日计划:
    a. 完成运动的时间插补算法——简单说就是给定每个关节目标角度以及多长时间内到达目标角度,算法会自动
       调整角速度使得关节在指定的时间点匀速运动到指定的角度。
    b. 借助时间插补算法,我需要采样至少6组舵舵机的运动角度信息(每组18个舵机的角度信息),然后以播放
       的形式实现前进的动作。对于后退的动作也需要6组这样的采样点。同理,左转,右转,向左横着走,向右
       横着走。愿主保佑我能顺利完成。

- 2014-8-27
    a. 更新工程模板
        > 修正了舵机控制的BUG
        > 增加了一个舵机运动插补和极坐标系映射的服务Joint
            Joint服务是一个运动插补的服务,它使得我们可以让指定的舵机以指定的角速度(度/秒)
            平滑的运动到指定的绝对角度。每个舵机的运动范围是0~180度,但是随着安装位置的不同
            舵机实际上缺乏一个相对同一个坐标系的绝对角度的定位能力。所以,一旦完成了舵机的
            安装,我们就可以借助Joint服务来给舵机指定绝对的角度——当然,舵机实际可以运动的
           角度范围之差不会超过180度。

  1. static void servo_demo(void)
  2. {
  3.     SERVO.Init ();
  4.     SERVO.Start ();

  5.     do {
  6.         NO_INIT static joint_t s_tJoint[18];
  7.         NO_INIT static DELEGATE_HANDLE s_tHandler;
  8.         JOINT_CFG(
  9.             s_tJoint[0],
  10.             LEFT_BACK_LEG_0,
  11.             45,                     //!< offset
  12.             0,                      //!< start angle
  13.             180,                    //!< end angle
  14.             180,                    //!< Max Angular Speed
  15.             135,
  16.         );

  17.     } while(false);

  18. }
复制代码

        这是一个Joint服务的例子,从初始化可以看出,目标舵机是左后腿的第一个关节(LEFT_BACK_LEG_0),
        相对蜘蛛的绝对坐标系,这个关节的实际运动角度范围是(45+0°)~(45+180°),最大允许的角速度
        是180°/s,复位状态下关节的绝对角度是135°。
        这段代码随后在完成初始化后,又命令关节s_tJoint[0]以45°/s的速度平滑的运动到绝对角度45°。

  1.     JOINT.TurnTo(&s_tJoint[0], 45, 45);
复制代码

    Joint服务还提供运动完成事件,用户可以注册事件处理程序(一个事件可以同时注册多个事件处理程序):

  1. //! \brief joint action complete event handler
  2. static fsm_rt_t joint_action_complete_event_handler(void *pArg, void *pParam)
  3. {
  4.     joint_t *ptJoint = (joint_t *)pArg;
  5.     static bool s_bFlag = false;
  6.     if (s_bFlag) {
  7.         JOINT.TurnTo(ptJoint, 45, 45);
  8.     } else {
  9.         JOINT.TurnTo(ptJoint, 135, 45);
  10.     }
  11.     s_bFlag = !s_bFlag;
  12.     return fsm_rt_cpl;
  13. }

  14. static void servo_demo(void)
  15. {
  16.     ...
  17.     do {
  18.         ...
  19.         NO_INIT static DELEGATE_HANDLE s_tHandler;
  20.         ...
  21.         delegate_handler_init(  &s_tHandler,
  22.                                 &joint_action_complete_event_handler,
  23.                                 &s_tJoint[0] );
  24.         JOINT.ActionCompleteEvent.Register(&s_tJoint[0], &s_tHandler);

  25.     } while(false);
  26.     ...
  27. }
复制代码

        这里函数joint_action_complete_event_handler()是s_tJoint[0]的运动完成事件处理函数,我们在这个
        事件处理程序里面用了类似乒乓操作的方式,让关节在45°和135°之间来回运动。注册事件需要借助
       DELEGATE_HANDLE类型的对象的帮助,我们需要先初始化它,告诉他事件处理函数是什么,要附带
       的对象是什么(这里我们把当前的Joint对象作为参数传递给了事件处理程序)。通过register方法,
       我们可以很方便的注册事件处理程序。
        Joint服务需要两个接口的支持,一个是1024分之一秒的定时中断服务,一个是用来设置指定舵机的角度
        的函数。前者我们通过SysTick的中断处理程序来实现,后者我们封装了一个接口适配器:

  1. ISR(SysTick_Handler)
  2. {
  3.     static uint32_t s_wCounter;
  4.     s_wCounter++;
  5.     if (!(s_wCounter & (_BV(10) - 1))) {
  6.         /* run code every 1s here, you can add debug code here*/

  7.     }
  8.     JOINT.TimerServiceRoutine();
  9. }

  10. /*! \note initialize application
  11. *  \param none
  12. *  \retval true hal initialization succeeded.
  13. *  \retval false hal initialization failed
  14. */  
  15. ROOT bool app_init(void)
  16. {

  17.     servo_demo();

  18.     /*! you can put your code here */
  19.     SYSTICK_CFG (
  20.         ENABLE_SYSTICK              |
  21.         SYSTICK_SOURCE_SYSCLK       |
  22.         ENABLE_SYSTICK_INTERRUPT,
  23.         (PM_GET_SYS_CLK() >> 10)
  24.     );

  25.     ENABLE_GLOBAL_INTERRUPT();

  26.     //! start a new task
  27.     return NEW_STATIC_FSM(DemoTask, REF_STATE(Demo_Init));
  28. }



  29. //! \brief interface adapter for joint service
  30. void joint_set_servo(joint_no_t tID, uint32_t wAngle)
  31. {
  32.     SERVO.Angle(tID, wAngle);
  33. }

复制代码

       通过这些接口Joint就能很好的为我们服务了。 下一步我们就可以利用Joint服务为每一个舵机建立一个Joint对象
       从而提供统一的运动插补和坐标系映射服务。这为我们后面的矢量控制算法,以及PC/Andriod脚本控制平台提供
      了准备。
      附上Joint服务的接口定义:

  1. //! \name joint interface
  2. //! @{
  3. DEF_INTERFACE(i_joint_t)

  4.     bool (*Init)            (joint_t *ptJoint, const joint_cfg_t *ptCFG);
  5.     void (*Finish)          (joint_t *ptJoint);

  6.     bool (*TurnTo)(joint_t *ptJoint, int32_t nAngle, int32_t nSpeed);

  7.     struct {
  8.         bool    (*Set)      (joint_t *ptJoint, int32_t nAngle);
  9.         int32_t (*Get)      (joint_t *ptJoint);
  10.     } Angle;
  11.     struct {
  12.         bool    (*Set)      (joint_t *ptJoint, int32_t nSpeed);
  13.         int32_t (*Get)      (joint_t *ptJoint);
  14.     } AngularSpeed;

  15.     void (*TimerServiceRoutine)(void);

  16.     struct {
  17.         bool (*Register)    (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
  18.         bool (*Unregister)  (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
  19.     }ActionCompleteEvent;

  20. END_DEF_INTERFACE(i_joint_t)
  21. //! @}
复制代码


        工程模板需要在IAR7.x下编译,单击这里下载:
        特别说明,工程文件在“SpiderRobot_Template\application\template\build_iar”下面

- 2014-8-20
    a. 更新了工程模板
        > 使用了板载的50MHz外部时钟源
        > 在工程模板中增加了SysTick产生1s中断的例子


  1. ISR(SysTick_Handler)
  2. {
  3.     static uint32_t s_wCounter;
  4.     s_wCounter++;
  5.     if (!(s_wCounter & (_BV(10) - 1))) {
  6.         /* run code every 1s here, you can add debug code here*/

  7.     }
  8. }

  9. /*! \note initialize application
  10. *  \param none
  11. *  \retval true hal initialization succeeded.
  12. *  \retval false hal initialization failed
  13. */  
  14. bool app_init(void)
  15. {
  16.     /*! you can put your code here */
  17.     SYSTICK_CFG (
  18.         ENABLE_SYSTICK              |
  19.         SYSTICK_SOURCE_SYSCLK       |
  20.         ENABLE_SYSTICK_INTERRUPT,
  21.         (PM_GET_SYS_CLK() >> 10)
  22.     );

  23.     ENABLE_GLOBAL_INTERRUPT();

  24.     servo_demo();

  25.     //! start a new task
  26.     return NEW_STATIC_FSM(DemoTask, REF_STATE(Demo_Init));
  27. }
复制代码


        > 在工程模板中增加了三色LED的例子,用以演示状态机调度器的使用

  1. /*============================ MACROS ========================================*/
  2. #define TOP         (0x01FF)

  3. /*============================ MACROFIED FUNCTIONS ===========================*/

  4. #define LED_RED_ON()        do { GSP_PORTB.OUTCLR |= PB22_MSK; } while(false)
  5. #define LED_RED_OFF()       do { GSP_PORTB.OUTSET |= PB22_MSK; } while(false)
  6. #define LED_GREEN_ON()      do { GSP_PORTE.OUTCLR |= PE26_MSK; } while(false)
  7. #define LED_GREEN_OFF()     do { GSP_PORTE.OUTSET |= PE26_MSK; } while(false)
  8. #define LED_BLUE_ON()       do { GSP_PORTB.OUTCLR |= PB21_MSK; } while(false)
  9. #define LED_BLUE_OFF()      do { GSP_PORTB.OUTSET |= PB21_MSK; } while(false)

  10. #define RGB(__R, __G, __B)                                                  \
  11.         do {                                                                \
  12.             set_led_red_gradation(__R);                                     \
  13.             set_led_green_gradation(__G);                                   \
  14.             set_led_blue_gradation(__B);                                    \
  15.         } while(false)

  16. #define LED_LIGHT               3
  17. #define LED_BREATH_SPEED        14

  18. /*! \brief set the 16-level led gradation
  19. *! \param hwLevel gradation
  20. *! \return none
  21. */
  22. static void set_led_red_gradation(uint16_t hwLevel)
  23. {
  24.     static uint16_t s_hwCounter = 0;
  25.    
  26.     if (hwLevel >= s_hwCounter) {
  27.         LED_RED_ON();
  28.     } else {
  29.         LED_RED_OFF();
  30.     }
  31.    
  32.     s_hwCounter++;
  33.     s_hwCounter &= TOP;
  34. }

  35. /*! \brief set the 16-level led gradation
  36. *! \param hwLevel gradation
  37. *! \return none
  38. */
  39. static void set_led_green_gradation(uint16_t hwLevel)
  40. {
  41.     static uint16_t s_hwCounter = 0;
  42.    
  43.     if (hwLevel >= s_hwCounter) {
  44.         LED_GREEN_ON();
  45.     } else {
  46.         LED_GREEN_OFF();
  47.     }
  48.    
  49.     s_hwCounter++;
  50.     s_hwCounter &= TOP;
  51. }


  52. /*! \brief set the 16-level led gradation
  53. *! \param hwLevel gradation
  54. *! \return none
  55. */
  56. static void set_led_blue_gradation(uint16_t hwLevel)
  57. {
  58.     static uint16_t s_hwCounter = 0;
  59.    
  60.     if (hwLevel >= s_hwCounter) {
  61.         LED_BLUE_ON();
  62.     } else {
  63.         LED_BLUE_OFF();
  64.     }
  65.    
  66.     s_hwCounter++;
  67.     s_hwCounter &= TOP;
  68. }

  69. static void breath_led(void)
  70. {
  71.     static uint16_t s_hwCounter = 0;
  72.     static int16_t s_nGrayRed = 0;
  73.     static int16_t s_nGrayGreen = 0;
  74.     static int16_t s_nGrayBlue = 0;

  75.     s_hwCounter++;
  76.     if (!(s_hwCounter & (_BV(LED_BREATH_SPEED)-1))) {
  77.         s_nGrayRed++;
  78.         if (s_nGrayRed == (TOP >> LED_LIGHT)) {
  79.             s_nGrayRed = 0;
  80.         }
  81.     }
  82.     if (!(s_hwCounter & (_BV(LED_BREATH_SPEED+1)-1))) {
  83.         s_nGrayGreen++;
  84.         if (s_nGrayGreen == (TOP >> LED_LIGHT)) {
  85.             s_nGrayGreen = 0;
  86.         }
  87.     }
  88.     if (!(s_hwCounter & (_BV(LED_BREATH_SPEED + 2)-1))) {
  89.         s_nGrayBlue++;
  90.         if (s_nGrayBlue == (TOP >> LED_LIGHT)) {
  91.             s_nGrayBlue = 0;
  92.         }
  93.     }

  94.     RGB(
  95.         ABS(s_nGrayRed - (TOP >> (LED_LIGHT + 1))),
  96.         ABS(s_nGrayGreen - (TOP >> (LED_LIGHT + 1))),
  97.         ABS(s_nGrayBlue - (TOP >> (LED_LIGHT + 1)))
  98.     );
  99. }

  100. /*! state machine implementation */
  101. IMPLEMENT_FSM(DemoTask)

  102.     //! state: Demo_Init
  103.     PRIVATE STATE(Demo_Init) BEGIN
  104.         /*! put your application service code here */
  105.         GSP_PORTB.DIR |= PB22_MSK | PB21_MSK;
  106.         GSP_PORTE.DIR |= PE26_MSK;
  107.         GSP_PORTB.OUTSET = PB22_MSK | PB21_MSK;
  108.         GSP_PORTE.OUTSET = PE26_MSK;

  109.         IO_CFG(
  110.             {PB22,  IO_WORKS_AS_FUNC1},         //!< LED Red
  111.             {PE26,  IO_WORKS_AS_FUNC1},         //!< LED Green
  112.             {PB21,  IO_WORKS_AS_FUNC1},         //!< LED Blue
  113.         );

  114.         TRANSFER_TO_STATE(Demo_Task);
  115.         REFLEXIVE_STATE;
  116.     END

  117.     //! state: Demo Task
  118.     PRIVATE STATE(Demo_Task) BEGIN
  119.         /*! put your none-blocked task code here */
  120.         breath_led();

  121.         REFLEXIVE_STATE;
  122.     END
  123. END_IMPLEMENT_FSM
复制代码


        工程模板需要在IAR7.x下编译,单击这里下载:
        特别说明,工程文件在“SpiderRobot_Template\application\template\build_iar”下面

- 2014-8-16
    a. 完成了硬件调试,只有一个地方需要飞下线,还算不错,谢谢大家为我们的团队成员出谋划策,我们从中学习了很多
    b. 完成了工程模板的第一个公测版Beta1
        我们对舵机进行了封装,提供如下的接口:

  1. //! servo interface
  2. //! \name i_servo_t
  3. //! @{
  4. DEF_INTERFACE (i_servo_t)
  5.     bool    (*Init)     (void);
  6.     bool    (*Deinit)   (void);
  7.     bool    (*Finish)   (void);
  8.     bool    (*Start)    (void);
  9.     bool    (*Angle)    (uint8_t chServoNum,  uint32_t wAngle);
  10. END_DEF_INTERFACE (i_servo_t)
  11. //! @}

  12. /*============================ PROTOTYPES ====================================*/
  13. /*============================ GLOBAL VARIABLES ==============================*/
  14. extern const i_servo_t SERVO;
复制代码

        使用起来也很简单,我们在template.c里面提供了代码范例:

  1. static void servo_demo(void)
  2. {
  3.     SERVO.Init ();
  4.    
  5.     for (uint8_t n = 0; n <= 18; n++) {
  6.         SERVO.Angle (n, 90);
  7.     }
  8.    
  9.     SERVO.Start ();
  10. //    SERVO.Angle (0, 90);
  11. //    SERVO.Angle (1, 0);
  12. //    SERVO.Angle (2, 45);
  13. //    SERVO.Angle (3, 10);   
  14. //    SERVO.Angle (4, 20);
  15. //    SERVO.Angle (5, 10);
  16. //    SERVO.Angle (6, 15);
  17. //    SERVO.Angle (7, 29);   
  18.    
  19. }
复制代码

        我们这次以SDK的形式提供对这个平台的支持,用户将看不到main.c,也看不到main函数,对用户来说,应用所需
    所有入口函数我们都提供了,例如硬件初始化,这个函数是main函数实际调用的第一个函数,其返回值决定了SDK默认
    的一些底层初始化是否要执行,true表示要执行,false表示不再执行。目前默认的底层硬件初始化只是处理了一些时钟
    上的配置,建议这里不要返回false。这个例子里面,我们展示了如何初始化IO,将其配置为对应的PWM功能。关于IO
    的配置,请参考io.h。

  1. /*! \brief hardware initialization
  2. *! \param none
  3. *! \retval true run the default initialization
  4. *! \retval false ignore the default initialization
  5. */
  6. ROOT bool ON_HW_INIT(void)                          
  7. {

  8.     /*! you can put your code here */
  9.     IO_CFG(
  10.         {PC1,   IO_WORKS_AS_FUNC4},
  11.         {PC2,   IO_WORKS_AS_FUNC4},
  12.         {PC3,   IO_WORKS_AS_FUNC4},
  13.         {PC4,   IO_WORKS_AS_FUNC4},

  14.         {PC8,   IO_WORKS_AS_FUNC3},
  15.         {PC9,   IO_WORKS_AS_FUNC3},
  16.         {PC10,  IO_WORKS_AS_FUNC3},
  17.         {PC11,  IO_WORKS_AS_FUNC3},

  18.         {PD0,   IO_WORKS_AS_FUNC4},
  19.         {PD1,   IO_WORKS_AS_FUNC4},
  20.         {PD2,   IO_WORKS_AS_FUNC4},
  21.         {PD3,   IO_WORKS_AS_FUNC4},
  22.         {PD4,   IO_WORKS_AS_FUNC4},
  23.         {PD5,   IO_WORKS_AS_FUNC4},

  24.         {PB18,  IO_WORKS_AS_FUNC3},
  25.         {PB19,  IO_WORKS_AS_FUNC3},

  26.         {PA1,   IO_WORKS_AS_FUNC3},
  27.         {PA2,   IO_WORKS_AS_FUNC3},
  28.     );
  29.    
  30.     return true;
  31. }
复制代码

        用户另外一个要用到的就是应用初始化app_init。这个app_init是main函数完成所有既定的初始化工作以后,调用的
    最后一个初始化函数——也就是用户自己的初始化函数。用户应该在这里做他自己想做的事情,但最后一定要起一个
    状态机任务,就像例子里面提供的那样,不然,离开超级循环,大家怎么活?

  1. //! \brief demo task
  2. STATIC_FSM(DemoTask)
  3.     PRIVATE STATE(Demo_Init);
  4.     PRIVATE STATE(Demo_Task);
  5. END_STATIC_FSM
  6. ...
  7. /*! \note initialize application
  8. *  \param none
  9. *  \retval true hal initialization succeeded.
  10. *  \retval false hal initialization failed
  11. */  
  12. bool app_init(void)
  13. {
  14.     servo_demo();

  15.     //! start a new task
  16.     return NEW_STATIC_FSM(DemoTask, REF_STATE(Demo_Init));
  17. }

  18. /*! state machine implementation */
  19. IMPLEMENT_FSM(DemoTask)

  20.     //! state: Demo_Init
  21.     PRIVATE STATE(Demo_Init) BEGIN
  22.         /*! put your application service code here */

  23.         TRANSFER_TO_STATE(Demo_Task);
  24.         REFLEXIVE_STATE;
  25.     END

  26.     //! state: Demo Task
  27.     PRIVATE STATE(Demo_Task) BEGIN
  28.         /*! put your none-blocked task code here */

  29.         REFLEXIVE_STATE;
  30.     END
  31. END_IMPLEMENT_FSM
复制代码


        工程模板需要在IAR7.x下编译,单击这里下载:
        特别说明,工程文件在“SpiderRobot_Template\application\template\build_iar”下面
   
    c. 由于我最近身体不舒服,在家休养,所以动作调试上耽搁了很多,团队的小伙伴很努力,本周稍后应该会有一个简单的
        演示。

    下一步计划:
    a. 发布工程模板Beta2,提供与此次开源直接相关的蜘蛛运动控制相关的模块及其源代码,修正Beta1发现的问题
    b. 完成基本的动作调试,考虑要不要重新做一版硬件来解决飞线的问题。

- 2014-8-9
    a. 拿到了PCB,组装了下,还蛮好看的,硬件还在调试

    b. 完成了K6x的工程模板,需要IAR7.x的支持,争取下周放出公测版
    c. 初步完成单爪动作和封装


    下一步计划:
    a. 尝试用基本的单爪动作组合出所需的运动,比如,横着爬,前进后退等
    b. 完成硬件调试
    c. 开放工程模板公测

- 2014-8-3
    a. PCB 已经送出去,粘贴原理图如下
        
        特别说明,由于本团队硬件能力非常有限,如果发现任何不合理的地方请及时指出,当前硬件设计未经过严格验证
        不推荐作为参考设计,仅供本项目第一阶段验证和测试使用。
    b. Software Framework 基本完成
        目前暂时基于K20开发了HAL层。已经调试完成。
    c. 蜘蛛的运动控制部分正在测试,近几天可以完成基本的单爪运动状态机封装。

    下一步计划:
    a. 完成蜘蛛运动抽象层的底层部分,即爪子的行为模式封装(比如爪子的弯曲,爪子的收缩),为高层运动模式做准备
      (比如,横着走,比如前后走)
    b. 完成K6x的Software Framework扩展






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2014-8-3 15:24:24 | 显示全部楼层
顶顶 老师!

出0入0汤圆

发表于 2014-8-3 15:29:52 | 显示全部楼层
该顶 该顶

出0入0汤圆

发表于 2014-8-3 15:34:31 | 显示全部楼层
我感觉你的电源口画的有问题

出0入0汤圆

发表于 2014-8-3 15:50:54 | 显示全部楼层
怒赞一个!

出10入210汤圆

发表于 2014-8-3 16:00:25 | 显示全部楼层
学习学习。
我的就用洞洞板搭了。
头像被屏蔽

出0入0汤圆

发表于 2014-8-3 17:07:19 来自手机 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2014-8-3 17:24:28 | 显示全部楼层
走线有点杂,先调功能吧,估计后续要改版。

出0入0汤圆

发表于 2014-8-3 17:53:00 | 显示全部楼层
等着看效果了,哈哈 好期待

出0入10汤圆

发表于 2014-8-3 18:39:25 | 显示全部楼层
顶傻孩子老师~~~

出0入0汤圆

发表于 2014-8-3 21:12:00 | 显示全部楼层
进度好快啊,嫉妒羡慕中,PCB布局很好

出0入0汤圆

发表于 2014-8-3 21:32:13 | 显示全部楼层
上面的固定孔是用螺丝固定吗?实际安装时是否会碰到周围器件?

出0入0汤圆

发表于 2014-8-3 22:11:19 | 显示全部楼层
顶,关注中~~

出100入101汤圆

发表于 2014-8-3 22:16:44 | 显示全部楼层
” 蜘蛛的运动控制”,专业。

出0入0汤圆

发表于 2014-8-3 22:28:10 | 显示全部楼层
赞一个 速度好快

出0入0汤圆

发表于 2014-8-4 08:44:24 | 显示全部楼层
都构架好Framework了 支持

出0入0汤圆

发表于 2014-8-4 08:49:48 | 显示全部楼层
赞赞赞,这就是效率

出0入0汤圆

发表于 2014-8-4 09:24:03 | 显示全部楼层

出0入0汤圆

发表于 2014-8-4 10:09:42 | 显示全部楼层
器件放置挺整齐

出0入45汤圆

发表于 2014-8-4 10:32:58 | 显示全部楼层
1个光耦1rmb。而且这个光耦不是用于隔离作用,只是做个电平转换,这成本太高了
LM2576的不轮layout的体积,还是成本感觉都不是最好的。这个电源部分可以大部分的压缩空间和成本

出0入0汤圆

发表于 2014-8-4 11:09:14 | 显示全部楼层
myiccdream 发表于 2014-8-4 10:32
1个光耦1rmb。而且这个光耦不是用于隔离作用,只是做个电平转换,这成本太高了
LM2576的不轮layout的体积, ...

硬件是我做的,软件工程师做硬件真是有点勉为其难了,您能把更好的方案说的详细一点吗? 光耦在这里确实是隔离用,控制和舵机的地是分开的,只是光耦这么用不知合不合适,更经济的光耦型号有哪些;供电部分2576确实占面积而且贵,我也是手头有这个所以直接用了,您有改进的选型能说一下吗?蜘蛛测试版做完后我可以在第二版上改进

出0入45汤圆

发表于 2014-8-4 11:36:45 | 显示全部楼层
我从原理图上看你所使用的是非隔离的电源(隔离电源可以参考金升阳的模块)。所以我个人觉得这个地方不算严格的隔离。当然您这样使用光耦也没什么问题

假定您的电源输入为12V。那么我用过的电源芯片如下
比如TI的5A的TP5450, 3A的TPS5430
MPS的3A MP2303 MP1495 .  2A的MP1470
或者RT8105

出0入17汤圆

发表于 2014-8-4 11:39:37 | 显示全部楼层
不在乎速度光耦换成TLP281-4GB;4光耦,SOP16封装。
开关电源用TPS54331 ;3.5V 至 28V 输入、3A、570kHz 降压转换器

出0入0汤圆

发表于 2014-8-4 11:54:01 | 显示全部楼层
myiccdream 发表于 2014-8-4 11:36
我从原理图上看你所使用的是非隔离的电源(隔离电源可以参考金升阳的模块)。所以我个人觉得这个地方不算严 ...

嗯 确实不算隔离,用隔离的dcdc模块确实是更好的选择,多谢指点!

出0入0汤圆

发表于 2014-8-4 11:57:09 | 显示全部楼层
hhxb 发表于 2014-8-4 11:39
不在乎速度光耦换成TLP281-4GB;4光耦,SOP16封装。
开关电源用TPS54331 ;3.5V 至 28V 输入、3A、570kHz  ...

查了一下这个光耦的资料,确实是更好的选择, 电源IC也比2576更适合,谢谢!

出0入0汤圆

发表于 2014-8-4 11:59:32 | 显示全部楼层
hhxb 发表于 2014-8-4 11:39
不在乎速度光耦换成TLP281-4GB;4光耦,SOP16封装。
开关电源用TPS54331 ;3.5V 至 28V 输入、3A、570kHz  ...

下一版可能选择金升阳的模块,不过这一版先只能这样将就了

出0入0汤圆

发表于 2014-8-4 12:09:20 | 显示全部楼层
电源没有隔离 光耦没有起到隔离作用  VIN  多少伏?7805有2.5V压降  这个功耗不容忽视。

出0入0汤圆

发表于 2014-8-4 12:26:49 来自手机 | 显示全部楼层
顶,学习学习

出0入0汤圆

发表于 2014-8-4 12:39:44 | 显示全部楼层
如果只是为了完成将3.3V电压到5V 电压转换(非隔离),普通三极管就可胜任,若后面的负载有点重,需要驱动DC 马达之类的负载,则可考用MOS管来兼做电平转换和驱动,供参考。

出0入0汤圆

发表于 2014-8-4 12:50:49 来自手机 | 显示全部楼层
期待这种有质量的代码。喜欢这种分层。

出0入0汤圆

发表于 2014-8-4 13:09:16 | 显示全部楼层
各个接口之间的距离挨的有点近,将来对线插拔的时候可能下不了手。特别是阵列布的3pin的那些接口

出0入0汤圆

发表于 2014-8-4 13:29:54 | 显示全部楼层
电源插座的孔是否有问题?

出0入296汤圆

 楼主| 发表于 2014-8-4 17:42:18 | 显示全部楼层
非常感谢大家!!

出0入0汤圆

发表于 2014-8-4 19:25:19 | 显示全部楼层
顶,学习学习

出0入0汤圆

发表于 2014-8-4 19:46:13 | 显示全部楼层
学习,顶顶

出0入0汤圆

发表于 2014-8-5 09:14:26 | 显示全部楼层
学习,支持傻孩子

出0入0汤圆

发表于 2014-8-5 14:34:30 | 显示全部楼层
傻孩子大大厉害=-=

出0入0汤圆

发表于 2014-8-5 15:52:55 | 显示全部楼层
大力关注傻孩子

出0入0汤圆

发表于 2014-8-5 16:21:42 | 显示全部楼层
yiming988 发表于 2014-8-4 11:09
硬件是我做的,软件工程师做硬件真是有点勉为其难了,您能把更好的方案说的详细一点吗? 光耦在这里确实 ...

GND,PGND,WGND没有隔离开吧,这样即使用光耦也是起不到隔离作用的
光耦可以用TLP185GB,比较便宜 (TLP181似乎停产了)

出0入0汤圆

发表于 2014-8-6 08:57:31 | 显示全部楼层
顶一下、、、

出0入0汤圆

发表于 2014-8-6 11:28:42 | 显示全部楼层
速度好快哈。。。

出0入0汤圆

发表于 2014-8-6 13:15:13 | 显示全部楼层
PCB上,DC电源座的封装没问题吗?

出0入0汤圆

发表于 2014-8-6 13:38:11 | 显示全部楼层
支持,期待大师的软件。

出0入0汤圆

发表于 2014-8-6 21:59:24 | 显示全部楼层
原来傻孩子团队用AD9画板子啊 画的不错啊 这块板子是傻孩子画的?

出0入0汤圆

发表于 2014-8-6 22:18:27 | 显示全部楼层
赞LZ的 快速度

出0入0汤圆

发表于 2014-8-7 08:38:05 | 显示全部楼层
效率真高,赞

出0入0汤圆

发表于 2014-8-7 08:48:49 | 显示全部楼层
期待早日成功

出0入0汤圆

发表于 2014-8-7 16:45:33 | 显示全部楼层
关注中,电源器件后面的建议不错

出0入296汤圆

 楼主| 发表于 2014-8-9 12:49:36 | 显示全部楼层
sbk100 发表于 2014-8-6 21:59
原来傻孩子团队用AD9画板子啊 画的不错啊 这块板子是傻孩子画的?

我不懂画板子。

出0入0汤圆

发表于 2014-8-9 13:32:02 | 显示全部楼层
很多东西都不会,只能默默支持了。。。

出0入8汤圆

发表于 2014-8-9 16:49:08 | 显示全部楼层
支持,期待最后结果!~~~

出0入0汤圆

发表于 2014-8-9 23:18:21 | 显示全部楼层
sbk100 发表于 2014-8-6 21:59
原来傻孩子团队用AD9画板子啊 画的不错啊 这块板子是傻孩子画的?

板子是傻孩子老师委托我画的,我本意是将舵机电源与核心板电源隔离,仓促画板竟然把PGND和GND连起来了,不过供测试用还是没有问题的。

突然感觉,我越来越像一个软件工程师了(硬件已经渐行渐远  默哀,撒花。。。)

出0入296汤圆

 楼主| 发表于 2014-8-9 23:33:02 | 显示全部楼层
进度更新了

出0入0汤圆

发表于 2014-8-9 23:45:06 | 显示全部楼层
好厉害好礼哈啊

出0入0汤圆

发表于 2014-8-9 23:45:33 | 显示全部楼层
傻孩子好厉害,赶紧做出来看看啥样

出0入0汤圆

发表于 2014-8-10 20:28:21 | 显示全部楼层
进度还是挺快的

出0入0汤圆

发表于 2014-8-10 21:41:09 来自手机 | 显示全部楼层
动作好快,顶个

出0入0汤圆

发表于 2014-8-11 19:02:51 | 显示全部楼层
大神啊          佩服

出0入0汤圆

发表于 2014-8-11 19:54:00 | 显示全部楼层
好东西,期待成品

出0入0汤圆

发表于 2014-8-12 10:29:39 | 显示全部楼层
想加入 不知如何才能

出0入0汤圆

发表于 2014-8-12 23:43:35 | 显示全部楼层
期待后续进展

出0入0汤圆

发表于 2014-8-13 10:59:19 | 显示全部楼层
看了大家的的评论  学到了不少
楼主速度很快啊

出0入0汤圆

发表于 2014-8-14 11:12:06 | 显示全部楼层
顶一下、、、

出0入0汤圆

发表于 2014-8-14 13:25:56 | 显示全部楼层
不错啊,以后可以改进成家庭服务机器人,满屋子的爬呀爬。

出0入0汤圆

发表于 2014-8-15 17:14:21 | 显示全部楼层
哇,期待下一步动作

出0入296汤圆

 楼主| 发表于 2014-8-16 23:31:27 | 显示全部楼层
更新了工程模板的Beta1。

出0入0汤圆

发表于 2014-8-17 00:02:24 来自手机 | 显示全部楼层
期待,大工程啊

出60入0汤圆

发表于 2014-8-17 00:02:49 来自手机 | 显示全部楼层
顶顶,珍惜辛勤劳动成果

出0入0汤圆

发表于 2014-8-17 00:19:40 | 显示全部楼层
老师注意身体呀。。
头像被屏蔽

出0入0汤圆

发表于 2014-8-17 02:36:33 来自手机 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2014-8-17 09:42:09 来自手机 | 显示全部楼层
不错不错

出0入0汤圆

发表于 2014-8-17 09:46:28 | 显示全部楼层
工程模板棒极了,又跟着学着不少东西

出0入0汤圆

发表于 2014-8-17 18:56:31 | 显示全部楼层
工程模板不错,学习了
同时楼主多注意身体呀!

出0入0汤圆

发表于 2014-8-19 12:58:27 | 显示全部楼层
再次顶一个

出0入0汤圆

发表于 2014-8-19 17:18:59 | 显示全部楼层
这个不错哈。。。。

出0入0汤圆

发表于 2014-8-19 17:59:30 | 显示全部楼层
不错,继续保持关注中···

出0入296汤圆

 楼主| 发表于 2014-8-20 16:37:43 | 显示全部楼层
更新了,增加了GPIO操作的例子,使用外部50MHz精确时钟,增加了SysTick的使用范例

出0入0汤圆

发表于 2014-8-20 17:08:14 | 显示全部楼层
赶上更新了,看看

出0入0汤圆

发表于 2014-8-20 17:33:40 | 显示全部楼层
更新蛮快的嘛期待。。。。。。。。。。。。

出0入0汤圆

发表于 2014-8-20 18:12:48 | 显示全部楼层
来学习了

出0入0汤圆

发表于 2014-8-20 20:08:36 | 显示全部楼层

老师能讲一下,三色灯驱动程序吗?
还有宏定义为什么要do while 结构,不是直接一个语句呢?

出0入0汤圆

发表于 2014-8-20 20:42:08 来自手机 | 显示全部楼层
三色LED驱动不错,学习了

出0入0汤圆

发表于 2014-8-21 00:37:48 | 显示全部楼层
进度很快啊,期待大神的程序,从傻孩子的文章里学到很多。

出0入0汤圆

发表于 2014-8-21 08:40:50 | 显示全部楼层
傻孩子大牛一个啊,学习

出0入296汤圆

 楼主| 发表于 2014-8-21 11:41:41 | 显示全部楼层
Pupil 发表于 2014-8-20 20:08
老师能讲一下,三色灯驱动程序吗?
还有宏定义为什么要do while 结构,不是直接一个语句呢?  ...

可以避免被宏进行文字替换的时候由于上下文的原因产生歧义。

出0入0汤圆

发表于 2014-8-21 11:52:53 | 显示全部楼层
更新真快啊,赞一个,不久就能看到作品了

出0入0汤圆

发表于 2014-8-21 12:32:26 | 显示全部楼层
不错。。。。。。。。。。。。。

出0入0汤圆

发表于 2014-8-22 12:24:36 | 显示全部楼层
学习楼主的资料

出0入0汤圆

发表于 2014-8-22 12:58:39 | 显示全部楼层
封装的太严实反而感觉不好用了!

出0入296汤圆

 楼主| 发表于 2014-8-22 13:21:32 | 显示全部楼层
jlhgold 发表于 2014-8-22 12:58
封装的太严实反而感觉不好用了!


蜘蛛平台专注的是运动控制,至于怎么发生PWM,这是大家都知道的东西,没必要增加编译的难度。
专注于应用实现而不是驱动开发,这才是做项目应有的态度。

出0入0汤圆

发表于 2014-8-22 13:33:36 | 显示全部楼层
支持一下

出0入0汤圆

发表于 2014-8-22 19:15:07 | 显示全部楼层
Gorgon_Meducer 发表于 2014-8-22 13:21
蜘蛛平台专注的是运动控制,至于怎么发生PWM,这是大家都知道的东西,没必要增加编译的难度。
专注于应用 ...

那为啥要把main函数封装掉?如果PWM是中断自动产生的 何必在意买了怎么写 只要告知必须要假如某个初始化函数即可

出0入0汤圆

发表于 2014-8-22 20:17:19 | 显示全部楼层
感觉有一个团队能够合作的很好,那么效率会非常高的

出0入0汤圆

发表于 2014-8-22 21:30:49 | 显示全部楼层
大牛,每个地方都有可以学习的内容!

出0入296汤圆

 楼主| 发表于 2014-8-23 00:54:11 | 显示全部楼层
jlhgold 发表于 2014-8-22 19:15
那为啥要把main函数封装掉?如果PWM是中断自动产生的 何必在意买了怎么写 只要告知必须要假如某个初始化 ...

PWM硬件产生,而且和上层无关,没有使用中断。PWM的初始化函数就是SERVO.Init()
不提供 main是一种格式上的规范。用户并没有损失任何灵活性和可能性。由于main里面
有一些固定的结构,为了避免被破坏导致系统服务失效,所以采取了这种结构。其实如果
你非常介意这个问题,同时又不想用调度器,直接把app_init当作main函数就可以了,你
可以在里面加上超级循环。

出0入0汤圆

发表于 2014-8-23 14:50:37 | 显示全部楼层
我是来向高手学习的

出0入0汤圆

发表于 2014-8-23 15:37:54 | 显示全部楼层
顶顶                        

出0入17汤圆

发表于 2014-8-23 17:27:37 | 显示全部楼层
进来学习一下软件思路。
把灵活的变机械,把机械的变灵活。

出0入0汤圆

发表于 2014-8-23 20:08:14 | 显示全部楼层
程序写的太牛了,羡慕中

出0入0汤圆

发表于 2014-8-24 08:06:33 | 显示全部楼层
状态机编程,架构搭的不错!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 21:02

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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