Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Pengontrol Plotter XY Berbasis Web dengan Arduino dan Pengontrol Motor Stepper

Komponen dan Perlengkapan

Pengontrol Plotter XY Berbasis Web dengan Arduino dan Pengontrol Motor Stepper
Arduino UNO
× 1
Pengontrol Plotter XY Berbasis Web dengan Arduino dan Pengontrol Motor Stepper
PHPoC WiFi Shield 2 for Arduino
× 1
Pengontrol Plotter XY Berbasis Web dengan Arduino dan Pengontrol Motor Stepper
PHPoC Stepper Motor Controller
× 2
Makeblock XY Plotter
× 1

Tentang Proyek Ini

Demonstrasi

Jika Anda baru menggunakan Arduino, Anda dapat memulai dengan:

Cara Kerja

Saat jari menyentuh area gambar pada halaman web, koordinat XY dari titik sentuhan dikirim ke Arduino. Setelah menyesuaikan koordinat, Arduino akan memindahkan dua motor stepper untuk menempatkan pena ke koordinat tersebut. Selama proses pergerakan, Arduino terus mengirim lintasan pena ke aplikasi web, dan aplikasi web menggambar lintasan tersebut pada kanvas.

Kode Sumber

Kode sumber terdiri dari dua bagian: kode Arduino dan kode Antarmuka Pengguna Web.

Kode Arduino

Ini adalah kode Arduino yang berjalan dalam loop tak terbatas untuk:

Antarmuka Pengguna Web

Lihat kode di bagian Kode

remote_draw.php adalah file yang berisi Antarmuka Pengguna Web. File ini perlu disimpan pada PHPoC [WiFi] Shield. Untuk mengunggah file ke PHPoC [WiFi] Shield, silakan lakukan langkah berikut:

Cara Melakukan

Untuk membeli komponen elektronik, Anda dapat memesannya dari utsource.net

The Best Arduino Starter Kit for Beginner

Lihat The Best Arduino Kit for Beginners


Referensi Fungsi

Kode

