XTXB 发表于 2018-2-20 11:53:14

用stc15w4k32移植arduino小贱钟Plotclock

本帖最后由 XTXB 于 2018-2-20 19:02 编辑

大伙见过类似的东东吧?最早是老外用arduino做的开源项目,用的是avr芯片,春节闲来无事,移植到STC,供大家一乐。
本人业余电子爱好者,多年前从AVR入坑,得到坛友们的无私奉献,收获许多快乐,多谢了!到现在还是菜鸟一个,代码都是东拼西凑的,多多包涵。
在此特别感谢: 傻孩子,马潮,鸿哥,有名称的**,heicad,还有众多网友,当然更要感谢阿莫,感谢amoBBS!
arduino代码:https://github.com/9a/plotclock/blob/master/plotclock.ino
网友作品视频地址:http://v.youku.com/v_show/id_XODIxNTk4MzA4.html。
左图是STC完工成品,数码管显示时,分,星期,写字时数码管熄灭,右图是网友arduino作品。

STC芯片下载线只需四根,串口无需晶振,又不用复位电路,单面板DIY排版超级简洁方便,这也是我不用AVR芯片DIY的主要原因了。

三个舵机的电源端合在一起,电容躺着不占地方,数码管是单排的,把管脚弯了90°,装在TOP层,哦!数码管装倒了。

