Gorgon_Meducer 发表于 2014-8-3 14:59:22

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

本帖最后由 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?mod=viewthread&tid=5614299&page=1#pid8405770

      感谢sunfulong的精彩作品!

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

      ACTION_REPEATE( REF_ACTION(Spider_Go_Front),    //!< target action
                        10,                           //!< times
                        REF_STATE(Spider_Action1));

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

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

      ACTION_DELAY_MS(4000,                           //!< delay time in ms
                        REF_STATE(Spider_Action2));   //!< next state

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

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

/*! \brief play action script
*! \param none
*! \return access result
*/
bool play_action_script(void)
{
    utilitis_init();

    return NEW_FSM(SpiderPlay, REF_STATE(Spider_Init));
}


IMPLEMENT_FSM(SpiderPlay)

    PRIVATE STATE(Spider_Init) BEGIN
      
      IO_CFG(
            {PB20, IO_WORKS_AS_GPIO, IO_PULL_UP},
      );
      GSP_PORTB.DIR &= ~PB20_MSK;
      
      TRANSFER_TO_STATE(Spider_Wait_for_Trigger);
      EXIT_STATE;
    END


    PRIVATE STATE(Spider_Wait_for_Trigger) BEGIN
      
      //! press key to start
      if (!(GSP_PORTB.IN & PB20_MSK)) {
            TRANSFER_TO_STATE(Spider_Play);
      }

      REFLEXIVE_STATE
    END
    PRIVATE STATE(Spider_Play) BEGIN
      
      ACTION_REPEATE( REF_ACTION(Spider_Go_Front),    //!< target action
                        10,                           //!< times
                        REF_STATE(Spider_Action1));

      EXIT_STATE;
    END

    PRIVATE STATE(Spider_Action1) BEGIN

      ACTION_DELAY_MS(4000,                           //!< delay time in ms
                        REF_STATE(Spider_Action2));   //!< next state
      EXIT_STATE
    END

    PRIVATE STATE(Spider_Action2) BEGIN

      ACTION_REPEATE(REF_ACTION(Spider_Go_Back), 10, REF_STATE(Spider_Action3));
      EXIT_STATE
    END


    PRIVATE STATE(Spider_Action3) BEGIN

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

      EXIT_STATE
    END

    PRIVATE STATE(Spider_Action4) BEGIN

      //! performance complete!!! wait for trigger again
      TRANSFER_TO_STATE(Spider_Wait_for_Trigger);
      EXIT_STATE
    END
   
END_IMPLEMENT_FSM


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

EXTERN_ACTION(Spider_Go_Front);
EXTERN_ACTION(Spider_Go_Back);
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

//! \name joint interface
//! @{
DEF_INTERFACE(i_joint_t)

    bool (*Init)                (joint_t *ptJoint, const joint_cfg_t *ptCFG);
    void (*Finish)            (joint_t *ptJoint);
    bool (*Start)               (joint_t *ptJoint);
    bool (*Stop)                (joint_t *ptJoint);
    const joint_cfg_t *(*Info)(joint_t *ptJoint);
    bool (*TurnTo)            (joint_t *ptJoint, int32_t nAngle, int32_t nSpeed);
    bool (*TurnToInTime)      (joint_t *ptJoint, int32_t nAngle, uint32_t wTime);
    struct {
      bool    (*Set)          (joint_t *ptJoint, int32_t nAngle);
      int32_t (*Get)          (joint_t *ptJoint);
    } Angle;
    struct {
      bool    (*Set)          (joint_t *ptJoint, int32_t nSpeed);
      int32_t (*Get)          (joint_t *ptJoint);
    } AngularSpeed;

    void                        (*TimerServiceRoutine)(void);

    struct {
      bool (*Register)      (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
      bool (*Unregister)      (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
      bool (*IsComplete)      (joint_t *ptJoint);
    }ActionCompleteEvent;

END_DEF_INTERFACE(i_joint_t)
//! @}


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

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

   ACTION_CFG(
      
      ACTION(
            ALL_LEGS_MSK ,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 135,
                = 180,
                = 225,
                = 45,
                = 0,
                = 315,

                = 200,
                = 200,
                = 200,
                = 335,
                = 335,
                = 335,

                = 115,
                = 120,
                = 115,
                = 65,
                = 65,
                = 65,
            }
      ),

      ACTION(
            TRI_LEGS_L1_MSK | TRI_LEGS_L0_MSK | TRI_LEGS_R1_MSK | TRI_LEGS_R2_MSK,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 225,
                = 225,
                = 315,

                = 135,
                = 180,
                = 23,

                = 0,
                = 0,
                = 180,

                = 90,
                = 90,
                = 90,
            }
      ),

      ACTION(
            TRI_LEGS_L1_MSK | TRI_LEGS_L2_MSK,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 180,
                = 180,
                = 0,

                = 90,
                = 90,
                = 90,
            }
      ),

      ACTION(
            TRI_LEGS_L0_MSK | TRI_LEGS_R0_MSK,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 180 - 23,
                = 225,
                = 338,

               
                = 0,
                = 270,
                = 225,
            }
      ),

      ACTION(
            TRI_LEGS_R0_MSK | TRI_LEGS_R1_MSK | TRI_LEGS_R2_MSK,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 45,
                = 350,
                = 180 - 23,

                = 315,
                = 315,
                = 200,

                = 45,
                = 45,
                = 135,
            }
      ),


      ACTION(
            TRI_LEGS_R1_MSK | TRI_LEGS_R2_MSK,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 0,
                = 0,
                = 180,

                = 90,
                = 90,
                = 90,
            }
      ),

      ACTION(
            TRI_LEGS_R0_MSK | TRI_LEGS_L0_MSK | TRI_LEGS_L1_MSK | TRI_LEGS_L2_MSK,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 135,
                = 180,
                = 23,

                = 225,
                = 225,
                = 315,

                = 135,
                = 135,
                = 45,

                = 0,
                = 315,
                = 180 + 22,
            }
      ),

    );

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

   

       根据这个位置,我们首先要完成对舵机的角度映射,这里我们要借助Joint类,Joint初始化中要根据图中标识
       的范围来设置角度的Offset,舵机的实际运动范围等等,下面,我们以右后腿为例,介绍Joint的初始化:
   
