对于STM32F103控制的三轴机械臂基本功能测试-关节转动控制
➤01 机械臂调试
1.简介
对于 基于STM32对于三轴机械臂控制器设计 的设计已经进行了如下的调试:
- 对于STM32F103三轴机械臂控制器进行基本功能测试-关节角度读取
- 对于STM32F103三轴机械臂控制器进行基本功能测试-上下运动功能
- 基于STM32对于三轴机械臂控制器设计 基本调试:串口命令调试。
下面对于该机械臂的两个关节转动进行调试:
1) 肘关节运动:参见: 增加行星轮减速后机械臂调试 、 组装肩部带有减速器双轴机械臂组装与调试
2)肘关节运动:参见: 两轴机械臂+机械爪整体控制板设计与机械爪控制调试 、 双关节机械臂+机械爪运动控制
➤02 关节转动初步调试
1.接口1
三个步进信号接口定义:
PSM1 | PSM2 | PSM3 |
---|---|---|
肩关节 | 肘关节 | 上下运动 |
(1)电路图
▲ 三个步进电机信号输出控制端口
(2)步进电机设置
A. 肩关节步进电机: S1 ~ S6: ON,ON,OFF,ON,OFF,OFF
参考步进电机数据文件: 57HSXXXXEIS一体化步进伺服驱动电机
**B. 肘关节步进电机:**S1 ~ S5: OFF,OFF,OFF,OFF,ON
参考步进电机数据文件: 42HS48EIS步进闭环电机最大转速
(3)角度运行范围
根据 组装肩部带有减速器双轴机械臂组装与调试 给出的测试结果:
(1)肩部角度运行180°,给定脉冲个数:32000
(2)肘部角度运行180°,给定脉冲个数:25600
脉冲数量:正→顺时针旋转;负→逆时针旋转
2.设置中断服务程序2
(1)中断Timer4
通过中断程序:ArthrosisISR来对两个关节步进电机发送脉冲信号。中断程序是在10kHzTimer4的定时中断下工作的。输出脉冲的频率为:5kHz。
(2)中断频率细分
分别通过g_nArthrosisDividerSoulderCount, g_nArthrosisDividerElbowCount对于两个关节脉冲输出频率从5kHz进行细分。
//------------------------------------------------------------------------------
void ArthrosisISR(void) {//--------------------------------------------------------------------------g_nArthrosisDividerShoulderCount += g_nShoulderDividerInc;if(g_nArthrosisDividerShoulderCount >= ARTHROSIS_DIVIDER_SHOULDER_PERIOD) {g_nArthrosisDividerShoulderCount -= ARTHROSIS_DIVIDER_SHOULDER_PERIOD;g_nArthrosisShoulderCount ++;if(g_nShoulderAngle != 0) {if(g_nShoulderAngle > 0) {ON(SM_DIR1);if(g_nArthrosisShoulderCount & 0x1) {ON(SM_PUL1);} else {OFF(SM_PUL1);g_nShoulderAngle --;} } else {OFF(SM_DIR1);if(g_nArthrosisShoulderCount & 0x1) {ON(SM_PUL1);} else {OFF(SM_PUL1);g_nShoulderAngle ++;} }}}g_nArthrosisDividerElbowCount += g_nElbowDividerInc;if(g_nArthrosisDividerElbowCount >= ARTHROSIS_DIVIDER_ELBOW_PERIOD) {g_nArthrosisDividerElbowCount -= ARTHROSIS_DIVIDER_ELBOW_PERIOD;g_nArthrosisElbowCount ++;if(g_nElbowAngle != 0) {if(g_nElbowAngle > 0) {ON(SM_DIR2);if(g_nArthrosisElbowCount & 0x1) {ON(SM_PUL2);} else {OFF(SM_PUL2);g_nElbowAngle --;} } else {OFF(SM_DIR2);if(g_nArthrosisElbowCount & 0x1) {ON(SM_PUL2);} else {OFF(SM_PUL2);g_nElbowAngle ++;} }}}
}
3.设置角度极限检查
使用 ArthrosisLimitCheck()来检查角度的极限。
CONTROL_EXT int g_nArthrosisCheckCount;
#define ARTHROSIS_CHECK_PERIOD 50
void ArthrosisLimitCheck(void);#define SHOULDER_ANGLE_MIN 8192
#define SHOULDER_ANGLE_MAX 24576
#define ELBOW_ANGLE_MIN 4096
#define ELBOW_ANGLE_MAX 28672
void ArthrosisLimitCheck(void) {if(HAL_GetTick() < g_nArthrosisCheckCount) return;g_nArthrosisCheckCount = HAL_GetTick() + ARTHROSIS_CHECK_PERIOD;if(g_nShoulderAngle != 0) { int nAngle = ShoulderAngle();if(g_nShoulderAngle < -1) {if(nAngle < SHOULDER_ANGLE_MIN)g_nShoulderAngle = -1; } else if(g_nShoulderAngle > 1) {if(nAngle > SHOULDER_ANGLE_MAX)g_nShoulderAngle = 1;} }if(g_nElbowAngle != 0) { int nAngle = ElbowAngle();if(g_nElbowAngle < -1) {if(nAngle < ELBOW_ANGLE_MIN)g_nElbowAngle = -1; } else if(g_nElbowAngle > 1) { if(nAngle > ELBOW_ANGLE_MAX)g_nElbowAngle = 1;} }
}
➤03 角度调节
1.角度设置
void ShoulderGotoAngle(int nAngle) {if(nAngle < SHOULDER_ANGLE_MIN) nAngle = SHOULDER_ANGLE_MIN;if(nAngle > SHOULDER_ANGLE_MAX) nAngle = SHOULDER_ANGLE_MAX;int nNowAngle = ShoulderAngle();int nDeltaAngle = (nAngle - nNowAngle) * SHOULDER_HALF_PULSE / 0x4000;g_nShoulderAngle += nDeltaAngle;
}void ElbowGotoAngle(int nAngle) {if(nAngle < ELBOW_ANGLE_MIN) nAngle = ELBOW_ANGLE_MIN;if(nAngle > ELBOW_ANGLE_MAX) nAngle = ELBOW_ANGLE_MAX;int nNowAngle = ElbowAngle();int nDeltaAngle = (nAngle - nNowAngle) * ELBOW_HALF_PULSE / 0x4000;g_nElbowAngle += nDeltaAngle;}
2.角度调节
void ShoulderAngleSet(int nAngle) {g_nElbowAngleSet = nAngle;g_nElbowAngleAdjustTime = 5;
}void ElbowAngleSet(int nAngle) {g_nShoulderAngleSet = nAngle;g_nShoulderAngleAdjustTime = 5;
}
➤※ 附件
/*
**==============================================================================
** CONTROL.C: -- by Dr. ZhuoQing, 2014-2-4
**
**==============================================================================
*/
#include "stm32f1xx_hal.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "stm32f1xxa.h"
#include "serialtxt.h"
#include "stdsub.h"
#include "config.h"
#include "cmdsub.h"
//------------------------------------------------------------------------------#define CONTROL_GLOBALS 1 // Define the global variables
#include "CONTROL.H"
#include "ST3806.H"//==============================================================================
// Initialize function
//------------------------------------------------------------------------------
extern TIM_HandleTypeDef htim1, htim4;
void ControlInit(void) {SerialTxtInit(); // Initialize the console debug interface//--------------------------------------------------------------------------HAL_TIM_Base_Start(&htim1);HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);HAL_TIM_Base_Start_IT(&htim4);//----------------------------------------------------------------------OFF(SM_PUL1); // as NL2003 output, OFF means out off.OFF(SM_DIR1);OFF(SM_PUL2);OFF(SM_DIR2);OFF(SM_PUL3);OFF(SM_DIR3);OFF(SM_ENABLE);OUT(SM_PUL1);OUT(SM_DIR1);OUT(SM_PUL2);OUT(SM_DIR2);OUT(SM_PUL3);OUT(SM_DIR3);OUT(SM_ENABLE);//------------------------------------------------------------------ ON(ARM_POS0);ON(ARM_POS1);INPU(ARM_POS0);INPU(ARM_POS1); g_nArmUpDownFlag = ARM_UPDOWN_STOP;g_nArmUpDownCount = 0;//--------------------------------------------------------------------------ST3806Init(1);//--------------------------------------------------------------------------g_nShoulderAngle = 0;g_nElbowAngle = 0;g_nArthrosisShoulderCount = 0;g_nArthrosisElbowCount = 0;g_nArthrosisDividerShoulderCount = 0;g_nArthrosisDividerElbowCount = 0;g_nShoulderDividerInc = ARTHROSIS_DIVIDER_SHOULDER_INC;g_nElbowDividerInc = ARTHROSIS_DIVIDER_ELBOW_INC;g_nArthrosisCheckCount = HAL_GetTick() + ARTHROSIS_CHECK_PERIOD;g_nShoulderAngleSet = ShoulderAngle();g_nElbowAngleSet = ElbowAngle();g_nShoulderAngleAdjustTime = 0;g_nElbowAngleAdjustTime = 0;
}//--------------------------------------------------------------------------
void ArmMoveUpDownISR(void) {if(g_nArmUpDownFlag == ARM_UPDOWN_STOP) return;//--------------------------------------------------------------------------g_nArmUpDownISRCount ++;if(++g_nArmUpDownCount & 0x1) {ON(SM_PUL3);} else {OFF(SM_PUL3);if(g_nArmUpDownFlag == ARM_UPDOWN_MOVEUP) {if(ARM_POS_UP) g_nArmUpDownFlag = ARM_UPDOWN_STOP;} else {if(ARM_POS_DOWN) g_nArmUpDownFlag = ARM_UPDOWN_STOP;}}
}//------------------------------------------------------------------------------
void ArmMoveUp(void) {ON(SM_DIR3);g_nArmUpDownFlag = ARM_UPDOWN_MOVEUP;g_nArmUpDownISRCount = 0;}//------------------------------------------------------------------------------
void ArmMoveDown(void) {OFF(SM_DIR3);g_nArmUpDownFlag = ARM_UPDOWN_MOVEDOWN;g_nArmUpDownISRCount = 0;
}void ArmMoveStop(void) {g_nArmUpDownFlag = ARM_UPDOWN_STOP;g_nArmUpDownISRCount = 0;
} //------------------------------------------------------------------------------
unsigned int ShoulderAngle(void) {unsigned int nAngle;nAngle = ST3806ReadNumber(ST3806_CHANNEL_1);return (nAngle + ARM_SHOULDER_OFFSET) & 0x7fff;
}unsigned int ElbowAngle(void) {unsigned int nAngle;nAngle = ST3806ReadNumber(ST3806_CHANNEL_2);return (nAngle + ARM_ELBOW_OFFSET) & 0x7fff;
}//------------------------------------------------------------------------------
void ArthrosisISR(void) {//--------------------------------------------------------------------------g_nArthrosisDividerShoulderCount += g_nShoulderDividerInc;if(g_nArthrosisDividerShoulderCount >= ARTHROSIS_DIVIDER_SHOULDER_PERIOD) {g_nArthrosisDividerShoulderCount -= ARTHROSIS_DIVIDER_SHOULDER_PERIOD;g_nArthrosisShoulderCount ++;if(g_nShoulderAngle != 0) {if(g_nShoulderAngle > 0) {ON(SM_DIR1);if(g_nArthrosisShoulderCount & 0x1) {ON(SM_PUL1);} else {OFF(SM_PUL1);g_nShoulderAngle --;} } else {OFF(SM_DIR1);if(g_nArthrosisShoulderCount & 0x1) {ON(SM_PUL1);} else {OFF(SM_PUL1);g_nShoulderAngle ++;} }}}g_nArthrosisDividerElbowCount += g_nElbowDividerInc;if(g_nArthrosisDividerElbowCount >= ARTHROSIS_DIVIDER_ELBOW_PERIOD) {g_nArthrosisDividerElbowCount -= ARTHROSIS_DIVIDER_ELBOW_PERIOD;g_nArthrosisElbowCount ++;if(g_nElbowAngle != 0) {if(g_nElbowAngle > 0) {ON(SM_DIR2);if(g_nArthrosisElbowCount & 0x1) {ON(SM_PUL2);} else {OFF(SM_PUL2);g_nElbowAngle --;} } else {OFF(SM_DIR2);if(g_nArthrosisElbowCount & 0x1) {ON(SM_PUL2);} else {OFF(SM_PUL2);g_nElbowAngle ++;} }}}}//------------------------------------------------------------------------------
void ArthrosisLimitCheck(void) {if(HAL_GetTick() < g_nArthrosisCheckCount) return;g_nArthrosisCheckCount = HAL_GetTick() + ARTHROSIS_CHECK_PERIOD;if(g_nShoulderAngle != 0) { int nAngle = ShoulderAngle();if(g_nShoulderAngle < -1) {if(nAngle < SHOULDER_ANGLE_MIN)g_nShoulderAngle = -1; } else if(g_nShoulderAngle > 1) {if(nAngle > SHOULDER_ANGLE_MAX)g_nShoulderAngle = 1;} } else {if(g_nShoulderAngleAdjustTime > 0) {g_nShoulderAngleAdjustTime --;ShoulderGotoAngle(g_nShoulderAngleSet);}}if(g_nElbowAngle != 0) { int nAngle = ElbowAngle();if(g_nElbowAngle < -1) {if(nAngle < ELBOW_ANGLE_MIN)g_nElbowAngle = -1; } else if(g_nElbowAngle > 1) { if(nAngle > ELBOW_ANGLE_MAX)g_nElbowAngle = 1;} } else {if(g_nElbowAngleAdjustTime > 0) {g_nElbowAngleAdjustTime --;
// ElbowGotoAngle(g_nElbowAngleSet);}}}//------------------------------------------------------------------------------
void ShoulderGotoAngle(int nAngle) {if(nAngle < SHOULDER_ANGLE_MIN) nAngle = SHOULDER_ANGLE_MIN;if(nAngle > SHOULDER_ANGLE_MAX) nAngle = SHOULDER_ANGLE_MAX;int nNowAngle = ShoulderAngle();int nDeltaAngle = (nAngle - nNowAngle) * SHOULDER_HALF_PULSE / 0x4000;g_nShoulderAngle += nDeltaAngle;
}void ElbowGotoAngle(int nAngle) {if(nAngle < ELBOW_ANGLE_MIN) nAngle = ELBOW_ANGLE_MIN;if(nAngle > ELBOW_ANGLE_MAX) nAngle = ELBOW_ANGLE_MAX;int nNowAngle = ElbowAngle();int nDeltaAngle = (nAngle - nNowAngle) * ELBOW_HALF_PULSE / 0x4000;g_nElbowAngle += nDeltaAngle;}//------------------------------------------------------------------------------
void ShoulderAngleSet(int nAngle) {g_nElbowAngleSet = nAngle;g_nElbowAngleAdjustTime = 5;
}void ElbowAngleSet(int nAngle) {g_nShoulderAngleSet = nAngle;g_nShoulderAngleAdjustTime = 5;
}//------------------------------------------------------------------------------//==============================================================================
// END OF THE FILE : CONTROL.C
//------------------------------------------------------------------------------
/*
**==============================================================================
** CONTROL.H: -- by Dr. ZhuoQing, 2014-2-4
**
** Description:
**
**==============================================================================
*/
#ifndef __CONTROL__
#define __CONTROL__
//------------------------------------------------------------------------------
#ifdef CONTROL_GLOBALS#define CONTROL_EXT
#else#define CONTROL_EXT extern
#endif // CONTROL_GLOBALS
//------------------------------------------------------------------------------//==============================================================================
// INTERFACE INITIALIZE FUNCTION
//------------------------------------------------------------------------------
void ControlInit(void);//#define ANGLE_DIR1 GPIOB,7
//#define ANGLE_DIR2 GPIOB,6
#define BEEP GPIOB,5
#define KEYIN GPIOB,4 //---------------------------------------------------------------------------
#define SM_PUL1 GPIOA,4
#define SM_DIR1 GPIOA,5
#define SM_PUL2 GPIOA,6
#define SM_DIR2 GPIOA,7
#define SM_PUL3 GPIOB,0
#define SM_DIR3 GPIOB,1
#define SM_ENABLE GPIOC,15#define ARM_MOVE_UP ON(SM_DIR3)
#define ARM_MOVE_DOWN OFF(SM_DIR3)//------------------------------------------------------------------------------
#define ARM_POS0 GPIOA,0
#define ARM_POS1 GPIOA,1#define ARM_POS_UP VAL(ARM_POS1)
#define ARM_POS_DOWN VAL(ARM_POS0)void ArmMoveUpDownISR(void);
CONTROL_EXT int g_nArmUpDownFlag; // 0: Stop; 1:Move Up; 2:Move Down
CONTROL_EXT int g_nArmUpDownCount; // Last bit generate pulse
#define ARM_UPDOWN_STOP 0
#define ARM_UPDOWN_MOVEUP 1
#define ARM_UPDOWN_MOVEDOWN 2CONTROL_EXT int g_nArmUpDownISRCount;void ArmMoveUp(void);
void ArmMoveDown(void);
void ArmMoveStop(void);//------------------------------------------------------------------------------
#define ARM_SHOULDER_OFFSET 15176
#define ARM_ELBOW_OFFSET 7433unsigned int ShoulderAngle(void);
unsigned int ElbowAngle(void);//------------------------------------------------------------------------------
CONTROL_EXT int g_nShoulderAngle, g_nElbowAngle;
CONTROL_EXT int g_nArthrosisShoulderCount, g_nArthrosisElbowCount;
CONTROL_EXT int g_nArthrosisDividerShoulderCount, g_nArthrosisDividerElbowCount;#define ARTHROSIS_DIVIDER_SHOULDER_PERIOD 100
#define ARTHROSIS_DIVIDER_SHOULDER_INC 65
#define ARTHROSIS_DIVIDER_ELBOW_PERIOD 100
#define ARTHROSIS_DIVIDER_ELBOW_INC 60CONTROL_EXT int g_nShoulderDividerInc, g_nElbowDividerInc;void ArthrosisISR(void);//------------------------------------------------------------------------------
CONTROL_EXT int g_nArthrosisCheckCount;
#define ARTHROSIS_CHECK_PERIOD 50
void ArthrosisLimitCheck(void);#define SHOULDER_ANGLE_MIN 8192
#define SHOULDER_ANGLE_MAX 24576
#define ELBOW_ANGLE_MIN 4096
#define ELBOW_ANGLE_MAX 28672#define SHOULDER_HALF_PULSE 32000
#define ELBOW_HALF_PULSE 25600//------------------------------------------------------------------------------
void ShoulderGotoAngle(int nAngle);
void ElbowGotoAngle(int nAngle);//------------------------------------------------------------------------------
CONTROL_EXT int g_nShoulderAngleSet, g_nElbowAngleSet;
CONTROL_EXT int g_nShoulderAngleAdjustTime;
CONTROL_EXT int g_nElbowAngleAdjustTime;void ShoulderAngleSet(int nAngle);
void ElbowAngleSet(int nAngle);//==============================================================================
// END OF THE FILE : CONTROL.H
//------------------------------------------------------------------------------
#endif // __CONTROL__
■ 相关文献链接:
- 基于STM32对于三轴机械臂控制器设计
- 对于STM32F103三轴机械臂控制器进行基本功能测试-关节角度读取
- 对于STM32F103三轴机械臂控制器进行基本功能测试-上下运动功能
- 增加行星轮减速后机械臂调试
- 组装肩部带有减速器双轴机械臂组装与调试
- 两轴机械臂+机械爪整体控制板设计与机械爪控制调试
- 双关节机械臂+机械爪运动控制
- 57HSXXXXEIS一体化步进伺服驱动电机
- 42HS48EIS步进闭环电机最大转速
硬件结构AD设计工程文件:AD\XQWF\2020\机械臂\CNTINTERFACE.PcbDoc ↩︎
STM32单片机工程文件:STM32\Application\XQWF\2020\CNTSTM103\ ↩︎
对于STM32F103控制的三轴机械臂基本功能测试-关节转动控制相关推荐
- 基于STM32对于三轴机械臂控制器设计
简 介: 本文使用了STM32对于一款三轴机械臂进行初步驱动,调试他的各个关节的运动情况. 关键词: 机械臂,三轴机械臂,STM32 ➤ 01背景 在 组装肩部带有减速器双轴机械臂组装与调试 的调试基 ...
- 对于STM32F103三轴机械臂控制器进行基本功能测试-上下运动功能
简 介: 本文针对基于在基于STM32对于三轴机械臂控制器设计 中设计了控制电路板.本文记录对其在机械臂实际部件进行调试的过程. 关键词: STM32F103,机械臂,三轴,上下运动 ➤01 机械臂控 ...
- 对于STM32F103三轴机械臂控制器进行基本功能测试-关节角度读取
➤01 机械臂调试 1.简介 对 基于STM32对于三轴机械臂控制器设计 中对应的控制电路读取肩部和肘部两个 角度编码器 ST-3806-15-RS 数据进行调试. 2.接口电路1 ▲ 角度读取的相关 ...
- Rviz玩转三轴机械臂
前言 最近想加深ROS仿真机械臂的理解,所以笔者参考一些资料与博客,在ROS下搭个简单的三轴机械臂,在Rviz下实现各轴关节转动,如果后续有时间的话,可能会更新下Gazebo下仿真,如果时间不够的话, ...
- grbl控制3轴机械臂 原理 实现 (四) 之GRBL源码修改驱动三轴机械臂
往期回顾: 第一篇:grbl控制3轴机械臂 原理 实现 (一) 之2D机械臂模拟及实现 第二篇:grbl控制3轴机械臂 原理 实现 (二) 之3D机械臂模拟及实现 第三篇:grbl控制3轴机械臂 原理 ...
- 逆运动学:RRR型 2D 三轴机械臂的IK求解 | 机械臂运动学笔记(二)
任务: 给定末端的(x,y, \phi),求各轴角度( θ 1 , θ 2 , θ 3 \theta_1 , \theta_2, \theta_3 θ1,θ2,θ3) 先将多个空间几何拆解成平面 ...
- 三轴机械臂/三自由度四足单腿DH正逆运动学及matlab验证
实物模型 DH建立坐标系以及正逆运动学推导 Matlab验证 clear; clc; a1=-9.57*0.001;alpha1=pi/2; a2=-59.2*0.001; a3=-77*0.001; ...
- 基于STM32F103双轴机械臂完整电路板设计
➤01 机械臂设计 在 基于STM32对于三轴机械臂控制器设计 设计了机械臂的控制电路板.采用了双板分开设计方式.并分别进行了如下的测试: 1. 对于STM32F103三轴机械臂控制器进行基本 ...
- grbl控制3轴机械臂 原理 实现 (三) 之如何通过步进电机控制机械臂、插补算法
参考: 图形学入门 https://www.zhihu.com/question/20330720 https://zhuanlan.zhihu.com/p/30553006 https://www. ...
最新文章
- LeetCode: 344. Reverse String
- 【Android NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 )
- w ndows无法识别usb,电脑无法识别usb设备的解决方法
- 8支团队正在努力构建下一代Ethereum
- Python资料分享来袭,收下不谢!
- 在线打假!“鲁迅说过的话”检索系统上线 网友太热情系统一度崩溃
- 创建多个设备文件节点_使用DEVICE_ATTR实例分析
- 推荐 OS X 下最方便实用的六款解压缩软件
- MATLAB 内积外积混合积
- itext7接口和类概述以及pdf常见操作
- vcard怎么转excel vcf转excel神器教程
- 心存希望,幸福就会靠近你;心存梦想,机遇就会笼罩你;心存坚持,快乐就会常伴你;心存善念,阳光就会照耀你;心存美丽,温暖就会围绕你;心存他人,真情就会回报你;心存感恩,贵人就会青睐你。
- 电商行业特点以及理解电商的模式
- java http心跳_MQTT协议笔记之连接和心跳
- 重启w7计算机按那个键,win7电脑重启的快捷键
- 顺丰下单空运实际发陆运
- 【H.264】SPS 解析
- 开放世界游戏中的大地图的实现——内容制作篇/异次元篇
- vue3版本网页小游戏
- 2022华为杯数学建模B题——方形件组批优化问题
热门文章
- 新ITC提交APP常见问题与解决方法(Icon Alpha,Build version,AppIcon120x120)(2014-11-17)
- asp.net core 教程(七)-异常处理、静态文件
- 机器学习——大数据与MapReduce
- android下调试声卡驱动之概述
- 浅谈通信编程(二)--如何分离通信物理接口和应用程序
- 从强制卸载Office到强制安装WPS
- 第 127 章 Piranha - Cluster administation tools
- LeoFS —— 高可靠性的分布式对象存储系统
- PHP并发IO编程之路
- jquery插件,nocube