题外话,硅胶线(用30#细线)做下载线就是爽:软,耐高温,胶皮多次焊接不熔,拆普通杜邦线的插头焊上,爽得不要不要的。

用SolidWorks画的外壳,部分设计参照网友的外壳,在此感谢了。个人经验,PAL材料壳体厚度1.5mm比较好,强度够用,打印也迅速。

笔座XY坐标与舵机角度转换的数学模型,当初我看arduino程序时只敢照抄,后来画图仔细研究了一下,其实就是初中几何及三角函数而已。

C语言程序实现:------从xy坐标到舵机角度转换函数,有了以上的推导,C实现起来好像也不是那么复杂了。
***********************************************************/
float return_angle(float a, float b, float c)         //备用函数,已知ABC三边求AC夹角
{
      // cosine rule for angle between c and a
      return acos((a * a + c * c - b * b) / (2 * a * c));
}
//固定尺寸OL=L1,OT=L2,TH=L3∠TMO=120°,∠HTO=46.7°(实际测量角度)
void set_XY(double Tx, double Ty) 从xy坐标到舵机角度转换函数,
{
      float dx;float dy;float c;float a1;float a2;float Hx;float Hy;
      delay_ms(1);//写字速度调节
      // calculate triangle between pen, servoLeft and arm joint
      // cartesian dx/dy
      //左舵机臂长度L1,OT=L2
      dx = Tx - O1X;
      dy = Ty - O1Y;
      // polar lemgth (c) and angle (a1)
      c = sqrt(dx * dx + dy * dy); // 笔(Tx,Ty)到左舵机中心点L的距离TL
      a1 = atan2(dy, dx); //a1=(Tx,Ty)到左舵机中心点与X轴夹角a1=∠TLC,
      a2 = return_angle(L1, L2, c);//a2=LO与LT的夹角∠TLO
      write_Ms(1,floor(((a2 + a1 - M_PI) * SERVOFAKTORLEFT) + SERVOLEFTNULL));//驱动左舵机
      //左舵机角度∠OLC=∠TLO+∠TLC=a1+a2
      //舵机总角度180°(弧度3.14)对应总脉宽2000us,
      //角度与脉宽转换比例SERVOFAKTORLEFT=总脉宽2000us/总角度180°=2000/3.14=637
      //舵机臂安装起始角度=SERVOLEFTNULL
      a2 = return_angle(L2, L1, c);//a2=L2与C的夹角∠OTL
      //三叉支点H的坐标=(Hx,Hy)
      //L3与Y轴的夹角=a1-a2+46.7°
      //46.7°=0.815(OT与HT夹角,机械结构决定的)
      //∠MTH=∠0TG+∠OTH+180°=(∠LTH-∠LTO)+∠OTH+180°
      Hx = Tx + L3 * cos((a1 - a2 + 0.815) + M_PI);
      Hy = Ty + L3 * sin((a1 - a2 + 0.815) + M_PI);
      // calculate triangle between pen joint, servoRight and arm joint
      dx = Hx - O2X;
      dy = Hy - O2Y;
      c = sqrt(dx * dx + dy * dy);//C=HR
      a1 = atan2(dy, dx);//a1=∠HRC,
      a2 = return_angle(L1, 45, c);//a1=∠HRP,HP=45
      write_Ms(2,floor(((a1 - a2) * SERVOFAKTORRIGHT) + SERVORIGHTNULL));//驱动右舵机
      //右舵机角度∠PRC=∠MRC-∠MRP=a1-a2
}
//
C语言程序实现:------舵机角度与高电平脉宽的转换
舵机脉冲周期20ms0°-180°对应高电平0.5ms-2.5ms相差2000us,角度与脉宽转换比例 SERVOFAKTORLEFT=总脉宽/总角度=2000/3.14=637。
左舵机的驱动函数可以写成write_Ms(1,floor(((a1 + a2 - M_PI) * SERVOFAKTORLEFT) + SERVOLEFTNULL)); (floor是取整函数)
1为左舵机编号,由于舵机安装起始角度无法绝对准确,所以先减M_PI=180°,后加180°=SERVOLEFTNULL=2000作为可调补偿量,当初为这个一减一加困惑了很久。
这是arduino写的驱动函数:servo2.writeMicroseconds(floor(((a1 + a2 - M_PI) * SERVOFAKTORLEFT) + SERVOLEFTNULL));
右舵机初始跟左舵机垂直,可调补偿量SERVORIGHTNULL=1000,就是直接加90°。
由于设定字体的中心纵坐标为0,设定01Y=02Y=-25 笔尖位于蓝色中心线最左到最右,旋转角度为90°,舵机摇臂初始安装时与极限位置(橙色虚线)的夹角45°时最佳。

C语言程序实现:------3个舵机驱动脉冲的产生
整体思路:参照开源程序,占用一个16位定时器,连续输出3个舵机所需的高电平,加上剩下的低电平时间凑够舵机驱动周期20ms。
***********************************************************/

void write_Ms(unsigned char Channel,unsigned int value)//舵机驱动函数,channel=通道,value=高电平脉宽(550-2500)us
{
                TR0 = 1;//启动定时器0
                PWM_Value=(value*2);//时钟24MHz 定时器12分频 计数2次1us
                if(PWM_Value>5000)PWM_Value=5000;//脉冲宽度不大于2.5ms
                if(PWM_Value<1200)PWM_Value=1200;//脉冲宽度不小于0.6ms
}
void Timer0_Init(void)                        //servo定时器初始化@24MHz
{
                AUXR &= 0x7F;                //定时器时钟12T模式24MHz
                TMOD &= 0xF0;                //设置定时器模式
                TL0=(65536-5000)%256;//虽然后面都要重装,但初始化时还是不要太大为好
                TH0=(65536-5000)/256;
                TR0 = 1;//启动定时器0
                //ET0 = 1;//仅在写字时打开定时器0中断,数码管扫描及读时钟时要关闭中断
}
void timer0(void) interrupt 1 //连续输出3路高电平脉冲,剩下的时间为低电平补足20ms
{
                TR0 = 0;//关闭定时器0
                switch(order)
                        {
                              case 1:   
                                                PWM_OUT0=1; //开第0路高电平,
                                                TL0=(-PWM_Value)%256;//(-PWM_Value)=(65536-PWM_Value) 定时时间会更精准
                                                TH0=(-PWM_Value)/256;    //赋值第0路舵机高电平时间
                                                break;
                              case 2:
                                                PWM_OUT0=0;//关第0路高电平,开第1路高电平,
                                                PWM_OUT1=1;
                                                TL0=(-PWM_Value)%256;
                                                TH0=(-PWM_Value)/256;   //赋值第1路舵机高电平时间
                                                break;
                              case 3:
                                                PWM_OUT1=0; //关第1路高电平,开第2路高电平
                                                PWM_OUT2=1;
                                                TL0=(-PWM_Value)%256;
                                                TH0=(-PWM_Value)/256; //赋值第2路舵机高电平时间
                                                break;
                              case 4:   
                                                PWM_OUT2=0; //3路舵机低电平时间=20ms-3路高电平时间
                                                TL0=(25536+PWM_Value+PWM_Value+PWM_Value)%256;
                                                TH0=(25536+PWM_Value+PWM_Value+PWM_Value)/256;   
                                                order=0;
                                                break;
                        }
                                                TR0 = 1;//启动定时器0
                                                order++;
}

C语言程序实现:------直线运动插补(插入许多点逼近直线),实现从A(lastX,lastY)走直线到B(pX,pY),
/************************************************/
void drawTo(float pX, float pY) {
float dx; float dy; float c;
int i;
         // dx dy of new point
      dx = pX - lastX;//以上次点为坐标原点
      dy = pY - lastY;
      //path lenght in mm, times 4 equals 4 steps per mm
      c = floor(4 * sqrt(dx * dx + dy * dy));
      //计算两点之间直线距离并取整CxC=AxA+BxB
      if (c < 1) c = 1;
      for (i = 0; i <= c; i++) {
                // 每次走i/c ,逐点走完距离C
                set_XY(lastX + (i * dx / c), lastY + (i * dy / c));
      }
      lastX = pX;//存储此次位置坐标
      lastY = pY;
}
//
C语言程序实现:------圆弧运动插补(插入许多点逼近圆弧),弧的圆心(bx,by),半径radius,起始角度start,结束角度ende
/************************************************/
void bogenGZS(float bx, float by, float radius, int start, int ende, float sqee)
{//圆弧圆心(bx,by),圆弧半径radius,起始角度start,结束角度ende,X轴向比例sqee
float inkr = 0.05;//圆弧插补,逆时针每次+0.05°顺时针是-0.05°
float count = 0;
do {
      drawTo(sqee * radius * cos(start + count) + bx,radius * sin(start + count) + by);
      //三角函数X=斜边*cosα, Y=斜边*sinα,      
      count += inkr;//下一点旋转角度inkr
}
while ((start + count) <= ende);//到达角度ende,结束
}
//
C语言程序实现:------有了以上函数,如何写数字?
/************************************************/
case 5:   //在中心坐标(bx,by)处写数字5
    drawTo(bx + 2 * scale, by + 5 * scale);//走到起始位置
    lift(0);//落笔
    bogenGZS(bx + 5 * scale, by + 6 * scale, 6 * scale, -2.5, 2, 1);//从5的最下端逆时针画圆弧
    drawTo(bx + 5 * scale, by + 20 * scale);//画5的脖子
    drawTo(bx + 12 * scale, by + 20 * scale);//画5的顶上一横
    lift(1);//抬笔
    break;
C语言程序实现:------main流程
******************************************/
void main(void)
{
                unsigned char Last_ucTemp4=0;//分钟个位记录
                delay_ms(5);
                Init_devices();//初始化
                //ds3231_write_time();//时钟初始数据写入
                uiVoiceCnt=40;//开机短响                        
                delay1s();                        
      while (1)         
      {
                key_service_1_win_4_flash();//按键服务的应用程序
                display_service_1_win_6_flash(); //显示的窗口菜单服务程序
                delay1s();
                if(ucTemp4!=Last_ucTemp4){//如果分有变化,开始写字程序,每分钟写一次
                        P1|=0x3F;////0B xx11 1111;熄灭数码管
                        Last_ucTemp4=ucTemp4;//保存当前分钟值
                        IE2 &=~(1<<2);//关定时器2中断
                        ET0 = 1;//开定时器0中断
                     /*lift(0); //落笔   没用白板笔
                        drawTo(rubberx, rubbery); //停留在笔擦位置,小心撞笔,损坏舵机
                        delay1s();
                        lift(2); //抬笔 */               
                     /*lift(1); //落笔
                        drawTo(0, 25);//装配测试,笔从写字板左边走到右边
                        delay1s();               
                        drawTo(60, 25);      
                        delay1s(); */                  
                        Test_DrawTime();//写时间函数
                        IE2 |=(1<<2);//开定时器2中断,准备按键扫描,数码管显示,
                        ET0 = 0;//关定时器0中断,防止干扰         
                }
      }
}
//
C语言程序实现:------编译结果,code=13800 ,好家伙,有十几K!

sunshulin 发表于 2018-2-20 11:58:14

厉害,我这一假期就是睡觉了

ourdemo 发表于 2018-2-20 12:41:36

点赞,初中学了SIN,COS基本没用过{:sweat:}

su33691 发表于 2018-2-20 12:43:33

这个必须支持。

wxlcj 发表于 2018-2-20 15:55:51

牛!!!
真心佩服!

lisingch 发表于 2018-2-20 16:30:16

这个好玩。牛!

frank_88888 发表于 2018-2-20 16:39:30

支持!挺好玩的。

sisia 发表于 2018-2-20 16:50:49

厉害!支持楼主

atl0402 发表于 2018-2-20 18:45:22

挺好玩的。但是这钟也太能造了

wkman 发表于 2018-2-21 10:33:15

{:titter:}点赞,初中学了SIN,COS基本没用 {:victory:}{:lol:}

XTXB 发表于 2018-2-21 12:08:45

本帖最后由 XTXB 于 2018-2-22 07:55 编辑

新年好!多谢各位的点赞!春节还逛坛子的对电子都是真爱,要不咱们移植个更有意思的。https://github.com/grbl/grbl
工程量可能有点大,好在人家已经铺好了路,咱们只是探索一下,应该只是时间问题,有感兴趣的筒子吗?
我大致看了下雕刻机,写字机,3D打印机的开源程序,基本原理都是读取G码数据,然后控制XYZ。代码也都差不多。

aohu_2012 发表于 2018-2-21 12:56:50

大大的赞一个

瓶子 发表于 2018-2-21 16:06:44

厉害,大好的假期时间被我浪费了

lcw_swust 发表于 2018-2-21 22:35:09

不错,很有意思

love_zjb 发表于 2018-2-22 07:54:39

666,前排围观

fsmcu 发表于 2018-2-22 08:51:59

不错,楼主加油

foxpro2005 发表于 2018-2-22 20:00:59

不错,赞一个, 楼主DIY能力超强哇

Wisen 发表于 2018-2-22 23:24:12

太牛了,必须顶一下!

panjun10 发表于 2018-2-22 23:27:59

移植grbl不如Marlin啊 Marlin应用范围广一点

qiqirachel 发表于 2018-2-23 00:23:12

厉害了,这个假期就是吃喝睡玩抓螃蟹

zljcat3721 发表于 2018-2-23 08:24:44

不错,感谢楼主分享。我的3D打印机吃灰好久了,改天也仿一个

panjun10 发表于 2018-2-23 14:45:11

XTXB 发表于 2018-2-21 12:08
新年好!多谢各位的点赞!春节还逛坛子的对电子都是真爱,要不咱们移植个更有意思的。https://github.com/g ...

这个已经有某位大神移植到了stm32 上面了, 我比较感兴趣的是 marlin这个 只有很久以前 的一个 不完整的移植版

XTXB 发表于 2018-2-24 09:00:52

本帖最后由 XTXB 于 2018-2-24 10:11 编辑

panjun10 发表于 2018-2-23 14:45
这个已经有某位大神移植到了stm32 上面了, 我比较感兴趣的是 marlin这个 只有很久以前 的一个 不完整的 ...

marlin的步进电机驱动的确很牛,打印时加减速的声音听着就舒服,值得学习,正好有台3D打印机,机械方面都是现成的,板子也是现成的,把arduino移植到c,哈哈,更省事了

okplay 发表于 2018-2-24 09:59:07

用笔还是太消耗了。可以改成沙盘写字

https://www.elektor.com/arduino-controlled-sand-clock

XTXB 发表于 2018-2-24 10:02:06

本帖最后由 XTXB 于 2018-2-24 10:49 编辑

用沙盘,这都想得到,人才啊,赞!舵机精度很重要,4块5的舵机连个直线都画不直。

gagaguojia 发表于 2018-2-28 11:54:52

就喜欢这种高射炮打蚊子的做法,超贱超牛! 哈哈

bg4mna 发表于 2018-3-20 13:27:57

厉害,这个给小孩子做一个相对不错。

whxiaowang 发表于 2018-3-20 18:23:45

创意不错

duxingkei 发表于 2018-3-21 21:23:22

有意思,羡慕你们没事搞点这种创意玩的人,现在我已经变懒了。。。。

蚍蜉窝 发表于 2018-5-20 09:03:47

收藏,收藏,做个小玩具挺好的

zllhfl 发表于 2018-5-20 20:40:33

支持一下{:sweat:}

小李非刀 发表于 2018-5-21 12:23:03

楼主牛B得一塌糊涂,必须赞!

xiangbin099 发表于 2018-5-21 12:35:17

支持一下,谢谢分享

piaoran1314 发表于 2018-5-23 17:20:18

牛逼,这个很不错

Honey_comb 发表于 2018-6-12 13:52:05

mark,备用

taoworking 发表于 2018-6-12 14:12:48

厉害了,留个印备用。

surmenx 发表于 2018-6-13 20:16:36

好玩,改天做个玩玩

闲鱼翻身 发表于 2018-6-14 12:02:32

想问下这个机械结构哪买的?看着挺好玩的呀

XTXB 发表于 2018-6-17 15:45:05

闲鱼翻身 发表于 2018-6-14 12:02
想问下这个机械结构哪买的?看着挺好玩的呀

我有台3d打印机

shangxf 发表于 2018-6-17 22:21:18

不错
厉害了

闲鱼翻身 发表于 2018-6-19 10:07:00

XTXB 发表于 2018-6-17 15:45
我有台3d打印机

{:titter:} 好吧,只能默默口水下

huangxia6 发表于 2018-6-23 07:51:53

大神,非常不错!{:lol:}

leolong03 发表于 2018-6-26 09:28:00

三角函数......我会....那是不可能的了

HXDZ-AAA 发表于 2018-6-26 10:02:01

伟大数学家高斯说过,数学是科学之王。实际上高深技术最终拼的是数学。

XTXB 发表于 2018-6-27 09:51:01

本帖最后由 XTXB 于 2018-6-27 09:55 编辑

HXDZ-AAA 发表于 2018-6-26 10:02
伟大数学家高斯说过,数学是科学之王。实际上高深技术最终拼的是数学。

1999年,在任正非的支持下,华为公司在俄罗斯建立了专门的算法研究所,招聘了数十名全球顶级的数学家,创造性地用非线性数学多维空间逆函数解决了GSM多载波干扰问题。算法研究所突破了移动网络的几个特殊瓶颈,使华为成为全球第一家实现GSM多载波合并的公司,通过软件打通2G、3G和4G网络,使2G、3G、4G产品可以在同一平台上运行,不再需要一个波段一根天线,节省成本,还节省空间,这可能是华为在移动基站领域得以崛起的最重大的突破。

keil_c51 发表于 2019-1-31 03:03:51

机械臂 也是这个算法

love_zjb 发表于 2019-1-31 09:15:08

厉害了,亲

jack12345 发表于 2019-2-6 09:27:34

不错,很有意思!备用{:lol:}

changshs 发表于 2019-3-6 14:48:31

学习了,感谢楼主分享!~

armok. 发表于 2023-10-25 17:14:55

帖子移动通知:
原分论坛:8051/STC32【已下线】
目标分论坛:51单片机
移动时间:0小时之后
页: [1]
查看完整版本: 用stc15w4k32移植arduino小贱钟Plotclock