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

DIY Mesin Frais CNC 3 Sumbu VMC: Bangun Mesin Presisi

Tentang Proyek Ini

Model prototipe kami berbasis IoT sehingga menyediakan arsitektur yang dapat diskalakan untuk digunakan dari hampir mana saja dengan koneksi internet. Ini adalah CNC berukuran 350mm x 350mm dengan area kerja 250mm x 240mm, berjalan pada perangkat lunak kontrol gerak open source (GRBL). Bahkan hardware kami juga sebagian besar open source sehingga menjadi potongan biaya utama. Mesin ini dibuat sepenuhnya dari barang yang dibeli secara lokal dan dapat memproses kayu, plastik, karet keras, resin keras, dan sebagainya. Target utama kami adalah pembuatan PCB dengan biaya rendah.

Kemungkinan ukir kayu juga tersedia.

Kami berencana menambahkan dukungan pemotongan laser juga sebagai bagian dari proyek masa depan kami.

Karena sistem saat ini dapat dikontrol dari jaringan intranet lokal secara nirkabel, kami ingin menskalakannya lebih lanjut untuk membuat aplikasi web terdistribusi yang membuat dan menghubungkan ekosistem sejumlah perangkat seperti ini.

Kemungkinan dengan mesin kami adalah tak terbatas.

Model prototipe kami memiliki bingkai dasar yang terbuat dari profil aluminium berlubang 2020 dan penyangga L. Mesin ini memberikan daya sekitar 80-85 Watt dengan palang DC 2000 rpm. Ini menggunakan skema gerakan baut lead dan baut berputar dengan batang halus yang memiliki bantalan bola radial groove snap fit untuk operasi yang mulus di semua 3 sumbu.

Pitch lead minimum adalah 0.8mm/revolusi dengan 2000 langkah/revolusi kita memiliki resolusi 1600 untuk semua sumbu. Ukuran kasar mesin kami sekitar 430x430x330mm dan area kerja sekitar 270x170x65mm dengan akurasi posisi 0.04mm. Gantry sumbu Z kami dicetak 3D dari awal dengan dua batang pemandu.

Perjalanan sumbu Z adalah 4.8 cm dengan bit palang dipasang. Kami menggunakan alat pemotong V-bit 45° untuk tujuan ukir PCB, juga mendukung bit end mill 0.2mm hingga 1.8mm. Kami menggunakan motor stepper NEMA 23 dengan arus maksimum 3A untuk setiap sumbu penggerak utama. Motor didorong oleh driver A4988 2.5A dengan resolusi mikro-langkah maksimum 1/16 memberikan kita presisi pemotongan maksimal dengan biaya yang sangat ekonomis.

Untuk bagian IoT, kami telah membuatnya memungkinkan untuk mengontrol router CNC dari layar tanpa monitor seperti layar seluler/tablet (berfungsi sebagai HMI kami) dari mana saja dengan koneksi internet. Kami menggunakan Raspberry Pi dan router (keamanan) yang terhubung ke internet dan menjalankan web server untuk menyediakan antarmuka untuk mengontrol CNC kami secara nirkabel. Kami juga berencana untuk mendapatkan wawasan bagian mesin yang berharga seperti torsi motor waktu nyata, arus yang ditarik, getaran, kebisingan, dll. dan menggambar wawasan waktu nyata di platform web untuk kolaborasi yang lebih baik. Yang mungkin disebut di sektor manufaktur sebagai Industrial IoT (INDUSTRY 4.0).

Kode

