menu
 
H-Grbl (PL)

For english, go here.

Jeśli podoba się Tobie moja praca wyślij dotację przez PayPal lub bezpośrednio.

Gotowe pliki do pobrania:

 H-Grbl v1.0 – oryginalne GRBL w wersji grbl-1.1h.20190825 po poniższych przeróbkach

diff_v1.0 – plik różnic pomiędzy oryginałem a „moją” wersją.

Proszę o niekopiowanie tych plików na inne strony.

Niniejszy projekt ma służyć uruchomieniu Grbl na układzie opartym na mostkach H.

Grbl is a no-compromise, high performance, low cost alternative to parallel-port-based motion control for CNC milling. It will run on a vanilla Arduino (Duemillanove/Uno) as long as it sports an Atmega 328.

Screenshot_20191107_141513

W sieci istnieje już taka próba, ale oparta na Grbl w wersji 0.7. W chwili pisania tej strony istnieje już wersja 1.1h. Dużo zmian, które warto mieć we własnych projektach. Ponieważ starałem się wprowadzać zmiany w możliwie „przenośny” sposób, przedstawiam tutaj instrukcję jak to zrobić:

– Po pierwsze, pobieramy ze strony grbl aktualną wersję oprogramowania i wypakowujemy ją w dowolnym miejscu (zakładam, że wykorzystujesz „oryginalną” wersję sterownika do innych projektów, więc biblioteka NIE ląduje do katalogu bibliotek).
– W katalogu grbl’a wyszukujemy edytujemy plik cpu_map.h, celem modyfikacji jest „wyłączenie” z używania portów STEPPERS_DISABLE_BIT oraz Z_LIMIT_BIT – portów, których będziemy używali do sterowania mostkami H. W tym celu wyszukujemy linie:

#define STEPPERS_DISABLE_BIT 0 i zamieniamy ją na #define STEPPERS_DISABLE_BIT 10
oraz
#define Z_LIMIT_BIT 3 // Uno Digital Pin 12 na #define Z_LIMIT_BIT 13 // Uno Digital Pin 12
oraz
#define Z_LIMIT_BIT 4 // Uno Digital Pin 12 na #define Z_LIMIT_BIT 14 // Uno Digital Pin 12

Generalnie trzeba to zmienić na wartość powyżej 7, wtedy arduino „modyfikuje” bit poza zakresem portu.

Warto, ale nie trzeba, zmienić plik grbl.h:

#define GRBL_VERSION "1.1h" na #define GRBL_VERSION "1.1h for H-bridge by San Zamoyski"

…dzięki czemu będziemy mieli jasną od Arduino informację z którą wersją mamy do czynienia i kto ją zrobił 😉

I teraz najtrudniejsza część. Do pliku stepper.c należy dodać (np. przed funkcją ISR(TIMER1_COMPA_vect)):

// B (digital pin 8 to 13)
 // C (analog input pins)
 // D (digital pins 0 to 7)
#define STEPPER_X_A1 (0x01<<PIND2)
 #define STEPPER_X_A2 (0x01<<PIND3)
 #define STEPPER_X_B1 (0x01<<PIND4)
 #define STEPPER_X_B2 (0x01<<PIND5)
#define STEPPER_Y_A1 (0x01<<PIND6)
 #define STEPPER_Y_A2 (0x01<<PIND7)
 #define STEPPER_Y_B1 (0x01<<PINB0)
 #define STEPPER_Y_B2 (0x01<<PINB4)
/*#define STEPPER_Z_A1 (0x01<<PINC0)
 #define STEPPER_Z_A2 (0x01<<PINC1)
 #define STEPPER_Z_B1 (0x01<<PINC2)
 #define STEPPER_Z_B2 (0x01<<PINC3)*/
//#define STEPPING_PORT_Z PORTC
 #define STEPPING_PORT_Y0 PORTD
 #define STEPPING_PORT_Y1 PORTB
 #define STEPPING_PORT_X PORTD