JOINT_CFG(
            this.ptJoints,
            RIGHT_BACK_LEG_0,
            225,                  //!< offset
            0,                     //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            315,                  //!< Reset Position
            1024,                  //!< K
      );
   
      结合上面的图,我们知道右后腿(RIGHT_BACK_LEG_0,这里的0,1,2表示每个腿由身体一次向外的3个关节),
      的运动范围是225°~45°的180度范围。所以,我们将offset配置为225。舵机的实际运动范围就是0°~180°。
      这里,我们还配置了最大的角速度为180°/s,关节复位时候关节的角度315°。关于起始角和终止角,这个实际
      上是用来限定舵机的安全运动范围的,比如虽然舵机可以0°~180°之间运动,但有时候,机械上并不允许这么
      大的运动范围,所以必须要限定一个起始角和终止角。以右后腿为例,为了防止右后腿和右中退产生碰撞,我
      们限定右后腿的实际运动范围是45°~135°(90°范围),修改后的初始化如下:
   
JOINT_CFG(
            this.ptJoints,
            RIGHT_BACK_LEG_0,
            225,                  //!< offset
            45,                     //!< start angle
            135,                  //!< end angle
            180,                  //!< Max Angular Speed
            315,                  //!< Reset Position
            1024,                  //!< K
      );
   
      不幸的是10块钱的舵机线性度太差,所以,我们需要根据安装的实际情况对舵机的角度进行两点矫正,矫正
   方法如下:
   1、首先将起始角和终止角分别设定为0°和180°,并通过复位位置将舵机运动到第一个点,比如270°的点
   
JOINT_CFG(
            this.ptJoints,
            RIGHT_BACK_LEG_0,
            225,                  //!< offset
            0,                     //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            270,                  //!< Reset Position
            1024,                  //!< K
      );
   
      修正offset使得关节物理上到达270°。我的舵机修正的结果如下:

JOINT_CFG(
            this.ptJoints,
            RIGHT_BACK_LEG_0,
            222,                  //!< offset
            0,                     //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            270,                  //!< Reset Position
            1024,                  //!< K
      );

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

JOINT_CFG(
            this.ptJoints,
            RIGHT_BACK_LEG_0,
            222,                  //!< offset
            48,                     //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            270,                  //!< Reset Position
            1024,                  //!< K
      );

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

JOINT_CFG(
            this.ptJoints,
            RIGHT_BACK_LEG_0,
            222,                  //!< offset
            48,                     //!< start angle
            138,                  //!< end angle
            180,                  //!< Max Angular Speed
            315,                  //!< Reset Position
            900,                  //!< K
      );

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

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