Kode Sampel Gcode
(Scribbled version of C:\Users\ABDERR~1\AppData\Local\Temp\ink_ext_XXXXXX.svgISF45X @ 3000.00) ( unicorn.py --tab="plotter_setup" --pen-up-angle=50 --pen-down-angle=30 --start-delay=160 --stop-delay=150 --xy-feedrate=3000 --z-feedrate=150 --z-height=0 --finished-height=0 --register-pen=true --x-home=0 --y-home=0 --num-copies=1 --continuous=false --pause-on-layer-change=true C:\Users\ABDERR~1\AppData\Local\Temp\ink_ext_XXXXXX.svgISF45X ) G21 (metric ftw) G90 (absolute mode) G92 X0.00 Y0.00 Z0.00 (you are here) M300 S30 (pen down) G4 P160 (wait 160ms) M300 S50 (pen up) G4 P150 (wait 150ms) M18 (disengage drives) M01 (Was registration test successful?) M17 (engage drives if YES, and continue) M01 (Plotting layer 'Calque 1') (Polyline consisting of 29 segments.) G1 X16.85 Y4.97 F3000.00 ... This file has been truncated, please download it to see its full contents. 
Kode Stepper
//AMIT #include <Servo.h> #include <AFMotor.h> #define LINE_BUFFER_LENGTH 512 char STEP = MICROSTEP ; const int penZUp = 115; const int penZDown = 83; const int penServoPin =10 ; const int stepsPerRevolution = 48; Servo penServo; AF_Stepper myStepperY(stepsPerRevolution,1); AF_Stepper myStepperX(stepsPerRevolution,2); struct point { float x; float y; float z; }; struct point actuatorPos; float StepInc = 1; int StepDelay = 0; int LineDelay =0; int penDelay = 50; float StepsPerMillimeterX = 100.0; float StepsPerMillimeterY = 100.0; float Xmin = 0; float Xmax = 40; float Ymin = 0; float Ymax = 40; float Zmin = 0; float Zmax = 1; float Xpos = Xmin; float Ypos = Ymin; float Zpos = Zmax; boolean verbose = false; void setup() { Serial.begin( 9600 ); penServo.attach(penServoPin); penServo.write(penZUp); delay(100); myStepperX.setSpeed(600); myStepperY.setSpeed(600); Serial.println("Mini CNC Plotter alive and kicking!"); Serial.print("X range is from "); Serial.print(Xmin); Serial.print(" to "); Serial.print(Xmax); Serial.println(" mm."); Serial.print("Y range is from "); Serial.print(Ymin); Serial.print(" to "); Serial.print(Ymax); Serial.println(" mm."); } void loop() { delay(100); char line[ LINE_BUFFER_LENGTH ]; char c; int lineIndex; bool lineIsComment, lineSemiColon; lineIndex = 0; lineSemiColon = false; lineIsComment = false; while (1) { while ( Serial.available()>0 ) { c = Serial.read(); if (( c == '\n') || (c == '\r') ) { if ( lineIndex > 0 ) { line[ lineIndex ] = '\0'; if (verbose) { Serial.print( "Received : "); Serial.println( line ); } processIncomingLine( line, lineIndex ); lineIndex = 0; } lineIsComment = false; lineSemiColon = false; Serial.println("ok"); } else { if ( (lineIsComment) || (lineSemiColon) ) { if ( c == ')' ) lineIsComment = false; } else { if ( c <= ' ' ) { } else if ( c == '/' ) { } else if ( c == '(' ) { lineIsComment = true; } else if ( c == ';' ) { lineSemiColon = true; } else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) { Serial.println( "ERROR - lineBuffer overflow" ); lineIsComment = false; lineSemiColon = false; } else if ( c >= 'a' && c <= 'z' ) { line[ lineIndex++ ] = c-'a'+'A'; } else { line[ lineIndex++ ] = c; } } } } } } void processIncomingLine( char* line, int charNB ) { int currentIndex = 0; char buffer[ 64 ]; struct point newPos; newPos.x = 0.0; newPos.y = 0.0; while( currentIndex < charNB ) { switch ( line[ currentIndex++ ] ) { case 'U': penUp(); break; case 'D': penDown(); break; case 'G': buffer[0] = line[ currentIndex++ ]; buffer[1] = '\0'; switch ( atoi( buffer )){ case 0: case 1: char* indexX = strchr( line+currentIndex, 'X' ); char* indexY = strchr( line+currentIndex, 'Y' ); if ( indexY <= 0 ) { newPos.x = atof( indexX + 1); newPos.y = actuatorPos.y; } else if ( indexX <= 0 ) { newPos.y = atof( indexY + 1); newPos.x = actuatorPos.x; } else { newPos.y = atof( indexY + 1); indexY = '\0'; newPos.x = atof( indexX + 1); } drawLine(newPos.x, newPos.y ); actuatorPos.x = newPos.x; actuatorPos.y = newPos.y; break; } break; case 'M': buffer[0] = line[ currentIndex++ ]; buffer[1] = line[ currentIndex++ ]; buffer[2] = line[ currentIndex++ ]; buffer[3] = '\0'; switch ( atoi( buffer )){ case 300: { char* indexS = strchr( line+currentIndex, 'S' ); float Spos = atof( indexS + 1); if (Spos == 30) { penDown(); } if (Spos == 50) { penUp(); } break; } case 114: Serial.print( "Absolute position : X = " ); Serial.print( actuatorPos.x ); Serial.print( " - Y = " ); Serial.println( actuatorPos.y ); break; default: Serial.print( "Command not recognized : M"); Serial.println( buffer ); } } } } } void drawLine(float x1, float y1) { if (x1 >= Xmax) { x1 = Xmax; } if (x1 <= Xmin) { x1 = Xmin; } if (y1 >= Ymax) { y1 = Ymax; } if (y1 <= Ymin) { y1 = Ymin; } x1 = (int)(x1*StepsPerMillimeterX); y1 = (int)(y1*StepsPerMillimeterY); float x0 = Xpos; float y0 = Ypos; long dx = abs(x1-x0); long dy = abs(y1-y0); int sx = x0<x1 ? StepInc : -StepInc; int sy = y0<y1 ? StepInc : -StepInc; long i; long over = 0; if (dx > dy) { for (i=0; i<dx; ++i) { myStepperX.onestep(sx,STEP); over+=dy; if (over>=dx) { over-=dx; myStepperY.onestep(sy,STEP); } delay(StepDelay); } } else { for (i=0; i<dy; ++i) { myStepperY.onestep(sy,STEP); over+=dx; if (over>=dy) { over-=dy; myStepperX.onestep(sx,STEP); } delay(StepDelay); } } delay(LineDelay); Xpos = x1; Ypos = y1; } void penUp() { penServo.write(penZUp); delay(penDelay); Zpos=Zmax; digitalWrite(15, LOW); digitalWrite(16, HIGH); if (verbose) { Serial.println("Pen up!"); } } void penDown() { penServo.write(penZDown); delay(penDelay); Zpos=Zmin; digitalWrite(15, HIGH); digitalWrite(16, LOW); if (verbose) { Serial.println("Pen down."); } } 
Library
// Adafruit Motor shield library // copyright Adafruit Industries LLC, 2009 // this code is public domain, enjoy! #if (ARDUINO >= 100) #include "Arduino.h" #else #if defined(__AVR__) #include <avr/io.h> #endif #include "WProgram.h" #endif #include "AFMotor.h" static uint8_t latch_state; #if (MICROSTEPS == 8) uint8_t microstepcurve[] = {0, 50, 98, 142, 180, 212, 236, 250, 255}; #elif (MICROSTEPS == 16) uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255}; #endif AFMotorController::AFMotorController(void) { TimerInitalized = false; } void AFMotorController::enable(void) { pinMode(MOTORLATCH, OUTPUT); pinMode(MOTORENABLE, OUTPUT); pinMode(MOTORDATA, OUTPUT); pinMode(MOTORCLK, OUTPUT); latch_state = 0; latch_tx(); digitalWrite(MOTORENABLE, LOW); } void AFMotorController::latch_tx(void) { uint8_t i; digitalWrite(MOTORLATCH, LOW); digitalWrite(MOTORDATA, LOW); for (i=0; i<8; i++) { digitalWrite(MOTORCLK, LOW); if (latch_state & _BV(7-i)) { digitalWrite(MOTORDATA, HIGH); } else { digitalWrite(MOTORDATA, LOW); } digitalWrite(MOTORCLK, HIGH); } digitalWrite(MOTORLATCH, HIGH); } static AFMotorController MC; inline void initPWM1(uint8_t freq) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) TCCR2A |= _BV(COM2A1) | _BV(WGM20) | _BV(WGM21); TCCR2B = freq & 0x7; OCR2A = 0; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) TCCR1A |= _BV(COM1A1) | _BV(WGM10); TCCR1B = (freq & 0x7) | _BV(WGM12); OCR1A = 0; #elif defined(__PIC32MX__) #if defined(PIC32_USE_PIN9_FOR_M1_PWM) pinMode(9, OUTPUT); pinMode(11, INPUT); if (!MC.TimerInitalized) { T2CON = 0x8000 | ((freq & 0x07) << 4); TMR2 = 0x0000; PR2 = 0x0100; MC.TimerInitalized = true; } OC4CON = 0x8006; OC4RS = 0x0000; OC4R = 0x0000; #elif defined(PIC32_USE_PIN10_FOR_M1_PWM) pinMode(10, OUTPUT); pinMode(11, INPUT); if (!MC.TimerInitalized) { T2CON = 0x8000 | ((freq & 0x07) << 4); TMR2 = 0x0000; PR2 = 0x0100; MC.TimerInitalized = true; } OC5CON = 0x8006; OC5RS = 0x0000; OC5R = 0x0000; #else digitalWrite(11, LOW); #endif #else #error "This chip is not supported!" #endif #if !defined(PIC32_USE_PIN9_FOR_M1_PWM) && !defined(PIC32_USE_PIN10_FOR_M1_PWM) pinMode(11, OUTPUT); #endif } inline void setPWM1(uint8_t s) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) OCR2A = s; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) OCR1A = s; #elif defined(__PIC32MX__) #if defined(PIC32_USE_PIN9_FOR_M1_PWM) OC4RS = s; #elif defined(PIC32_USE_PIN10_FOR_M1_PWM) OC5RS = s; #else if (s > 127) { digitalWrite(11, HIGH); } else { digitalWrite(11, LOW); } #endif #else #error "This chip is not supported!" #endif } inline void initPWM2(uint8_t freq) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) TCCR2A |= _BV(COM2B1) | _BV(WGM20) | _BV(WGM21); TCCR2B = freq & 0x7; OCR2B = 0; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) TCCR3A |= _BV(COM1C1) | _BV(WGM10); TCCR3B = (freq & 0x7) | _BV(WGM12); OCR3C = 0; #elif defined(__PIC32MX__) if (!MC.TimerInitalized) { T2CON = 0x8000 | ((freq & 0x07) << 4); TMR2 = 0x0000; PR2 = 0x0100; MC.TimerInitalized = true; } OC1CON = 0x8006; OC1RS = 0x0000; OC1R = 0x0000; #else #error "This chip is not supported!" #endif pinMode(3, OUTPUT); } inline void setPWM2(uint8_t s) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) OCR2B = s; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) OCR3C = s; #elif defined(__PIC32MX__) OC1RS = s; #else #error "This chip is not supported!" #endif } inline void initPWM3(uint8_t freq) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) TCCR0A |= _BV(COM0A1) | _BV(WGM00) | _BV(WGM01); OCR0A = 0; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) TCCR4A |= _BV(COM1A1) | _BV(WGM10); TCCR4B = (freq & 0x7) | _BV(WGM12); OCR4A = 0; #elif defined(__PIC32MX__) if (!MC.TimerInitalized) { T2CON = 0x8000 | ((freq & 0x07) << 4); TMR2 = 0x0000; PR2 = 0x0100; MC.TimerInitalized = true; } OC3CON = 0x8006; OC3RS = 0x0000; OC3R = 0x0000; #else #error "This chip is not supported!" #endif pinMode(6, OUTPUT); } inline void setPWM3(uint8_t s) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) OCR0A = s; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) OCR4A = s; #elif defined(__PIC32MX__) OC3RS = s; #else #error "This chip is not supported!" #endif } inline void initPWM4(uint8_t freq) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) TCCR0A |= _BV(COM0B1) | _BV(WGM00) | _BV(WGM01); OCR0B = 0; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) TCCR3A |= _BV(COM1A1) | _BV(WGM10); TCCR3B = (freq & 0x7) | _BV(WGM12); OCR3A = 0; #elif defined(__PIC32MX__) if (!MC.TimerInitalized) { T2CON = 0x8000 | ((freq & 0x07) << 4); TMR2 = 0x0000; PR2 = 0x0100; MC.TimerInitalized = true; } OC2CON = 0x8006; OC2RS = 0x0000; OC2R = 0x0000; #else #error "This chip is not supported!" #endif pinMode(5, OUTPUT); } inline void setPWM4(uint8_t s) { #if defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega88__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega328P__) OCR0B = s; #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) OCR3A = s; #elif defined(__PIC32MX__) OC2RS = s; #else #error "This chip is not supported!" #endif } AF_DCMotor::AF_DCMotor(uint8_t num, uint8_t freq) { motornum = num; pwmfreq = freq; MC.enable(); switch (num) { case 1: latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B); MC.latch_tx(); initPWM1(freq); break; case 2: latch_state &= ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); MC.latch_tx(); initPWM2(freq); break; case 3: latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B); MC.latch_tx(); initPWM3(freq); break; case 4: latch_state &= ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); MC.latch_tx(); initPWM4(freq); break; } } void AF_DCMotor::run(uint8_t cmd) { uint8_t a, b; switch (motornum) { case 1: a = MOTOR1_A; b = MOTOR1_B; break; case 2: a = MOTOR2_A; b = MOTOR2_B; break; case 3: a = MOTOR3_A; b = MOTOR3_B; break; case 4: a = MOTOR4_A; b = MOTOR4_B; break; default: return; } switch (cmd) { case FORWARD: latch_state |= _BV(a); latch_state &= ~_BV(b); MC.latch_tx(); break; case BACKWARD: latch_state &= ~_BV(a); latch_state |= _BV(b); MC.latch_tx(); break; case RELEASE: latch_state &= ~_BV(a); latch_state &= ~_BV(b); MC.latch_tx(); break; } } void AF_DCMotor::setSpeed(uint8_t speed) { switch (motornum) { case 1: setPWM1(speed); break; case 2: setPWM2(speed); break; case 3: setPWM3(speed); break; case 4: setPWM4(speed); break; } } AF_Stepper::AF_Stepper(uint16_t steps, uint8_t num) { MC.enable(); revsteps = steps; steppernum = num; currentstep = 0; if (steppernum == 1) { latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) & ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); MC.latch_tx(); pinMode(11, OUTPUT); pinMode(3, OUTPUT); digitalWrite(11, HIGH); digitalWrite(3, HIGH); initPWM1(STEPPER1_PWM_RATE); initPWM2(STEPPER1_PWM_RATE); setPWM1(255); setPWM2(255); } else if (steppernum == 2) { latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B) & ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); MC.latch_tx(); pinMode(5, OUTPUT); pinMode(6, OUTPUT); digitalWrite(5, HIGH); digitalWrite(6, HIGH); initPWM3(STEPPER2_PWM_RATE); initPWM4(STEPPER2_PWM_RATE); setPWM3(255); setPWM4(255); } } void AF_Stepper::setSpeed(uint16_t rpm) { usperstep = 60000000 / ((uint32_t)revsteps * (uint32_t)rpm); steppingcounter = 0; } void AF_Stepper::release(void) { if (steppernum == 1) { latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) & ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); MC.latch_tx(); } else if (steppernum == 2) { latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B) & ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); MC.latch_tx(); } } void AF_Stepper::step(uint16_t steps, uint8_t dir, uint8_t style) { uint32_t uspers = usperstep; uint8_t ret = 0; if (style == INTERLEAVE) { uspers /= 2; } else if (style == MICROSTEP) { uspers /= MICROSTEPS; steps *= MICROSTEPS; } while (steps--) { ret = onestep(dir, style); delay(uspers/1000); steppingcounter += (uspers % 1000); if (steppingcounter >= 1000) { delay(1); steppingcounter -= 1000; } } if (style == MICROSTEP) { while ((ret != 0) && (ret != MICROSTEPS)) { ret = onestep(dir, style); delay(uspers/1000); steppingcounter += (uspers % 1000); if (steppingcounter >= 1000) { delay(1); steppingcounter -= 1000; } } } } uint8_t AF_Stepper::onestep(uint8_t dir, uint8_t style) { uint8_t a, b, c, d; uint8_t ocrb, ocra; ocra = ocrb = 255; if (steppernum == 1) { a = _BV(MOTOR1_A); b = _BV(MOTOR2_A); c = _BV(MOTOR1_B); d = _BV(MOTOR2_B); } else if (steppernum == 2) { a = _BV(MOTOR3_A); b = _BV(MOTOR4_A); c = _BV(MOTOR3_B); d = _BV(MOTOR4_B); } else { return 0; } if (style == SINGLE) { if ((currentstep/(MICROSTEPS/2)) % 2) { if (dir == FORWARD) { currentstep += MICROSTEPS/2; } else { currentstep -= MICROSTEPS/2; } } else { if (dir == FORWARD) { currentstep += MICROSTEPS; } else { currentstep -= MICROSTEPS; } } } else if (style == DOUBLE) { if (! (currentstep/(MICROSTEPS/2) % 2)) { if (dir == FORWARD) { currentstep += MICROSTEPS/2; } else { currentstep -= MICROSTEPS/2; } } else { if (dir == FORWARD) { currentstep += MICROSTEPS; } else { currentstep -= MICROSTEPS; } } } else if (style == INTERLEAVE) { if (dir == FORWARD) { currentstep += MICROSTEPS/2; } else { currentstep -= MICROSTEPS/2; } } if (style == MICROSTEP) { if (dir == FORWARD) { currentstep++; } else { currentstep--; } currentstep += MICROSTEPS*4; currentstep %= MICROSTEPS*4; ocra = ocrb = 0; if ( (currentstep >= 0) && (currentstep < MICROSTEPS)) { ocra = microstepcurve[MICROSTEPS - currentstep]; ocrb = microstepcurve[currentstep]; } else if ( (currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2)) { ocra = microstepcurve[currentstep - MICROSTEPS]; ocrb = microstepcurve[MICROSTEPS*2 - currentstep]; } else if ( (currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3)) { ocra = microstepcurve[MICROSTEPS*3 - currentstep]; ocrb = microstepcurve[currentstep - MICROSTEPS*2]; } else if ( (currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4)) { ocra = microstepcurve[currentstep - MICROSTEPS*3]; ocrb = microstepcurve[MICROSTEPS*4 - currentstep]; } } currentstep += MICROSTEPS*4; currentstep %= MICROSTEPS*4; if (steppernum == 1) { setPWM1(ocra); setPWM2(ocrb); } else if (steppernum == 2) { setPWM3(ocra); setPWM4(ocrb); } latch_state &= ~a & ~b & ~c & ~d; if (style == MICROSTEP) { if ((currentstep >= 0) && (currentstep < MICROSTEPS)) latch_state |= a | b; if ((currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2)) latch_state |= b | c; if ((currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3)) latch_state |= c | d; if ((currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4)) latch_state |= d | a; } else { switch (currentstep/(MICROSTEPS/2)) { case 0: latch_state |= a; break; case 1: latch_state |= a | b; break; case 2: latch_state |= b; break; case 3: latch_state |= b | c; break; case 4: latch_state |= c; break; case 5: latch_state |= c | d; break; case 6: latch_state |= d; break; case 7: latch_state |= d | a; break; } } MC.latch_tx(); return currentstep; } 

Proses manufaktur

  1. Buat LUMAZOID Sendiri: Visualisasi Musik Arduino DIY
  2. Buat Voltmeter Cerdas dengan Arduino & Smartphone – Proyek DIY Mudah
  3. Bangun Papan Skate VR DIY dengan Arduino, Google Cardboard, dan Bluetooth
  4. Mesin CNC Triple – Pembuatan Upgrade Premium
  5. Zen Garden CNC-Enabled End Table: Bangun Mebel Pintar Sendiri
  6. Buat Sendiri Perangkat Perawatan EMR Radionik Arduino
  7. Bangun Mesin CNC Fungsional Penuh dengan Arduino Nano R3
  8. Simulator Balap 2D DIY Menggunakan Arduino Nano & Servo SG90
  9. Vertical Machining & CNC VMC: A Comprehensive Introduction
  10. Mesin VMC Mini Dijelaskan: CNC Milling Kompak untuk Proyek Skala Kecil