Kode ArduinoArduino
#include <Phpoc.h> #include <PhpocExpansion.h> #include <Servo.h> #define MAX_X 55550 // unit is step #define MAX_Y 68780 // unit is step #define TOUCH_OFFSET 5000 // unit is 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 ((long)40 * STEP_MODE) #define SPEED_X_MAX ((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_STATE_LOCK 1 #define RESOLUTION 500 #define MIN_UPDATE_INTERVAL 100 // in millisecond PhpocServer server(80); ExpansionStepper stepX(14); ExpansionStepper stepY(13); Servo servo; long preX = 0; long preY = 0; byte penState = PEN_STATE_UP; bool isUnlockedX = false; bool isUnlockedY = false; int forwardDirX = -1; /* direction of XY plotter when motor X move forward, depending on installization, It should be tested to determine the values*/ int forwardDirY = +1; /* direction of XY plotter when motor Y move up, depending on installization, It should be tested to determine the values*/ 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); // move pen to (0, 0) stepX.stepGotoSW(0, -forwardDirX); stepY.stepGotoSW(0, -forwardDirY); xyWait(); stepX.setPosition(0); stepY.setPosition(0); // uncomment this block for the first run and change the value in line 6, 7 of this file and line 33 of index.php according to value in IDE console /* // check max steps stepX.stepGotoSW(1, forwardDirX); stepY.stepGotoSW(1, forwardDirY); xyWait(); // change these value in line 45 of index.php 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); xyWait(); 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 < TOUCH_OFFSET) x = TOUCH_OFFSET; else if(x > (MAX_X - TOUCH_OFFSET)) x = MAX_X - TOUCH_OFFSET; if(y < TOUCH_OFFSET) y = TOUCH_OFFSET; else 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); long speedX = SPEED_X_COEF * abs(deltaX); long speedY = SPEED_Y_COEF * abs(deltaY); if(speedX > speedY) { if(speedX > SPEED_X_MAX) speedX = SPEED_X_MAX; double ratio = deltaY / (double)deltaX; speedY = (long) (ratio * speedX); } else { if(speedY > SPEED_Y_MAX) speedY = SPEED_Y_MAX; double ratio = deltaX / (double)deltaY; speedX = (long) (ratio * speedY); } long accelX; long accelY; if(speedX < speedY) { accelY = ACCEL_Y_MAX; double ratio = accelY / (double)speedY; accelX = (long) (ratio * speedX); } else { accelX = ACCEL_X_MAX; double ratio = accelX / (double)speedX; accelY = (long) (ratio * speedY); } if(deltaX != 0) stepX.command(F("goto %ld %lu %lu"), x, speedX, accelX); if(deltaY != 0) stepY.command(F("goto %ld %lu %lu"), y, speedY, accelY); } void xyCheckUpdateToWeb() { bool isUpdate = false; unsigned long curMillis = millis(); if((curMillis - lastUpdateMillis) > MIN_UPDATE_INTERVAL) isUpdate = true; long curX = stepX.getPosition(); long curY = stepY.getPosition(); long deltaX = curX - preX; long 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(); // send current postion to display on web } void sendPositionToWeb() { char wbuf[20]; long x = stepX.getPosition() * forwardDirX; long y = stepY.getPosition() * forwardDirY; String data = 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); while(!Serial) ; Phpoc.begin(PF_LOG_SPI | PF_LOG_NET); server.beginWebSocket("xy_plotter"); Serial.print("WebSocket server address : "); Serial.println(Phpoc.localIP()); Expansion.begin(460800); servo.attach(8); /** NOTE: For the first run: * - uncomment the last block in xyInit() * - run Arduino code * - change the value in line 6, 7 of this file and line 33 of index.php according to value in IDE console. **/ xyInit(); lastUpdateMillis = millis(); } void loop() { // wait for a new client: PhpocClient client = server.available(); if(client) { String data = client.readLine(); if(data) { //Serial.println(data); byte separatorPos1 = data.indexOf(':'); byte separatorPos2 = data.lastIndexOf(':'); byte 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(); break; case CMD_PEN_UP: //xyWait(); while(stepX.getState() > 1 || stepY.getState() > 1) xyCheckUpdateToWeb(); penUp(); break; case CMD_MOVE: xyGoto(x, y); break; } } } xyCheckUpdateToWeb(); } 
Antarmuka Pengguna WebPHP
<!DOCTYPE html> <html> <head> <title>Arduino - PHPoC Shield - XY Plotter</title> <meta name="viewport" content="width=device-width, initial-scale=0.7"> <style> body { text-align: center; background-color: #33C7F2; } #canvas { margin-right: auto; margin-left: auto; position: relative; background-color: #FFFFFF; } canvas { position: absolute; left: 0px; top: 0px; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; /* nice webkit native scroll */ } #layer1 { z-index: 2; } #layer2 { z-index: 1; } #layer3 { z-index: 0; } </style> <script> var PEN_STATE_UP = 0; var PEN_STATE_DOWN = 1; var CMD_PEN_UP = 0; var CMD_PEN_DOWN = 1; var CMD_MOVE = 2; var RESOLUTION = 1000; var MIN_UPDATE_INTERVAL = 100; // in millisecond var MAX_X = 55550, MAX_Y = 68780; var CANVAS_WIDTH = 0, CANVAS_HEIGHT = 0; var ws = null; var canvas = null; var layer1 = null, layer2 = null, layer3 = null; var ctx1 = null, ctx2 = null, ctx3 = null; var touchState = 0; var touchStepX = 0, touchStepY = 0; /* unit is step */ var touchPixelX = 0, touchPixelY = 0; /* unit is pixel */ var plotterX = 0, plotterY = 0; var plotterPenState = PEN_STATE_UP; var lastUpdateMillis; var buffer = ""; function init() { canvas = document.getElementById("canvas"); layer1 = document.getElementById("layer1"); /* for drawing current postion, which is received from XY plotter */ layer2 = document.getElementById("layer2"); /* for drawing trajatory of XY plotter, which is received from XY plotter*/ layer3 = document.getElementById("layer3"); /* for drawing the current touch postion, which is inputed by user on screen */ ctx1 = layer1.getContext("2d"); ctx2 = layer2.getContext("2d"); ctx3 = layer3.getContext("2d"); layer1.addEventListener("touchstart", mouse_down); layer1.addEventListener("touchend", mouse_up); layer1.addEventListener("touchmove", mouse_move); layer1.addEventListener("mousedown", mouse_down); layer1.addEventListener("mouseup", mouse_up); layer1.addEventListener("mousemove", mouse_move); canvasResize(); var d = new Date(); lastUpdateMillis = d.getTime(); } function ws_onmessage(e_msg) { buffer += e_msg.data; var pos = buffer.indexOf('\n'); if(pos == -1) return; var data = buffer.substring(0, pos); buffer = buffer.substring(pos + 1); var arr = JSON.parse(data); plotterX = arr[0]; plotterY = arr[1]; var newPlotterPenState = arr[2]; /* convert step unit to pixel unit */ plotterX = Math.round(plotterX * CANVAS_WIDTH / MAX_X); plotterY = -Math.round(plotterY * CANVAS_HEIGHT / MAX_Y); /* draw current postion of plotter*/ ctx1.clearRect(0, 0, CANVAS_WIDTH, -CANVAS_HEIGHT); ctx1.beginPath(); ctx1.arc(plotterX, plotterY, 7, 0, 2*Math.PI); ctx1.fill(); /* draw trajatory of plotter only when pen down */ if(plotterPenState == PEN_STATE_UP && newPlotterPenState == PEN_STATE_DOWN) ctx2.beginPath(); if(newPlotterPenState == PEN_STATE_DOWN) { ctx2.lineTo(plotterX, plotterY); ctx2.stroke(); } plotterPenState = newPlotterPenState; } function ws_onopen() { document.getElementById("ws_state").innerHTML = "OPEN"; document.getElementById("wc_conn").innerHTML = "Disconnect"; } function ws_onclose() { document.getElementById("ws_state").innerHTML = "CLOSED"; document.getElementById("wc_conn").innerHTML = "Connect"; ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; } function wc_onclick() { if(ws == null) { ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/xy_plotter", "text.phpoc"); document.getElementById("ws_state").innerHTML = "CONNECTING"; ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; } else ws.close(); } function event_handler(event, type) { // convert coordinate if(event.targetTouches) { if(event.targetTouches.length > 1) return false; touchPixelX = event.targetTouches[0].pageX - canvas.offsetLeft; touchPixelY = event.targetTouches[0].pageY - canvas.offsetTop - CANVAS_HEIGHT; } else { touchPixelX = event.offsetX; touchPixelY = event.offsetY - CANVAS_HEIGHT; } /* convert from pixel to step */ var newTouchStepX = Math.round(touchPixelX / CANVAS_WIDTH * MAX_X); var newTouchStepY = Math.round((-touchPixelY) / CANVAS_HEIGHT * MAX_Y); if(type == "MOVE") { /* check update condition to avoid sending too much data to plotter */ var isUpdate = false; var d = new Date(); var curMillis = d.getTime(); if((curMillis - lastUpdateMillis) > MIN_UPDATE_INTERVAL) { isUpdate = true; } var deltaX = newTouchStepX - touchStepX; var deltaY = newTouchStepY - touchStepY; var dist = Math.sqrt( Math.pow(deltaX, 2) + Math.pow(deltaY, 2) ); if(dist > RESOLUTION) isUpdate = true; if(isUpdate == false) return false; lastUpdateMillis = curMillis; } touchStepX = newTouchStepX; touchStepY = newTouchStepY; drawXYline(); return true; } function mouse_down() { event.preventDefault(); event_handler(event, "DOWN"); sendToPlotter(CMD_PEN_DOWN, touchStepX, touchStepY); touchState = 1; } function mouse_up() { event.preventDefault(); touchState = 0; sendToPlotter(CMD_PEN_UP, touchStepX, touchStepY); } function mouse_move() { event.preventDefault(); if(touchState == 1) { if(event_handler(event, "MOVE")) sendToPlotter(CMD_MOVE, touchStepX, touchStepY); } } function sendToPlotter(cmd, x, y) { if(ws != null && ws.readyState == 1) ws.send(cmd + ":" + touchStepX + ":" + touchStepY + "\r\n"); } function canvasClear() { ctx2.clearRect(0, 0, CANVAS_WIDTH, -CANVAS_HEIGHT); /* only clear trajatory */ } function canvasResize() { var width = Math.round(window.innerWidth*0.95); var height = Math.round(window.innerHeight*0.95) - 100; var temp_height = Math.round(width*MAX_Y/MAX_X); if(temp_height <= height) { CANVAS_WIDTH = width; CANVAS_HEIGHT = temp_height; } else { CANVAS_WIDTH = height*MAX_X/MAX_Y; CANVAS_HEIGHT = height; } canvas.style.width = CANVAS_WIDTH + "px"; canvas.style.height = CANVAS_HEIGHT + "px"; layer1.width = CANVAS_WIDTH; layer1.height = CANVAS_HEIGHT; layer2.width = CANVAS_WIDTH; layer2.height = CANVAS_HEIGHT; layer3.width = CANVAS_WIDTH; layer3.height = CANVAS_HEIGHT; ctx1.translate(0, CANVAS_HEIGHT); ctx2.translate(0, CANVAS_HEIGHT); ctx3.translate(0, CANVAS_HEIGHT); ctx1.fillStyle = "#00979d"; ctx2.lineWidth = 3; ctx2.strokeStyle = "black"; ctx3.strokeStyle = "00FFFF"; } function drawXYline() { ctx3.clearRect(0, 0, CANVAS_WIDTH, -CANVAS_HEIGHT); ctx3.beginPath(); ctx3.moveTo(0, touchPixelY); ctx3.lineTo(CANVAS_WIDTH, touchPixelY); ctx3.moveTo(touchPixelX, 0); ctx3.lineTo(touchPixelX, -CANVAS_HEIGHT); ctx3.stroke(); } window.onload = init; </script> </head> <body onresize="canvasResize()"> <br> <div id="canvas"> <canvas id="layer1"></canvas> <canvas id="layer2"></canvas> <canvas id="layer3"></canvas> </div> <p>WebSocket : <span id="ws_state">null</span></p> <button id="wc_conn" type="button" onclick="wc_onclick();">Connect</button> <button type="button" onclick="canvasClear();">Clear</button> </body> </html> 

Proses manufaktur

  1. Membangun DTMF Decoder Hanya Menggunakan Arduino – Tidak Perlu IC Tambahan
  2. Sistem Pencahayaan DMX Dikonrol Web – Kontroler Master Arduino
  3. Robot Deteksi Manusia Berbasis Arduino Uno: Integrasi Sensor Langkah demi Langkah
  4. Pengontrol USB Game Arduino DIY – Buat Gamepad Tinggi Performa Sendiri
  5. SERENA: Sistem Alarm Kustom Arduino Mega 2560 dengan Layar Sentuh TFT LCD
  6. Bangun Kendaraan Jarak Jauh Terkontrol Android dengan Motor Shield Raspberry Pi
  7. Buat Robot Pengikuti Garis Otonom dengan Arduino UNO
  8. Kendalikan Rover Arduino dengan Mulus menggunakan Firmata dan Gamepad Xbox One
  9. Arduino UNO & WiFi Shield: Tampilan Suhu Real-Time di Web melalui Serial
  10. Amankan Arduino dengan Pola Unlock Web – Pengaturan Mudah dan Kendali Jarak Jauh