//! \name joint interface
//! @{
DEF_INTERFACE(i_joint_t)

    bool (*Init)                (joint_t *ptJoint, const joint_cfg_t *ptCFG);
    void (*Finish)            (joint_t *ptJoint);
    bool (*Start)               (joint_t *ptJoint);
    bool (*Stop)                (joint_t *ptJoint);
    const joint_cfg_t *(*Info)(joint_t *ptJoint);
    bool (*TurnTo)            (joint_t *ptJoint, int32_t nAngle, int32_t nSpeed);
    bool (*TurnToInTime)      (joint_t *ptJoint, int32_t nAngle, uint32_t wTime);
    struct {
      bool    (*Set)          (joint_t *ptJoint, int32_t nAngle);
      int32_t (*Get)          (joint_t *ptJoint);
    } Angle;
    struct {
      bool    (*Set)          (joint_t *ptJoint, int32_t nSpeed);
      int32_t (*Get)          (joint_t *ptJoint);
    } AngularSpeed;

    void                        (*TimerServiceRoutine)(void);

    struct {
      bool (*Register)      (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
      bool (*Unregister)      (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
    }ActionCompleteEvent;

END_DEF_INTERFACE(i_joint_t)
//! @}

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服务的初始化函数里面:


NO_INIT static joint_t s_tJoints;
...
static void spider_init(void)
{
    //! initialize servo service
    SERVO.Init ();
    SERVO.Start ();
   
    //! initialize cerebel layer
    CEREBEL_CFG(
      s_tJoints,
      UBOUND(s_tJoints),
    );
    ...
}

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

#define ACTION(__MSK, __AUTO, __TIME, ...)                                    \
      {                                                                     \
            (__MSK),                                                            \
            (__AUTO),                                                         \
            (__TIME),                                                         \
            .nAngles = __VA_ARGS__,                                             \
      }

#define ACTION_CFG(...)                                                         \
      do {                                                                  \
            static cerebel_action_t tActions[] = {__VA_ARGS__};                     \
            CEREBEL.Action.Move(tActions, UBOUND(tActions));                  \
      } 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。
       ... : 这个就是具体的角度配置明细表了,我们看一个例子:

    ACTION_CFG(
      ACTION(
            TRI_LEGS_L1_MSK | TRI_LEGS_L2_MSK,
            true,                                 //!< start automatically
            1 << JOINT_TIME_UNIT_RESOLUTION,      //!< Use 1s
            {
                = 180,
                = 180,
                = 0,

                = 90,
                = 90,
                = 90,
            }
      ),
    );

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

typedef enum {
    ...
    TRI_LEGS_L1_MSK               = ( LEFT_FRONT_LEG_1_MSK    |
                                        LEFT_BACK_LEG_1_MSK   |
                                        RIGHT_MIDDLE_LEG_1_MSK),

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

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

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

    do {
      NO_INIT static joint_t s_tJoint;
      NO_INIT static DELEGATE_HANDLE s_tHandler;

//      SERVO.Angle(RIGHT_BACK_LEG_2, 90);

      JOINT_CFG(
            s_tJoint,
            LEFT_BACK_LEG_2,
            355,                  //!< offset
            50,                     //!< start angle
            140,                  //!< end angle
            180,                  //!< Max Angular Speed
            90,                     //!< Reset Position
            680,                  //!< K
      );

      JOINT_CFG(
            s_tJoint,
            LEFT_MIDDLE_LEG_2,
            353,                  //!< offset
            52,                     //!< start angle
            142,                  //!< end angle
            180,                  //!< Max Angular Speed
            90,                     //!< Reset Position
            660,                   //!< K
      );

      JOINT_CFG(
            s_tJoint,
            LEFT_FRONT_LEG_2,
            353,                  //!< offset
            52,                     //!< start angle
            142,                  //!< end angle
            180,                  //!< Max Angular Speed
            90,                     //!< Reset Position
            680,                   //!< K
      );


      JOINT_CFG(
            s_tJoint,
            RIGHT_BACK_LEG_2,
            355,                  //!< offset
            50,                     //!< start angle
            140,                  //!< end angle
            180,                  //!< Max Angular Speed
            90,                     //!< Reset Position
            780,                  //!< K
      );

      JOINT_CFG(
            s_tJoint,
            RIGHT_MIDDLE_LEG_2,
            0,                      //!< offset
            45,                     //!< start angle
            135,                  //!< end angle
            180,                  //!< Max Angular Speed
            90,                     //!< Reset Position
            860,                  //!< K
      );

      JOINT_CFG(
            s_tJoint,
            RIGHT_FRONT_LEG_2,
            354,                  //!< offset
            51,                     //!< start angle
            141,                  //!< end angle
            180,                  //!< Max Angular Speed
            90,                     //!< Reset Position
            840,                  //!< K
      );

      JOINT_CFG(
            s_tJoint,
            RIGHT_BACK_LEG_1,
            275,                  //!< offset
            40,                     //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            0,                  //!< Reset Position
            1100,                   //!< K
      );

      JOINT_CFG(
            s_tJoint,
            RIGHT_MIDDLE_LEG_1,
            275,                  //!< offset
            40,                     //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            0,                  //!< Reset Position
            1024,                   //!< K
      );

      JOINT_CFG(
            s_tJoint,
            RIGHT_FRONT_LEG_1,
            260,                  //!< offset
            55,                     //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            0,                  //!< Reset Position
            970,                   //!< K
      );


      JOINT_CFG(
            s_tJoint,
            RIGHT_BACK_LEG_0,
            222,                  //!< offset
            48,                     //!< start angle
            138,                  //!< end angle
            180,                  //!< Max Angular Speed
            315,                  //!< Reset Position
            900,                  //!< K
      );

      


      JOINT_CFG(
            s_tJoint,
            RIGHT_MIDDLE_LEG_0,
            260,                  //!< offset
            55,                     //!< start angle
            145,                  //!< end angle
            180,                  //!< Max Angular Speed
            0,                      //!< Reset Position
            850,                  //!< K
      );


      JOINT_CFG(
            s_tJoint,
            RIGHT_FRONT_LEG_0,
            313,                  //!< offset
            47,                     //!< start angle
            137,                  //!< end angle
            180,                  //!< Max Angular Speed
            45,                     //!< Reset Position
            920,                  //!< K
      );


      JOINT_CFG(
            s_tJoint,
            LEFT_FRONT_LEG_0,
            40,                     //!< offset
            50,                     //!< start angle
            140,                  //!< end angle
            180,                  //!< Max Angular Speed
            135,                  //!< Reset Position
            890,                  //!< K
      );


      JOINT_CFG(
            s_tJoint,
            LEFT_MIDDLE_LEG_0,
            80,                     //!< offset
            55,                     //!< start angle
            145,                  //!< end angle
            180,                  //!< Max Angular Speed
            180,                  //!< Reset Position
            920,                   //!< K
      );

      JOINT_CFG(
            s_tJoint,
            LEFT_BACK_LEG_0,
            142,                  //!< offset
            38,                      //!< start angle
            128,                  //!< end angle
            180,                  //!< Max Angular Speed
            225,                  //!< Reset Position
            1130,                   //!< K
      );

      JOINT_CFG(
            s_tJoint,
            LEFT_BACK_LEG_1,
            105,                  //!< offset
            20,                     //!< start angle
            110,                  //!< end angle
            180,                  //!< Max Angular Speed
            180,                  //!< Reset Position
            1100,                   //!< K
      );

      JOINT_CFG(
            s_tJoint,
            LEFT_MIDDLE_LEG_1,
            90,                     //!< offset
            45,                     //!< start angle
            135,                  //!< end angle
            180,                  //!< Max Angular Speed
            180,                  //!< Reset Position
            950,                   //!< K
      );

      JOINT_CFG(
            s_tJoint,
            LEFT_FRONT_LEG_1,
            80,                     //!< offset
            55,                     //!< start angle
            145,                  //!< end angle
            180,                  //!< Max Angular Speed
            180,                  //!< Reset Position
            850,                   //!< K
      );

    } while(false);


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

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

static void servo_demo(void)
{
    SERVO.Init ();
    SERVO.Start ();

    do {
      NO_INIT static joint_t s_tJoint;
      NO_INIT static DELEGATE_HANDLE s_tHandler;
      JOINT_CFG(
            s_tJoint,
            LEFT_BACK_LEG_0,
            45,                     //!< offset
            0,                      //!< start angle
            180,                  //!< end angle
            180,                  //!< Max Angular Speed
            135,
      );

    } while(false);

}

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

    JOINT.TurnTo(&s_tJoint, 45, 45);

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

//! \brief joint action complete event handler
static fsm_rt_t joint_action_complete_event_handler(void *pArg, void *pParam)
{
    joint_t *ptJoint = (joint_t *)pArg;
    static bool s_bFlag = false;
    if (s_bFlag) {
      JOINT.TurnTo(ptJoint, 45, 45);
    } else {
      JOINT.TurnTo(ptJoint, 135, 45);
    }
    s_bFlag = !s_bFlag;
    return fsm_rt_cpl;
}

static void servo_demo(void)
{
    ...
    do {
      ...
      NO_INIT static DELEGATE_HANDLE s_tHandler;
      ...
      delegate_handler_init(&s_tHandler,
                              &joint_action_complete_event_handler,
                              &s_tJoint );
      JOINT.ActionCompleteEvent.Register(&s_tJoint, &s_tHandler);

    } while(false);
    ...
}

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

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

    }
    JOINT.TimerServiceRoutine();
}

/*! \note initialize application
*\param none
*\retval true hal initialization succeeded.
*\retval false hal initialization failed
*/
ROOT bool app_init(void)
{

    servo_demo();

    /*! you can put your code here */
    SYSTICK_CFG (
      ENABLE_SYSTICK            |
      SYSTICK_SOURCE_SYSCLK       |
      ENABLE_SYSTICK_INTERRUPT,
      (PM_GET_SYS_CLK() >> 10)
    );

    ENABLE_GLOBAL_INTERRUPT();

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



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


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

//! \name joint interface
//! @{
DEF_INTERFACE(i_joint_t)

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

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

    struct {
      bool    (*Set)      (joint_t *ptJoint, int32_t nAngle);
      int32_t (*Get)      (joint_t *ptJoint);
    } Angle;
    struct {
      bool    (*Set)      (joint_t *ptJoint, int32_t nSpeed);
      int32_t (*Get)      (joint_t *ptJoint);
    } AngularSpeed;

    void (*TimerServiceRoutine)(void);

    struct {
      bool (*Register)    (joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
      bool (*Unregister)(joint_t *ptJoint, DELEGATE_HANDLE *ptHandler);
    }ActionCompleteEvent;

END_DEF_INTERFACE(i_joint_t)
//! @}


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

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


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

    }
}

/*! \note initialize application
*\param none
*\retval true hal initialization succeeded.
*\retval false hal initialization failed
*/
bool app_init(void)
{
    /*! you can put your code here */
    SYSTICK_CFG (
      ENABLE_SYSTICK            |
      SYSTICK_SOURCE_SYSCLK       |
      ENABLE_SYSTICK_INTERRUPT,
      (PM_GET_SYS_CLK() >> 10)
    );

    ENABLE_GLOBAL_INTERRUPT();

    servo_demo();

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


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

/*============================ MACROS ========================================*/
#define TOP         (0x01FF)

/*============================ MACROFIED FUNCTIONS ===========================*/

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

#define RGB(__R, __G, __B)                                                \
      do {                                                                \
            set_led_red_gradation(__R);                                     \
            set_led_green_gradation(__G);                                 \
            set_led_blue_gradation(__B);                                    \
      } while(false)

#define LED_LIGHT               3
#define LED_BREATH_SPEED      14

/*! \brief set the 16-level led gradation
*! \param hwLevel gradation
*! \return none
*/
static void set_led_red_gradation(uint16_t hwLevel)
{
    static uint16_t s_hwCounter = 0;
   
    if (hwLevel >= s_hwCounter) {
      LED_RED_ON();
    } else {
      LED_RED_OFF();
    }
   
    s_hwCounter++;
    s_hwCounter &= TOP;
}

/*! \brief set the 16-level led gradation
*! \param hwLevel gradation
*! \return none
*/
static void set_led_green_gradation(uint16_t hwLevel)
{
    static uint16_t s_hwCounter = 0;
   
    if (hwLevel >= s_hwCounter) {
      LED_GREEN_ON();
    } else {
      LED_GREEN_OFF();
    }
   
    s_hwCounter++;
    s_hwCounter &= TOP;
}


/*! \brief set the 16-level led gradation
*! \param hwLevel gradation
*! \return none
*/
static void set_led_blue_gradation(uint16_t hwLevel)
{
    static uint16_t s_hwCounter = 0;
   
    if (hwLevel >= s_hwCounter) {
      LED_BLUE_ON();
    } else {
      LED_BLUE_OFF();
    }
   
    s_hwCounter++;
    s_hwCounter &= TOP;
}

static void breath_led(void)
{
    static uint16_t s_hwCounter = 0;
    static int16_t s_nGrayRed = 0;
    static int16_t s_nGrayGreen = 0;
    static int16_t s_nGrayBlue = 0;

    s_hwCounter++;
    if (!(s_hwCounter & (_BV(LED_BREATH_SPEED)-1))) {
      s_nGrayRed++;
      if (s_nGrayRed == (TOP >> LED_LIGHT)) {
            s_nGrayRed = 0;
      }
    }
    if (!(s_hwCounter & (_BV(LED_BREATH_SPEED+1)-1))) {
      s_nGrayGreen++;
      if (s_nGrayGreen == (TOP >> LED_LIGHT)) {
            s_nGrayGreen = 0;
      }
    }
    if (!(s_hwCounter & (_BV(LED_BREATH_SPEED + 2)-1))) {
      s_nGrayBlue++;
      if (s_nGrayBlue == (TOP >> LED_LIGHT)) {
            s_nGrayBlue = 0;
      }
    }

    RGB(
      ABS(s_nGrayRed - (TOP >> (LED_LIGHT + 1))),
      ABS(s_nGrayGreen - (TOP >> (LED_LIGHT + 1))),
      ABS(s_nGrayBlue - (TOP >> (LED_LIGHT + 1)))
    );
}

/*! state machine implementation */
IMPLEMENT_FSM(DemoTask)

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

      IO_CFG(
            {PB22,IO_WORKS_AS_FUNC1},         //!< LED Red
            {PE26,IO_WORKS_AS_FUNC1},         //!< LED Green
            {PB21,IO_WORKS_AS_FUNC1},         //!< LED Blue
      );

      TRANSFER_TO_STATE(Demo_Task);
      REFLEXIVE_STATE;
    END

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

      REFLEXIVE_STATE;
    END
END_IMPLEMENT_FSM


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

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

//! servo interface
//! \name i_servo_t
//! @{
DEF_INTERFACE (i_servo_t)
    bool    (*Init)   (void);
    bool    (*Deinit)   (void);
    bool    (*Finish)   (void);
    bool    (*Start)    (void);
    bool    (*Angle)    (uint8_t chServoNum,uint32_t wAngle);
END_DEF_INTERFACE (i_servo_t)
//! @}

/*============================ PROTOTYPES ====================================*/
/*============================ GLOBAL VARIABLES ==============================*/
extern const i_servo_t SERVO;

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

static void servo_demo(void)
{
    SERVO.Init ();
   
    for (uint8_t n = 0; n <= 18; n++) {
      SERVO.Angle (n, 90);
    }
   
    SERVO.Start ();
//    SERVO.Angle (0, 90);
//    SERVO.Angle (1, 0);
//    SERVO.Angle (2, 45);
//    SERVO.Angle (3, 10);   
//    SERVO.Angle (4, 20);
//    SERVO.Angle (5, 10);
//    SERVO.Angle (6, 15);
//    SERVO.Angle (7, 29);   
   
}

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

/*! \brief hardware initialization
*! \param none
*! \retval true run the default initialization
*! \retval false ignore the default initialization
*/
ROOT bool ON_HW_INIT(void)                        
{

    /*! you can put your code here */
    IO_CFG(
      {PC1,   IO_WORKS_AS_FUNC4},
      {PC2,   IO_WORKS_AS_FUNC4},
      {PC3,   IO_WORKS_AS_FUNC4},
      {PC4,   IO_WORKS_AS_FUNC4},

      {PC8,   IO_WORKS_AS_FUNC3},
      {PC9,   IO_WORKS_AS_FUNC3},
      {PC10,IO_WORKS_AS_FUNC3},
      {PC11,IO_WORKS_AS_FUNC3},

      {PD0,   IO_WORKS_AS_FUNC4},
      {PD1,   IO_WORKS_AS_FUNC4},
      {PD2,   IO_WORKS_AS_FUNC4},
      {PD3,   IO_WORKS_AS_FUNC4},
      {PD4,   IO_WORKS_AS_FUNC4},
      {PD5,   IO_WORKS_AS_FUNC4},

      {PB18,IO_WORKS_AS_FUNC3},
      {PB19,IO_WORKS_AS_FUNC3},

      {PA1,   IO_WORKS_AS_FUNC3},
      {PA2,   IO_WORKS_AS_FUNC3},
    );
   
    return true;
}

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

//! \brief demo task
STATIC_FSM(DemoTask)
    PRIVATE STATE(Demo_Init);
    PRIVATE STATE(Demo_Task);
END_STATIC_FSM
...
/*! \note initialize application
*\param none
*\retval true hal initialization succeeded.
*\retval false hal initialization failed
*/
bool app_init(void)
{
    servo_demo();

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

/*! state machine implementation */
IMPLEMENT_FSM(DemoTask)

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

      TRANSFER_TO_STATE(Demo_Task);
      REFLEXIVE_STATE;
    END

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

      REFLEXIVE_STATE;
    END
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扩展




gujiamao_love 发表于 2014-8-3 15:24:24

顶顶 老师!{:smile:}

HadesHe 发表于 2014-8-3 15:29:52

该顶 该顶

627255898 发表于 2014-8-3 15:34:31

我感觉你的电源口画的有问题

diti 发表于 2014-8-3 15:50:54

怒赞一个!

rainbow 发表于 2014-8-3 16:00:25

学习学习。
我的就用洞洞板搭了。

armok 发表于 2014-8-3 17:07:19

lcptw 发表于 2014-8-3 17:24:28

走线有点杂,先调功能吧,估计后续要改版。{:loveliness:}

浪里白条 发表于 2014-8-3 17:53:00

等着看效果了,哈哈 好期待

sunfulong 发表于 2014-8-3 18:39:25

顶傻孩子老师~~~

gnocy 发表于 2014-8-3 21:12:00

进度好快啊,嫉妒羡慕中,PCB布局很好

步之道 发表于 2014-8-3 21:32:13

上面的固定孔是用螺丝固定吗?实际安装时是否会碰到周围器件?

am869943552 发表于 2014-8-3 22:11:19

顶,关注中~~{:lol:}

fengyunyu 发表于 2014-8-3 22:16:44

” 蜘蛛的运动控制”,专业。

霸气侧漏 发表于 2014-8-3 22:28:10

赞一个 速度好快

lyzhangxiang 发表于 2014-8-4 08:44:24

都构架好Framework了 支持

pcbddd 发表于 2014-8-4 08:49:48

赞赞赞,这就是效率

Excellence 发表于 2014-8-4 09:24:03

{:victory:}{:victory:}{:victory:}

Ai_evan 发表于 2014-8-4 10:09:42

器件放置挺整齐

myiccdream 发表于 2014-8-4 10:32:58

1个光耦1rmb。而且这个光耦不是用于隔离作用,只是做个电平转换,这成本太高了
LM2576的不轮layout的体积,还是成本感觉都不是最好的。这个电源部分可以大部分的压缩空间和成本

yiming988 发表于 2014-8-4 11:09:14

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

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

myiccdream 发表于 2014-8-4 11:36:45

我从原理图上看你所使用的是非隔离的电源(隔离电源可以参考金升阳的模块)。所以我个人觉得这个地方不算严格的隔离。当然您这样使用光耦也没什么问题

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

hhxb 发表于 2014-8-4 11:39:37

不在乎速度光耦换成TLP281-4GB;4光耦,SOP16封装。
开关电源用TPS54331 ;3.5V 至 28V 输入、3A、570kHz 降压转换器

yiming988 发表于 2014-8-4 11:54:01

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

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

yiming988 发表于 2014-8-4 11:57:09

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

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

yiming988 发表于 2014-8-4 11:59:32

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

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

jzb8736 发表于 2014-8-4 12:09:20

电源没有隔离 光耦没有起到隔离作用VIN多少伏?7805有2.5V压降这个功耗不容忽视。

wxfje 发表于 2014-8-4 12:26:49

顶,学习学习

markdif 发表于 2014-8-4 12:39:44

如果只是为了完成将3.3V电压到5V 电压转换(非隔离),普通三极管就可胜任,若后面的负载有点重,需要驱动DC 马达之类的负载,则可考用MOS管来兼做电平转换和驱动,供参考。

zyw19987 发表于 2014-8-4 12:50:49

期待这种有质量的代码。喜欢这种分层。

miniqq80 发表于 2014-8-4 13:09:16

各个接口之间的距离挨的有点近,将来对线插拔的时候可能下不了手。特别是阵列布的3pin的那些接口

SamuelSiu 发表于 2014-8-4 13:29:54

电源插座的孔是否有问题?

Gorgon_Meducer 发表于 2014-8-4 17:42:18

非常感谢大家!!

renxupeng 发表于 2014-8-4 19:25:19

顶,学习学习

zwgmail 发表于 2014-8-4 19:46:13

学习,顶顶

周阳 发表于 2014-8-5 09:14:26

学习,支持傻孩子

Puppey 发表于 2014-8-5 14:34:30

傻孩子大大厉害=-=

alanse 发表于 2014-8-5 15:52:55

大力关注傻孩子{:lol:}{:lol:}

chenguanghua 发表于 2014-8-5 16:21:42

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

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

zhudadragon 发表于 2014-8-6 08:57:31

顶一下、、、

zjk 发表于 2014-8-6 11:28:42

速度好快哈。。。

chenrulin 发表于 2014-8-6 13:15:13

PCB上,DC电源座的封装没问题吗?

laotui 发表于 2014-8-6 13:38:11

支持,期待大师的软件。

sbk100 发表于 2014-8-6 21:59:24

原来傻孩子团队用AD9画板子啊 画的不错啊 这块板子是傻孩子画的?

WEIZ666 发表于 2014-8-6 22:18:27

赞LZ的 快速度

zhuyeling 发表于 2014-8-7 08:38:05

效率真高,赞

霸气侧漏 发表于 2014-8-7 08:48:49

期待早日成功

luckytwt1984 发表于 2014-8-7 16:45:33

关注中,电源器件后面的建议不错

Gorgon_Meducer 发表于 2014-8-9 12:49:36

sbk100 发表于 2014-8-6 21:59
原来傻孩子团队用AD9画板子啊 画的不错啊 这块板子是傻孩子画的?

我不懂画板子。

liaoya00000 发表于 2014-8-9 13:32:02

很多东西都不会,只能默默支持了。。。

opiviqo 发表于 2014-8-9 16:49:08

支持,期待最后结果!~~~

yiming988 发表于 2014-8-9 23:18:21

sbk100 发表于 2014-8-6 21:59
原来傻孩子团队用AD9画板子啊 画的不错啊 这块板子是傻孩子画的?

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

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

Gorgon_Meducer 发表于 2014-8-9 23:33:02

进度更新了

zhangchaoying 发表于 2014-8-9 23:45:06

好厉害好礼哈啊

zhangchaoying 发表于 2014-8-9 23:45:33

傻孩子好厉害,赶紧做出来看看啥样

yanpenghao 发表于 2014-8-10 20:28:21

进度还是挺快的

wxfje 发表于 2014-8-10 21:41:09

动作好快,顶个

franki 发表于 2014-8-11 19:02:51

大神啊          佩服

wengxiaoming 发表于 2014-8-11 19:54:00

好东西,期待成品

shinemotou 发表于 2014-8-12 10:29:39

想加入 不知如何才能

didadida 发表于 2014-8-12 23:43:35

期待后续进展{:smile:}

abszy 发表于 2014-8-13 10:59:19

看了大家的的评论学到了不少
楼主速度很快啊

chjf 发表于 2014-8-14 11:12:06

{:victory:}{:victory:}顶一下、、、

xiongh 发表于 2014-8-14 13:25:56

不错啊,以后可以改进成家庭服务机器人,满屋子的爬呀爬。

pcbddd 发表于 2014-8-15 17:14:21

哇,期待下一步动作

Gorgon_Meducer 发表于 2014-8-16 23:31:27

更新了工程模板的Beta1。

pcbddd 发表于 2014-8-17 00:02:24

期待,大工程啊

LJW 发表于 2014-8-17 00:02:49

顶顶,珍惜辛勤劳动成果

gujiamao_love 发表于 2014-8-17 00:19:40

老师注意身体呀。。

armok 发表于 2014-8-17 02:36:33

霸气侧漏 发表于 2014-8-17 09:42:09

不错不错

浪里白条 发表于 2014-8-17 09:46:28

工程模板棒极了,又跟着学着不少东西

wxfje 发表于 2014-8-17 18:56:31

工程模板不错,学习了
同时楼主多注意身体呀!

霸气侧漏 发表于 2014-8-19 12:58:27

再次顶一个

qinshiysb 发表于 2014-8-19 17:18:59

这个不错哈。。。。

bbsview 发表于 2014-8-19 17:59:30

不错,继续保持关注中···

Gorgon_Meducer 发表于 2014-8-20 16:37:43

更新了,增加了GPIO操作的例子,使用外部50MHz精确时钟,增加了SysTick的使用范例

qinshiysb 发表于 2014-8-20 17:08:14

赶上更新了,看看

zwei99999999 发表于 2014-8-20 17:33:40

更新蛮快的嘛{:lol:}期待。。。。。。。。。。。。

hjqr 发表于 2014-8-20 18:12:48

来学习了

Pupil 发表于 2014-8-20 20:08:36

Gorgon_Meducer 发表于 2014-8-9 23:33
进度更新了

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

wxfje 发表于 2014-8-20 20:42:08

三色LED驱动不错,学习了

laotui 发表于 2014-8-21 00:37:48

进度很快啊,期待大神的程序,从傻孩子的文章里学到很多。

rootxie 发表于 2014-8-21 08:40:50

傻孩子大牛一个啊,学习

Gorgon_Meducer 发表于 2014-8-21 11:41:41

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

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

qwert1213131 发表于 2014-8-21 11:52:53

更新真快啊,赞一个,不久就能看到作品了

zhaojun_xf 发表于 2014-8-21 12:32:26

不错。。。。。。。。。。。。。

hongyancl 发表于 2014-8-22 12:24:36

学习楼主的资料

jlhgold 发表于 2014-8-22 12:58:39

封装的太严实反而感觉不好用了!

Gorgon_Meducer 发表于 2014-8-22 13:21:32

jlhgold 发表于 2014-8-22 12:58
封装的太严实反而感觉不好用了!

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

gzhmcu 发表于 2014-8-22 13:33:36

支持一下

jlhgold 发表于 2014-8-22 19:15:07

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

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

gy810986741 发表于 2014-8-22 20:17:19

感觉有一个团队能够合作的很好,那么效率会非常高的

lanfeng0107 发表于 2014-8-22 21:30:49

大牛,每个地方都有可以学习的内容!

Gorgon_Meducer 发表于 2014-8-23 00:54:11

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

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

yzb1019 发表于 2014-8-23 14:50:37

我是来向高手学习的

王晨 发表于 2014-8-23 15:37:54

顶顶                        

wicy001 发表于 2014-8-23 17:27:37

进来学习一下软件思路。
把灵活的变机械,把机械的变灵活。

bluestone2012 发表于 2014-8-23 20:08:14

程序写的太牛了,羡慕中

bruce_helen 发表于 2014-8-24 08:06:33

状态机编程,架构搭的不错!
页: [1] 2 3 4
查看完整版本: [开源]阿莫蜘蛛进度报告[2015-02-15更新]