//#define STEPPING_DDR_Z DDRC
 //#define STEPPING_DDR_Y DDRD
 //#define STEPPING_DDR_X DDRB
#define ALL_STEPPER_PINS_X (STEPPER_X_A1|STEPPER_X_A2|STEPPER_X_B1|STEPPER_X_B2)
 #define ALL_STEPPER_PINS_Y (STEPPER_Y_A1|STEPPER_Y_A2|STEPPER_Y_B1|STEPPER_Y_B2)
 //#define ALL_STEPPER_PINS_Z (STEPPER_Z_A1 |STEPPER_Z_A2|STEPPER_Z_B1|STEPPER_Z_B2)
const int stepper_pins[2][4] = {
 {STEPPER_X_A1, STEPPER_X_A2, STEPPER_X_B1, STEPPER_X_B2},
 {STEPPER_Y_A1, STEPPER_Y_A2, STEPPER_Y_B1, STEPPER_Y_B2},
 //{STEPPER_Z_A1, STEPPER_Z_A2, STEPPER_Z_B1, STEPPER_Z_B2},
 };
//void convert_step(int dirs, int steps){
 void convert_step(){
 static unsigned int crrnt_step_x = 0;
 static unsigned int crrnt_step_y = 0;
//st.dir_outbits, st.step_outbits
if(st.step_outbits & (1<<X_STEP_BIT)) {
if(st.dir_outbits & (1<<X_DIRECTION_BIT)) {
 crrnt_step_x ++;
 if (crrnt_step_x >= 4)
 crrnt_step_x = 0;
 }
 else{
 if(crrnt_step_x == 0)
 crrnt_step_x = 4;
 crrnt_step_x -= 1;
 }
switch(crrnt_step_x) {
 case 0:
 STEPPING_PORT_X &= ~(stepper_pins[X_AXIS][0]|stepper_pins[X_AXIS][2]);
 STEPPING_PORT_X |= stepper_pins[X_AXIS][3] | stepper_pins[X_AXIS][1];
 break;
 case 1:
 STEPPING_PORT_X &= ~(stepper_pins[X_AXIS][1] | stepper_pins[X_AXIS][2]);
 STEPPING_PORT_X |= stepper_pins[X_AXIS][0] | stepper_pins[X_AXIS][3];
 break;
 case 2:
 STEPPING_PORT_X &= ~(stepper_pins[X_AXIS][1] | stepper_pins[X_AXIS][3]);
 STEPPING_PORT_X |= stepper_pins[X_AXIS][2] | stepper_pins[X_AXIS][0];
 break;
 case 3:
 STEPPING_PORT_X &= ~(stepper_pins[X_AXIS][0] | stepper_pins[X_AXIS][3]);
 STEPPING_PORT_X |= (stepper_pins[X_AXIS][1] | stepper_pins[X_AXIS][2]);
 break;
 return;
 }
 }
if(st.step_outbits & (1<<Y_STEP_BIT)) {
if(st.dir_outbits & (1<<Y_DIRECTION_BIT)) {
 crrnt_step_y ++;
 if (crrnt_step_y >= 4)
 crrnt_step_y = 0;
 }
 else{
 if(crrnt_step_y == 0)
 crrnt_step_y = 4;
 crrnt_step_y -= 1;
 }
switch(crrnt_step_y) {
 case 0:
 STEPPING_PORT_Y0 &= ~(stepper_pins[Y_AXIS][0]);
 STEPPING_PORT_Y0 |= stepper_pins[Y_AXIS][1];
STEPPING_PORT_Y1 &= ~(stepper_pins[Y_AXIS][2]);
 STEPPING_PORT_Y1 |= stepper_pins[Y_AXIS][3];
 break;
 case 1:
 STEPPING_PORT_Y0 &= ~(stepper_pins[Y_AXIS][1]);
 STEPPING_PORT_Y0 |= stepper_pins[Y_AXIS][0];
STEPPING_PORT_Y1 &= ~(stepper_pins[Y_AXIS][2]);
 STEPPING_PORT_Y1 |= stepper_pins[Y_AXIS][3];
 break;
 case 2:
 STEPPING_PORT_Y0 &= ~(stepper_pins[Y_AXIS][1]);
 STEPPING_PORT_Y0 |= stepper_pins[Y_AXIS][0];
STEPPING_PORT_Y1 &= ~(stepper_pins[Y_AXIS][3]);
 STEPPING_PORT_Y1 |= stepper_pins[Y_AXIS][2];
 break;
 case 3:
 STEPPING_PORT_Y0 &= ~(stepper_pins[Y_AXIS][0]);
 STEPPING_PORT_Y0 |= (stepper_pins[Y_AXIS][1]);
STEPPING_PORT_Y1 &= ~(stepper_pins[Y_AXIS][3]);
 STEPPING_PORT_Y1 |= (stepper_pins[Y_AXIS][2]);
 break;
 return;
 }
 }
 }

