Arduino - 使用步进电机控制器通过 Web 绘图
组件和用品
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 |
关于这个项目
演示
如果您是 Arduino 的新手,您可以开始使用:
- 适用于新手的 Arduino 教程。
- 关于 Arduino 的电机
工作原理
当手指触摸网页中的绘图区域时,触摸点的 XY 坐标被发送到 Arduino。缩放坐标后,Arduino 将移动两个步进电机以将笔定位到该坐标。在移动期间,Arduino不断地将笔的轨迹发送到web app,web app在画布上绘制轨迹。
源代码
源代码包括两部分:Arduino代码和Web用户界面代码。
Arduino 代码
这是 arduino 代码,它在无限循环中运行:
- 从网页接收命令并根据命令执行任务。
- CMD_MOVE:通过控制两个步进电机将笔移动到一个位置
- CMD_PEN_UP:通过改变伺服电机的角度来抬笔
- CMD_PEN_DOWN:通过改变伺服电机的角度来降低笔
- 连续读取笔的当前位置并发送到网页
网络用户界面
代码见代码部分
- 提供用户界面
- 处理用户事件并向Arduino发送带有坐标的命令
- 从Arduino接收轨迹并在网页上绘制
remote_draw.php 是一个包含 Web 用户界面的文件。它需要存储在 PHPoC [WiFi] Shield 上。要将文件上传到 PHPoC [WiFi] Shield,请执行以下步骤:
- 复制以下代码并将其保存到 remote_draw.php 文件中。
- 安装 PHPoC 调试器
- 按照此说明通过微型 USB 电缆将 PHPoC 连接到 PHPoC [WiFi] Shield。注意必须为 Arduino 供电。
- 按照此说明上传remote_draw.php文件到PHPoC [WiFi] Shield
如何
- 为 PHPoC shield 或 PHPoC WiFi shield 配置网络信息
- 安装 PHPoC 库
- 安装 PHPoC 扩展库
- 编译并上传代码到Arduino
- 将网页用户界面上传到 PHPoC [WiFi] shield
- 打开 Serial Monitor 并复制 PHPoC Shield 的 IP 地址
- 通过 Web 浏览器访问 Web 用户界面:http://ip_address_of_shield /remote_draw.php
- 通过网络绘图
购买电子元件,您可以从utsource.net订购
适合初学者的最佳 Arduino 入门套件
查看适合初学者的最佳 Arduino 套件
函数参考
- Serial.begin()
- Serial.println()
- 延迟()
- millis()
- for 循环
- while 循环
- 否则
- 循环()
- 设置()
- String.toInt()
- String.substring()
- String.indexOf()
- String.remove()
- String.equals()
代码
- Arduino 代码
- 网络用户界面
Arduino 代码Arduino
#include#include #include #define MAX_X 55550 // 单位是步#define MAX_Y 68780 // 单位是步#define TOUCH_OFFSET 5000 // 单位是step#define PEN_STATE_UP 0#define PEN_STATE_DOWN 1#define CMD_PEN_UP 0#define CMD_PEN_DOWN 1#define CMD_MOVE 2#define STEP_MODE 32#define SPEED_X_COEF ((long)40 * STEP_MODE)#define SPEED_Y_COEF)#define SPEED_Y_COEF( ((long)1500 * STEP_MODE)#define SPEED_Y_MAX ((long)1500 * STEP_MODE)#define ACCEL_X_MAX ((long)6000 * STEP_MODE)#define ACCEL_Y_MAX ((long)6000 * STEP_MODE)#define STEP_STATE_STOP 0#define STEP_LOCK1 define RESOLUTION 500#define MIN_UPDATE_INTERVAL 100 // 毫秒PhpocServer server(80);ExpansionStepper stepX(14);ExpansionStepper stepY(13);伺服伺服;long preX =0;long preY =0;byte penState =PEN_STATE_UP;bool isUnlockedX;bool isUnlockedY =false;int forwardDirX =-1; /* 电机 X 向前移动时 XY 绘图仪的方向,取决于安装,应测试确定值*/int forwardDirY =+1; /* 电机 Y 向上移动时 XY 绘图仪的方向,取决于安装,应测试确定值*/unsigned long lastUpdateMillis;void penUp() {servo.write(110); penState =PEN_STATE_UP;}void penDown() {servo.write(180); penState =PEN_STATE_DOWN;}void xyWait() { while(stepX.getState()> 1 || stepY.getState()> 1);}void xyInit() { penUp(); stepX.setMode(STEP_MODE); stepX.setVrefStop(4); stepX.setVrefDrive(15); stepX.setResonance(120, 250); stepX.setSpeed(20000); stepX.setAccel(50000); stepY.setMode(STEP_MODE); stepY.setVrefStop(4); stepY.setVrefDrive(15); stepY.setResonance(120, 250); stepY.setSpeed(20000); stepY.setAccel(50000); // 将笔移动到 (0, 0) stepX.stepGotoSW(0, -forwardDirX); stepY.stepGotoSW(0, -forwardDirY);等待(); stepX.setPosition(0); stepY.setPosition(0); // 在第一次运行时取消注释此块,并根据 IDE 控制台中的值更改此文件的第 6、7 行和 index.php 的第 33 行中的值 /* // 检查最大步数 stepX.stepGotoSW(1, forwardDirX); stepY.stepGotoSW(1, forwardDirY);等待(); // 在 index.php 的第 45 行更改这些值 Serial.print(F("MAX_X:")); Serial.println(stepX.getPosition() * forwardDirX); Serial.print(F("MAX_Y:")); Serial.println(stepY.getPosition() * forwardDirY); */ xyGoto(TOUCH_OFFSET, TOUCH_OFFSET);等待(); stepX.setEioMode(0, EIO_MODE_LOCK); stepX.setEioMode(1, EIO_MODE_LOCK); stepY.setEioMode(0, EIO_MODE_LOCK); stepY.setEioMode(1, EIO_MODE_LOCK);}void xyGoto(long x, long y) { if(x (MAX_X - TOUCH_OFFSET)) x =MAX_X - TOUCH_OFFSET; if(y (MAX_Y - TOUCH_OFFSET)) y =MAX_Y - TOUCH_OFFSET; x *=forwardDirX; y *=forwardDirY; int32_t deltaX =x - stepX.getPosition(); int32_t deltaY =y - stepY.getPosition(); deltaX =abs(deltaX); deltaY =abs(deltaY);长速度X =SPEED_X_COEF * abs(deltaX);长速度Y =SPEED_Y_COEF * abs(deltaY); if(speedX> speedY) { if(speedX> SPEED_X_MAX) speedX =SPEED_X_MAX;双倍比率 =deltaY / (double)deltaX; speedY =(long) (ratio * speedX); } else { if(speedY> SPEED_Y_MAX) speedY =SPEED_Y_MAX;双倍比率 =deltaX / (double)deltaY; speedX =(long) (ratio * speedY); } 长加速度;长加速; if(speedX MIN_UPDATE_INTERVAL) isUpdate =true; long curX =stepX.getPosition(); long curY =stepY.getPosition();长 deltaX =curX - preX;长 deltaY =curY - preY; long dist =sqrt(pow(deltaX, 2) + pow(deltaY, 2)); if(dist> RESOLUTION) isUpdate =true; if(isUpdate ==false || dist ==0) return false; lastUpdateMillis =curMillis; preX =curX; preY =curY; sendPositionToWeb(); // 发送当前位置以显示在网络上}void sendPositionToWeb() { char wbuf[20]; long x =stepX.getPosition() * forwardDirX; long y =stepY.getPosition() * forwardDirY;字符串数据 =String(F("[")) + x + String(F(",")) + y + String(F(",")) + penState + String(F("]\n")); data.toCharArray(wbuf, data.length() + 1); server.write(wbuf, data.length());}void setup() { Serial.begin(9600);而(!串行); Phpoc.begin(PF_LOG_SPI | PF_LOG_NET); server.beginWebSocket("xy_plotter"); Serial.print("WebSocket 服务器地址:"); Serial.println(Phpoc.localIP());扩展.开始(460800);伺服.attach(8); /** 注意:对于第一次运行: * - 取消注释 xyInit() 中的最后一个块 * - 运行 Arduino 代码 * - 根据 IDE 中的值更改此文件的第 6、7 行和 index.php 的第 33 行中的值安慰。 **/ xyInit(); lastUpdateMillis =millis();}void loop() { // 等待新客户端:PhpocClient client =server.available(); if(client) { String data =client.readLine(); if(data) { //Serial.println(data);字节分隔符Pos1 =data.indexOf(':');字节分隔符Pos2 =data.lastIndexOf(':');字节 cmd =data.substring(0, separatorPos1).toInt(); long x =data.substring(separatorPos1 + 1, separatorPos2).toInt(); long y =data.substring(separatorPos2 + 1).toInt(); switch(cmd) { case CMD_PEN_DOWN:xyGoto(x, y); //xyWait(); while(stepX.getState()> 1 || stepY.getState()> 1) xyCheckUpdateToWeb(); penDown();休息; case CMD_PEN_UP://xyWait(); while(stepX.getState()> 1 || stepY.getState()> 1) xyCheckUpdateToWeb(); penUp();休息; case CMD_MOVE:xyGoto(x, y);休息; } } } xyCheckUpdateToWeb();}
Web 用户界面PHP
Arduino - PHPoC Shield - XY 绘图仪 WebSocket :null
制造工艺