"废物利用"也抄袭——“完全”DIY"绘图仪"<二、下位机程序设计>
就不说怎么组装了吧,一把辛酸泪。说程序,因为这有两把辛酸泪……一把给下位机的C代码一把为了VB.NET的图像处理……不过就上上一篇说的,它们可以正确运行了,并且今天克服了Arduino上电过程中步进电机没事瞎转悠的困难。
其实上位机和下位机的功能界定非常清晰:上位机解释图片为指令,下位机解释上位机指令为硬件动作——就俩步进和一个激光器。当然,如果有读卡器模块,完全可以把命令写成文件实现脱机打印。总体框架就是这样,那么下位机要实现的具体功能有哪些呢?
1、串口通讯:接收指令和发送请求。既然是通讯,校验是少不了的,我写了一点CRC8校验。
2、控制步进电机:这方面的文章很多,够学一会的。我修改了Stepper库,当然只是用它的大部分框架,这个框架么……哎
3、控制激光器:激光器这里调节亮度的时候使用了PWM,正好手头有若干L298N…………
4、X,Y轴限位:用外部中断来控制,需要注意的是,我用的Uno么有那么多中断口可以挥霍,所以全部的微动开关都是连接在一起的。我是并联的,所以未按下时应该时断开的;如果串联,那么未按下时应该是闭合的。
5、软复位功能:可以用软件控制Arduino重启,方法也搜了一些,有些看着高大上的却然并卵。所以用的看门狗。
大体就是这样吧,下面看一下部分代码:
void setup() {
Serial.begin(115200);
AboveStepper.setSpeed(aSpeed); //设置上步进电机每分钟转数
BelowStepper.setSpeed(bSpeed); //设置下步进电机每分钟转数
AboveStepper.SetEnabled(true); //初始化完成完成其他初始化之后再开启步进电机
BelowStepper.SetEnabled(true);
attachInterrupt(InterruptIntID, Interrupt, CHANGE); //高电平
DoxGoto0();
DoyGoto0();
while (!Serial) {}
Serial.println(r_Ready);
}
一、初始化函数:这个函数在板子重启后被运行一次。
a、首先初始化串口,需要注意的是,这个波特率在你的板子所支持的范围内,越高越好——速度差异很大的。在这种频繁收发数据的应用中,9600明显感觉非常慢。
b、设置步进电机的转速,然后开启步进电机。
c、附加外部中断,利用微动开关使x,y轴归零。需要注意的是,如果你的板子加电时有扰动,那么应该在附加外部中断之前使x,y轴倒退一定的安全距离。
d、等待串口就绪,发送准备就绪信号。
二、外部中断函数
void Interrupt() {
if (digitalRead(InterruptIntPin) == HIGH) {
CurState = 0;
}
else {
if (CurState == 0) { //发生不应有的中断
CurState = -1;
AboveStepper.steps_left = 0l; //清理各个电机剩余步数
BelowStepper.steps_left = 0l;
digitalWrite(LaserPin, 0); //关闭激光器
}
else if (CurState == c_xGoto0) {
CurState = -c_xGoto0;
}
else if (CurState == c_yGoto0) {
CurState = -c_yGoto0;
}
else if (CurState == c_lzGoto0) {
CurState = -c_lzGoto0;
}
else if (CurState == c_rzGoto0) {
CurState = -c_rzGoto0;
}
}
}
这个函数也非常清晰,当微动闭合时,证明某一个开关被触动,如果是程序控制的,那么更改当前状态以便退出正在运行的循环;如果是意外中断,那么关闭相应的硬件避免损坏。这个函数应该尽可能短,它在极为有限的时间内就应调用完成,所以一般采用全局变量进行控制,这里就是使用CurState。
三、运行时的“循环”函数——Loop
这个函数并不是一次运行的,它是被系统不断的反复调用。我的代码如下:
void loop() {
if (CurState == 0 || CurState == State_Stop) { //非中断状态
if (Serial.available()>=msgBuffSize) {
msgLen = Serial.readBytes(msgBuff, msgBuffSize); //读取消息
if (msgBuff[msgBuffSize - 1] == cal_crc_table(msgBuff)) {
CommandParsing(msgBuff); //处理消息
if (CurState != State_Stop) {
RequestData(); //请求数据
}
}else{
RerequestData();
}
}
}
}
这里添加了暂停的功能,所以看起来可能有点乱。首先在正常状态或暂停状态下,尝试读取串口获取指令,当获取到数据后,进行Crc8验证,若未通过则重新申请数据;否则对命令进行解释并执行,随后当不处于暂停状态时再次申请指令。
命令解释器就不详细说了,无非是一个大的分支结构。这里简要说一下这个AxiDraw用的双电机结构是怎么移动x,y轴的,其实很简单,你装起来之后用手转转就知道了。两个电机不同时针方向运行控制一轴,两个电机同方向运行控制另一轴。我的是这样的(Y+,Y-代表Y轴正方向和负方向上的电机):
a、Y+顺时针Y-逆时针→X轴向负方向运行
b、Y+顺时针Y-顺时针→Y轴向负方向运行
所以代码是这样的:
void DoxMove(long dBeat) {
int dir, step;
if (dBeat < 0) {
dir = -1;
step = -dBeat;
}else{
dir = 1;
step = dBeat;
}
for (int i = 0; i < step; i++) {
AboveStepper.step(dir);
BelowStepper.step(-dir);
}
}
void DoyMove(long dBeat) {
int dir, step;
if (dBeat < 0) {
dir = -1;
step = -dBeat;
}else{
dir = 1;
step = dBeat;
}
for (int i = 0; i < step; i++) {
AboveStepper.step(dir);
BelowStepper.step(dir);
}
}
void Do13Move(long dBeat) {
AboveStepper.step(dBeat);
}
void Do24Move(long dBeat) {
BelowStepper.step(dBeat);
}
当然,完全可以不用For循环。但是走斜线的时候感官上好像“绕远”,看着有点矬。然后是激光器控制,直接用PWM就可以了。最后,是软重启,用看门狗最通用,很稳定,无接线:
#include <avr/wdt.h>
void Soft_ReStart(){
do{
wdt_enable(WDTO_15MS); //开启看门狗计时器,然后不喂狗……就重启了。
for (;;){ }
} while (0);
}
就是这……
"废物利用"也抄袭——“完全”DIY"绘图仪"<二、下位机程序设计>的更多相关文章
- "废物利用"也抄袭——“完全”DIY"绘图仪"<三、上位机程序设计>
上位机的程序主要是解析图片和生成较好的代码,现在实现的功能有灰度打印,二值打印,轮廓打印,骨骼打印.当然,必不可少的是打印大小的控制.测试了一些图片,总体来说,打印速度依次加快,因为打印的内容依次减少 ...
- "废物利用"也抄袭——“完全”DIY"绘图仪"<一、准备工作>
上一个光驱造已经解体若干天了,因为事情很多arduino也不太熟悉,直到今天才做出了一个可以用的样本.当然,上位机和下位机代码都写好了,可以正常工作,但是由于电路知识还是中学那点没还给老师的,加以各种 ...
- "废物利用"也抄袭——废旧喷墨打印机和光驱DIY"绘图仪"
很长时间没有写博客,因为各种各样的事情占去大块时间,只有零碎时间偶尔在CSDN逛逛也偶尔回几个帖子.很久以前就看到一些光驱DIY雕刻机之类的,很是向往,最近这几天得闲就TB了一套Arduino UNO ...
- [No0000CA]什么是“普瑞马法则”?以及 如何利用“普瑞马法则”,三步克服惰性
一般在学习和生活中,我们都可能有这样的经验,就是当说想要作某件事情的时候,但过了好久发现还是没有做:或者觉得有力气使不出来:或者总觉得生活是灰色和抑郁的等等. 这类情况反映在生活中,就是生活好像总是被 ...
- Touch Bar 废物利用系列 | 在触控栏上显示 Dock 应用图标
都说 Intel 第八代 CPU 对比上代是牙膏不小心挤多了,而配备第八代 CPU 的 MacBook Pro,只有 Touch Bar 版本,虽然贵了一点,但就一个字 -- 买! 收到电脑后,兴冲冲 ...
- [自娱自乐] 4、超声波测距模块DIY笔记(四)——终结篇·基于C#上位机软件开发
前言 上一节我们已经基本上把超声波硬件的发射和接收模块全部做好了,接下来我们着手开发一个软硬结合的基于C#的平面定位软件! 目录 一.整体思路 二.效果提前展示 2-1.软件部分展示 2-2.硬件部分 ...
- 实验三 Java基本程序设计(2)
实验三 Java基本程序设计(2) ...
- 20145208 实验三 Java面向对象程序设计
20145208 实验三 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步 ...
- 利用lipo编译合并iPhone模拟器和真机通用的静态类
利用lipo编译合并iPhone模拟器和真机通用的静态类 如何编译静态类库,而且现在网上也有很多的教程,现在问题时我们编译好了的静态类库会时两个版本的.a文件,分别用于模拟器和iPhone真迹,因此M ...
随机推荐
- HDU 2896 病毒侵袭(AC自动机)题解
题意:给你n个模式串,再给你m个主串,问你每个主串中有多少模式串,并输出是哪些.注意一下,这里给的字符范围是可见字符0~127,所以要开130左右. 思路:用字典树开的时候储存编号,匹配完成后set记 ...
- tfn2k工具使用介绍
主要介绍tfn2k(Linux),因为它最著名嘛!主要分为使用说明 然后在说安装所以有点长 (注意:有的人拿VPS来做DDOS·问题是有的人发现了会关闭你VPS的·除非你认识他或者你自己有服务器而不是 ...
- (CLR via C#学习笔记)线程基础
一 使用线程的理由 1.可响应性(通常是对于客户端GUI应用程序);2.性能,多个CPU(或多核CPU)能并发执行多个线程,同时执行多个操作能提升性能. 二 线程开销 线程有空间(内存耗用)和时间(运 ...
- 农历03__ZC
代码,改自 农历01(http://www.cnblogs.com/cppskill/p/5930558.html) 1.main.cpp #include "Lunar_ZC.h" ...
- java set初始化问题
set在执行add方法时,多次报空指针异常,后来发现Set初始化时,如果是 Set<Type> set = null; 这样的话,在执行 set.add(element)的时候会报空指针异 ...
- HDU 4522 (恶心建图)
湫湫系列故事——过年回家 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...
- LeetCode 48
这种方法首先对原数组取其转置矩阵,然后把每行的数字翻转可得到结果,如下所示(其中蓝色数字表示翻转轴): 1 2 3 1 4 7 7 4 1 4 5 6 --> 2 5 ...
- Linux终端界面屏保
Linux终端界面屏保 在很多Linux使用者的认知里,都认为终端下的Linux操作界面是没有屏保的,只有像windows那样的图形界面下才有屏保.但是其实Linux下也是有屏保的,只不过是ASC ...
- 【hive】时间段为五分钟的统计
问题内容 今天遇到了一个需求,需求就是时间段为5分钟的统计.有数据的时间戳.对成交单量进行统计. 想法思路 因为数据有时间戳,可以通过from_unixtime()来获取具体的时间. 有了具体的时间, ...
- 别名的使用注意,""真坑。
我们使用别名都是使用as关键字. 大多数时候我们都会省略as关键字,然后后面直接加别名就好了.我的习惯是别名用双引号括起来. 今天因为这个习惯坑了我一大波 首先oracle的别名的规则: AS 别名 ...