Powyższe to funkcja „tłumacząca” instrukcje dla sterowników na „instrukcje” dla mostków H.

Dodatkowo musimy tę funkcję wywołać tam gdzie trzeba oraz wyłączyć to co może nam przeszkadzać. Szukamy zatem wszystkich wystąpień `DIRECTION_PORT =` oraz `DIRECTION_PORT_DUAL =` i komentujemy linijki, w których to występuje za pomocą dwóch sleszy (//) lub je usuwamy (przede wszystkim w funkcji ISR(TIMER1_COMPA_vect)).
Następnie wyszukujemy miejsc gdzie występuje `STEP_PORT = ` i zastępujemy to funkcją convert_step();.

W funkcji void stepper_init() komentujemy wszystko co przed // Configure Timer 1: Stepper Driver Interrupt i dodajemy (po tym co zakomentowane):

DDRD = DDRD | 0b11111100; // sets pins 2 to 7 as outputs
DDRB = DDRB | 0b00010001; // sets pins 0 (pin 8) and 4 (pin 12)

Dodatkowo:

wyszukujemy funkcję ISR(TIMER0_OVF_vect) i komentujemy w jej ciele wszystko poza linią TCCR0B = 0;.
w funkcji ISR(TIMER0_COMPA_vect) można zamienić wszystko na convert_step();
w funkcji void st_reset() komentujemy wszystko od // Initialize step and direction port pins. do #endif

Na koniec tworzymy w tym katalogu nowy plik o nazwie H-Grbl.ino, wklejamy do niego:

/* ~ GRBL with L293d (H-Bridge) and DC Motor Pen mechanism ~
╦═╗╔╗ ╦╔═
By-- ╠╦╝╠╩╗╠╩╗ - 2016 Rakshith BK
╩╚═╚═╝╩ ╩
*
* No licences no copyrights, well may be MIT.
* Use modify distribute and do whatever you want
* And even though this code will not launch any Nukes,
* I'm not responsible for any destruction caused by it.!
*
* X-axis stepper --> 8, 9, 10, 11
* Y-axis stepper --> 4, 5, 6, 7
* DC motor pin for Pen --> 12 for Pen Up - M4
* for Pen Down - M3
*
*
* For Details and working --
*/

/*
* Moved to v1.1 by San Zamoyski 11-2019
* */

#include „grbl.h”

void setup() {

}

void loop() {

}

Uruchamiamy w arduino, wgrywamy i powinno działać od razu. Aby uruchomić wrzeciono (komenda M3), warto pamiętać o ustawieniu jego prędkości obrotowej (np. S500).

Generalnie, można by było oczyścić ten kod z rzeczy, które są wykonywane bez sensu, ale nie zagrażają one programowi, a ułatwiają ewentualne przeniesienie modyfikacji na następne wersje GRBL.