一种写字机新构型——双臂连杆式运动机构

本文介绍了一种新型写字机构的设计,基于极点求积仪的启发,结构简化,控制算法复杂但灵活。文章详细探讨了数学理论推导,包括利用圆的方程求解关节坐标,以及上位机编程实现,包括图像处理、电机控制和通信协议。项目承诺开源,以分享作者的思考和创作过程。
摘要由CSDN通过智能技术生成

1.1 导入

网上关于写字机的主流机构多具有以下特征:x,y两垂直轴,丝杆或传动带驱动,虽然相关资料全面,控制算法简单,但体积大,结构搭建复杂,灵活性欠佳,于是我便想创造一种结构简单的机构,但哪种结构可以胜任呢?直到我看见极点求积仪,看到它能在平面上灵活移动,而且结构简单,关节运动量小,我便有了答案——制作一个类求积仪机构。

2.数学理论上的推导

2.1 方程求解

首先,以关节1所在位置建立坐标系,若我们已知2个臂长为m,n,要让机构末端到达点(a,b),那么问题的关键便在于求出关节2坐标(x,y)。实际上这等价为已知一个三角形的三边长与两点坐标,求另一点坐标。

尺规作图的思想告诉我们作三角形时可以在线段两端作圆(如下图),连接交点与线段两端,那这是否能给我们带来些启发呢?

不难想到,我们可以效仿其通过圆的方程构造出两个圆(如图),那么两个圆的交点不就是(x,y)吗?于是我们可以联立两方程,得出:

x-a2+y-b2=n2

x2+y2=m2

通过展开平方式与消元,可以得到关于一个未知数的二元一次方程,代入解析式即可得到方程的两个根,而根据作圆的联想可知,这两个根实则就是圆的两个交点,于是我们取正根,就得到了此方程的解了:

(计算过程省略)

2.2模拟与分析

我们把这个数学模型导入geogebra模拟一下,看看有什么发现

https://download.csdn.net/download/2202_75517449/88861294?spm=1001.2014.3001.5501

通过观察,我们可以得出:

  1. 当b=0时,方程无解;b<0时,转为另一个根
  2. 当y<0时,第一关节应该得到负角
  3. 运动范围是以原点为圆心,以m+n为半径的处于y轴正半轴的半圆
  4. 当(a,b)成线性运动时,角度呈非线性变化;这就意味着不能直接以固定频率驱动步进电机。

3.上位机计划与编写

3.1上层图像处理

本程序采用python编写,图像处理部分是opencv库,串口通讯部分是Serial库,图形化显示部分为tkinter库。

在图像处理方面,本程序调用opencv的Canny算法与轮廓识别(findContours)实现了对轮廓的提取,调用腐蚀算法细化得到了图片的“骨架”,通过合理设置参数,便可得到数据点了。

3.2笔的轨迹

前文提到角度的非线性变化,既然一段较长的线无法通过线性角度变化得到,那么可以把这项工作拆分成若干项简单的任务,具体些就是将直线光栅化,像素化,通过Bresenham算法即可完成。这个算法把复杂问题简单化,将无数微观变化积累成了宏观的角度的非线性变化。

此后,只要用pen类的实例化对象p遍历数据点,得到角度变化数据了。

3.3图形化

本程序控件布局如下:

这部分多是一些基本的工作,包括创建组件,设置大小位置,绑定回调函数等等,值得注意的是对绘图过程的可视化:

本程序通过对两种不同坐标系的转换,从而实现了过程的可视化

当然,还有对图像点的平移操作,在此不赘述了。

4下位机

4.1motor类

本程序定义了一个motor类,便于对各种电机类型适配,调用时创建对象即可,实际上这也体现了面向对象的思想。

class motor

{

public:

    u8 a, b, c, d, dir;

    int ps;

    motor(u8 ia, u8 ib, u8 ic, u8 id)

    {

        this->a = ia;

        this->b = ib;

        this->c = ic;

        this->d = id;

        pinMode(this->a, OUTPUT);

        pinMode(this->b, OUTPUT);

        pinMode(this->c, OUTPUT);

        pinMode(this->d, OUTPUT);

    }

    void stop()

    {

        digitalWrite(this->a, LOW);

        digitalWrite(this->b, LOW);

        digitalWrite(this->c, LOW);

        digitalWrite(this->d, LOW);

    }

    void move(u8 step, u8 dir)

    {

        u8 temp = step;

        if (dir == 0)

        {

            temp = 7 - step;

        }

        digitalWrite(this->a, movelist[temp % 8] / 8 % 2);

        digitalWrite(this->b, movelist[temp % 8] / 4 % 2);

        digitalWrite(this->c, movelist[temp % 8] / 2 % 2);

        digitalWrite(this->d, movelist[temp % 8] % 2);

    }

};

4.2通信协议

为便于上位机与下位机的通信,本程序设计了自己的通信协议:

/*

波特率 9600

PC发送:

1字节 xDir

2字节 yDir

3字节 zState

4&5字节 xPS

6&7字节 yPS

单片机发送: 0xff 表示打印完成

*/

4.3电机驱动

下位机中值得一提的地方就是电机驱动了。在主进程接收到相应的移动数据并解析完成后,会进入for循环,如果i是休眠时间的整数倍,那么执行一个脉冲。

            for (i = 0; i < f->ps * 550 + 1; i++)

            {

                delayMicroseconds(1);

                if (i % 550 == 0)

                {

                    f->move(fi, f->dir);

                }

                if (i % sleeptime == 0)

                {

                    u->move(ui, u->dir);

                }

            }

与直流有刷电机不同的是,步进电机无法通过占空比调节转速,只能通过频率改变,这就要求单片机可以在一时间发出不同频率的脉冲,我也原本以为只能使用多任务的方法实现,但过一段时间再想就想出来了这种算法,与前者相比,这种方法无需多任务较大的编译量,足够轻量化,简单化,只要delay()的时间准,执行速度快,就能输出大差不差的脉冲了。

  1. 总结

这是一种新型的写字机构型,在算法与结构上做了取舍,虽控制算法复杂,但好在结构简单,灵活性高,运动量小,可以适应多种情况。其从另一个角度上说,这也是机械臂在二维上的简单构思,继承了其优点。

此外,实践才是检验真理的唯一标准,程序免不了有bug,之后若在实践中发现问题,我定会努力改正。

最后,特别鸣谢网上技术资料的作者,本项目也会开源,以记录、分享我的一些思考与创作。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值