"废物利用"也抄袭——“完全”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 ...
随机推荐
- 初识PHP(三)面向对象特性
PHP5开始支持面向对象的编程方式.PHP的面向对象编程方法和别的语言区别不大,下面对PHP面向编程基本语法进行简单记录. 一.声明对象 声明方法: class Say{ public functio ...
- windows下利用批处理脚本监控程序
1.要监控的程序为使用cygwin环境编译的exe可执行文件hello.exe,源码如下: #include <stdio.h> #include <unistd.h> voi ...
- Redis并发竞争
Redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘.由于单线程所以Redis本身并没有锁的概念,多个客户端连接并不存在竞争关系,但是利用jedis等客户端对Redi ...
- c++指向指针的指针与 c++指针作为函数参数传递问题
一直搞不明白,c++中指针到底是个啥东西,今天遇到到c++,指向指针的指针的问题,突然有点开窍了. 举个例子: int main(int argc, char** argv){ int a[5]={1 ...
- Java之试题
1.面向对象编程的三大特性是什么? 2.String 和StringBuffer的区别 3.说出ArrayList,Vector, LinkedList的存储性能和特性 4.Collection 和 ...
- nodejs使用multiparty模块实现文件上传(另附express.bodyParser()的说明)
最近师弟师妹们在用formidable做文件上传的时候会出现form.parse()不会触发的问题,在stackoverflow也没有找到答案,反而是几个答案推荐使用multiparty来代替,因为那 ...
- JavaScript--练习1--99乘法表
JavaScript--练习1--99乘法表 一.心得 二.代码 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" &quo ...
- Jbuilder(3300✨)
https://github.com/rails/jbuilder Jbuilder(3300✨) Jbuilder gives you a simple DSL for declaring JSON ...
- 多目标跟踪方法 NOMT 学习与总结
多目标跟踪方法 NOMT 学习与总结 ALFD NOMT MTT 读 'W. Choi, Near-Online Multi-target Tracking with Aggregated Local ...
- 个人知识管理系统Version1.0开发记录(06)
demo view 夜已深,我们先简单演示一下,完成一个小段落了.涉及工具及技术知识:图形处理软件photoshop cs6,js类库ext. 思路如下: 1.下载ps6,有破解版本的,dll文件覆盖 ...