mi ero promesso di non costruire più CNC e invece ci sono cascato di nuovo... non ho resistito!
Questa volta però è un pò diverso perchè l'aspetto più importante del progetto sul quale ho speso più tempo ed energie non è tanto la parte meccanica quanto quella software, non ho voluto utilizzare soluzioni già pronte ma inventarmene uno tutto mio mettendo insieme pezzi di codice opensource.
L'idea è quella di realizzare una lavagna auto cancellabile che potesse scrivere e disegnare in tempo reale attraverso un'interfaccia web e quindi anche da uno smartphone.
A cosa mi serve? non lo so! faccio questo più che altro per studio e ricerca, chissà se gli troverò mai un utilizzo... anche se a pensarci bene però una mezza idea ce l'avrei!
Mi piacerebbe (ma devo avere il consenso della moglie) posizionare la lavagna in un posto tipo in cucina appesa al muro e automatizzare la stampa di messaggi automatici come ad esempio qualche notizia presa via web oppure il meteo di oggi, gli appuntamenti della giornata recuperati da Google Calendar,un disegno fatto a mano, note/appunti scritti quando sono in auto e tanto altro... per adesso ci gioca mio figlio con il Tablet.
Per agevolare la lettura di questo articolo ho organizzato i contenuti in macro-sezioni:
- Componentistica
- Logica di funzionamento
- Meccanica
- Elettronica
- Software
- Considerazioni
Componentistica
Il progetto è basato principalmente sull'utilizzo di un Raspberry Pi3, di seguito elenco i componenti necessari per assemblare questa lavagna.


Componenti meccanici | Componenti elettronici |
---|---|
|
|
Logica di funzionamento
La scelta di adottare un Raspberry è dettata dal fatto che avendo un sistema operativo linux mi da la libertà di organizzare le cose a mio piacimento senza alcun tipo di vincolo, può andare in rete tramite WiFi e ultima ma non meno importante, posso farlo lavorare come un web server, ed è proprio questa la chiave di tutto perchè configurando opportunamente il router di casa posso accedere dall'esterno al Raspberry con il browser di uno smartphone.In parole povere il Raspberry è il webserver sul quale gira un sito con l'interfaccia per scrivere e disegnare poi il disegno in formato SVG viene inviato, sempre al Raspberry che lo converte in GCODE e lo processa per azionare i motori.
Più avanti nella sezione software spiegherò in dettaglio i processi.
Meccanica
A differenza di tutte le altre cnc che ho realizzato con materiali di recupero questa l'ho progettata da zero in Rhino con l'obbiettivo di stampare in ABS tutti i componenti necessari e assemblare il tutto senza sorprese o dover ricorrere a soluzioni posticce. Inoltre ho sviluppato anche tutta la parte software in grado di dialogare via web e pilotare la testina per disegnare e all'occorrenza cancellare la lavagna.
In termini di dimensioni ho cercato di far rientrare tutto in una scatola non troppo ingombrate e facilmente installabile perchè alla fine dei giochi da tale scatola vorrei che uscisse un solo cavo, quello della 220 Volt e nient'altro, un pò come fosse un piccolo plotter.
Meccanicamente ho progettato una struttura leggera con pochi pezzi ma ottimizzati per lo scopo, ho cercato di miniaturizzare il più possibile i componenti soprattutto quelli dedicati alla testina.
|
|
|
|
Modellare i pezzi è stato facile e se vogliamo anche veloce ma la cosa che mi ha fatto perdere un botto di tempo è stato riuscire a stamparli rispettandone le misure finali, provo a spiegarmi meglio...
Se ad esempio ho il modello 3D di un cubo 20x20x20 con un foro centrale diam. 6 mm quando lo si stampa le misure finali non saranno mai quelle del disegno originale per il fatto che il materiale di stampa (ABS nel mio caso) tende a restringersi durante la fase di raffreddamento. La cosa poco simpatica è che ad esempio i fori si riducono e le parti esterne si restringono.
Di quando si restringono i pezzi? boh! ho letto che la percentuale di restringimento può cambiare dalla marca del filamento usato e addirittura dal colore.
Io ho risolto la questione stampando prima dei pezzi campione e misurando le dimensioni finali, poi facendo delle proporzioni ho ricavato una percentuale di restringimento.
Questo scherzetto mi ha costretto a modificare tutte le misure dei pezzi in 3D con la conseguente perdita di tempo.
Oltre a questo mi sono ritrovato a dover rimodellare alcuni pezzi perchè una volta stampati non di adattavano bene o semplicemente mi ero dimenticato qualcosa (un foro, un perno, ecc...)

Mi sono reso conto che progettare un prototipo da zero comporta il dover rifare e rivedere ogni singolo pezzo e riadattarlo perché funzioni come dovrebbe, insomma bisogna essere pronti a rimettere in gioco tutto qualora si dovessero incontrare ostacoli o impedimenti.
Giusto per rendere l'idea la testina l'ho dovuta ristampare 5 volte e ancora non è alla situazione ottimale (ma fa il suo dovere).
Una volta stampati i pezzi il montaggio è molto semplice, basta rimediare delle pareti in multistrati e assemblarle a formare una C.
I pezzi stampati in ABS vengono installati all'interno della struttura a C.
La cosa più importante è fare in modo che lo stelo da 10 mm su cui scorrerà il carrello sia perfettamente perpendicolare alla struttura.
Per permettere lo scorrimento del carrello sullo stelo ho comprato su ebay una bronzina o meglio un cuscinetto lineare auto-lubrificante.

La bronzina s'incastra nel supporto in ABS del motore e per tenerla ferma l'ho fermata con 2 viti.
Nei giorni successivi avevo stampato 2 coperchi appositi per fermare le bronzine, che alla fine non ho ho montato, più che altro per pigrizia di smontare di nuovo tutto.
Assemblaggio del supporto inferiore con micro-switch di finecorsa:
Assemblaggio della testina di stampa:

La meccanica senza elettronica e software serve a ben poco ed è qui che entra in gioco la coppiata Raspberry + Arduino Uno.
Elettronica
I componenti elettronici in gioco sono principalmente un Raspberry Pi 3, un Arduino Uno e un CNC Shield.Il Raspberry è il cuore principale perchè gestisce tutte le operazioni e i segnali di input e output, Arduino ha lo scopo di gestire la corrente che passa nei motori e di azionare un servo per muovere la penna e il cancellino, il CNC shield ha a bordo dei driver pololu A4988 che a loro volta azionano dei Nema 17.
Oltre a questi componenti fondamentali troviamo un alimentatore da 12 Volt, un riduttore di tensione, un relè qualche cavo elettrico.
L'alimentazione ha il compito di alimentare il CNC shield e quindi i nema 17 e, attraverso un riduttore di tensione con uscita USB, il Raspberry e il servo motore.
Arduino è alimentato direttamente dal Raspberry tramite un cavetto usb e per semplificare un pò le cose ho installato sul Raspberry l'IDE di Arduino così che posso fare modifiche allo sketch al volo direttamente dall'interfaccia desktop de Raspberry anche da remoto via VNC.
Uno degli obiettivi che mi ero prefissato era di avere una macchina senza tanti file che uscivano fuori, trasformatori o driver esterni ma con il solo filo della 220 V che uscisse.
Detto questo ho cercato di incastrare tutto all'interno della struttura.
Ho tagliato un rettangolo di compensato dove ho predisposto i fori per avvitarci le 3 schede principali e fermare i fili.
Questo è lo schema dei collegamenti elettrici ultimo:
Infine chiuderò il resto con un coperchio di faesite bianca.
Software
La parte software di questo progetto è la cosa più importante perchè è quella che permette di gestire ogni singolo comportamento della macchina in base alle proprie esigenze.L'utente che vorrà interagire con la macchina (o lavagna) avrà a disposizione un'app web basata su jQuery che permetterà di disegnare a mano libera o di scrivere un testo e poi inviare il tutto al webserver (Raspberry) che dovrà processare il dato, convertirlo in Gcode e infine trasformarlo in segnali per i motori.
Detta così può sembrare una cosa complicata ma se si isolando tutti i vari processi in piccole operazioni atomiche tutto diventa più semplice e comprensibile.
I linguaggi di programmazione che sarebbe opportuno conoscere sono:
- Linux bash
- PHP
- Python
- HTML
- Javascript + jQuery
I pezzi di software in gioco per questo progetto sono i seguenti:
- PyCNC (gestione motori e gcode)
- svg2gcode (conversione da svg a gcode)
- grecode (manipolazione gcode)
- easysvg (generatore testi in svg)
- iBoard.class.php (classe principale di controllo)
- iBoard.js (classe javascript lato client che dialoga con iBoard.class.php)
Come ho accennato nell'introduzione il principio su cui si basa tutto è il formato SVG, molto utilizzato nel web per disegnare soprattutto grafici.
Se provate ad aprire con il blocco note un qualunque file .SVG noterete come prima cosa che è un formato testuale e all'interno è presente una struttura XML che contiene dei tag <path> con all'interno delle coordinate X,Y ed è proprio questo aspetto che permette di ottenere del Gcode.
in linea di massima questo è il flusso dati che ho ipotizzato:
Webserver Apache + PHP
La configurazione del server (Raspberry) è un pò laboriosa ma nulla di così complesso.Installare Apache2
sudo apt-get update
sudo apt-get install apache2
Installare PHP
sudo apt-get install php5 libapache2-mod-php5 php5-mcrypt
Dopo aver installato Apache e PHP e necessario configurare Apache in modo da farlo girare con l'utente "pi" e group "pi" perchè quando sarà il momento di eseguire gli script l'utente di apache non sarà in grado di eseguirli. Il file su cui bisognerà intervenire è questo
/etc/apache2/httpd.confmodifica da effettuare:
User pi
Group pi
Ora occorre creare un virtualhost e facendolo puntare alla directory del progetto.
La cartella dove creare un vhost si trova qui:
/etc/apache2/sites-enabledè sufficiente creare un file con estensione .conf ad esempio
iboard.tuodominio.com.confall'interno del file basta inserire questa configurazione
Fatte le modifiche è occorre riavviare il servizio apache
sudo /etc/init.d/apache2 stopPer poter vedere se la configurazione è andata a buon fine basta aprire il browser di un PC in rete e digitare il nome di dominio che avete scelto.
sudo /etc/init.d/apache2 start
Se non è stato configurato il router per accettare l'ingresso delle chiamate http e se non è stato ancora registrato un dominio è sufficiente aggiungerlo nel file hosts del pc.
Su Windows il file si trova qui:
C:\Windows\System32\drivers\etc\hosts
In fondo al file è necessario aggiungere una riga come questa
[IP Raspberry] iboard.tuodominio.comes.
192.168.1.70 iboard.tuodominio.com
Salvare il file e digitare sul browser del PC http://iboard.tuodominio.com, se è stato fatto tutto bene si dovrebbe vedere la pagina di benvenuto di Apache.
Libreria per controllo motori stepper
Senza un software capace di inviare segnali ai driver dei motori stepper questo progetto non esisterebbe.
Per poter convertire una istruzione gode in movimento è necessaria una libreria capace di interpretare il dato e gestire i segnali in uscita.
Per poter convertire una istruzione gode in movimento è necessaria una libreria capace di interpretare il dato e gestire i segnali in uscita.
La particolarità che dovrà avere questa libreria è che le istruzioni gcode dovranno essere lanciate in bash a linea di comando.
Libreria PyCNC (python)
Prima di mettermi a scrivere qualcosa da zero ho fatto una lunga ricerca ed alla fine ho trovato su GitHub una libreria scritta in Python chiamata PyCNC .
PyCNC è stata sviluppata da un ragazzo Nikolay Khabarov molto gentile e disponibile perchè ad ogni domanda che gli facevo mi ha sempre risposto con precisione e ottime soluzioni. a questo link è possibile consultare i quesiti tecnici che gli avevo posto e le sue relative risposte.
Prima di mettermi a scrivere qualcosa da zero ho fatto una lunga ricerca ed alla fine ho trovato su GitHub una libreria scritta in Python chiamata PyCNC .
PyCNC è stata sviluppata da un ragazzo Nikolay Khabarov molto gentile e disponibile perchè ad ogni domanda che gli facevo mi ha sempre risposto con precisione e ottime soluzioni. a questo link è possibile consultare i quesiti tecnici che gli avevo posto e le sue relative risposte.
Spiego in breve il motivo per il quale avevo contattato Nikolay.
La sua libreria riesce a gestire fino a 5 assi con motori stepper mentre nel mio progetto ho anche un piccolo servo utilizzato per azionare la penna ed il cancellino.
Secondo Nikolay la gestione del servo era possibile ma dopo aver fatto diversi test e modificato i sorgenti del suo codice siamo giunti entrambi alla conclusione che per come era stata scritta non era possibile farlo o meglio capitava che mentre gli stepper giravano mi si generavano delle interferenze sul servo.
La sua libreria riesce a gestire fino a 5 assi con motori stepper mentre nel mio progetto ho anche un piccolo servo utilizzato per azionare la penna ed il cancellino.
Secondo Nikolay la gestione del servo era possibile ma dopo aver fatto diversi test e modificato i sorgenti del suo codice siamo giunti entrambi alla conclusione che per come era stata scritta non era possibile farlo o meglio capitava che mentre gli stepper giravano mi si generavano delle interferenze sul servo.
La soluzione che ho adottato è stata quella di inserire nel progetto un Arduino Uno con il compito di azionare penna, cancellino ed un relè per la gestione del risparmio di energia che spiegherò più avanti.
Per far dialogare la libreria PyCNC con Arduino ho dovuto fare diverse modifiche al codice di Nikolay.
PyCNC detto in parole povere non fa altro che parsare ogni singola riga di gcode e identificare i comandi (es. G1,G2,G3,M3,M5, ecc....) e chiamate delle funzioni specifiche che generano segnali di uscita per i motori.
Tutti i parametri dei motori e la configurazione dei pin si trova in questo file:
PyCNC/cnc/config.py
ecco alcune linee di codice di configurazione:
MAX_VELOCITY_MM_PER_MIN_X = 10000
MAX_VELOCITY_MM_PER_MIN_Y = 10000
MAX_VELOCITY_MM_PER_MIN_Z = 600
MAX_VELOCITY_MM_PER_MIN_E = 1500
MIN_VELOCITY_MM_PER_MIN = 1
# Average velocity for endstop calibration procedure
CALIBRATION_VELOCITY_MM_PER_MIN = 1000
# Stepper motors steps per millimeter for each axis.
STEPPER_PULSES_PER_MM_X = 80.5
STEPPER_PULSES_PER_MM_Y = 39.75
STEPPER_PULSES_PER_MM_Z = 400
STEPPER_PULSES_PER_MM_E = 150
# -----------------------------------------------------------------------------
# Pins configuration.
# Enable pin for all steppers, low level is enabled.
STEPPERS_ENABLE_PIN = 26
STEPPER_STEP_PIN_X = 21
STEPPER_STEP_PIN_Y = 16
STEPPER_STEP_PIN_Z = 12
STEPPER_STEP_PIN_E = 8
STEPPER_DIR_PIN_X = 20
STEPPER_DIR_PIN_Y = 19
STEPPER_DIR_PIN_Z = 13
STEPPER_DIR_PIN_E = 7
# Mirco
PEN_PIN = 9
ERASER_PIN = 11
DRIVERS_PIN = 5
# Mirco
SPINDLE_PWM_PIN = 4
FAN_PIN = 27
EXTRUDER_HEATER_PIN = 24
BED_HEATER_PIN = 22
EXTRUDER_TEMPERATURE_SENSOR_CHANNEL = 2
BED_TEMPERATURE_SENSOR_CHANNEL = 1
ENDSTOP_PIN_X = 23
ENDSTOP_PIN_Y = 10
ENDSTOP_PIN_Z = 25
Quello che ho fatto è inventarmi 5 nuovi comandi Gcode M333, M444, M555, M666, M777 e implementarli in PyCNC dove ognuno di essi genera segnali di uscita sui pin del Raspberry.
In particolare
- M333 aziona il relè per alimentare i driver
- M444 disattiva il relè per alimentare i driver
- M555 servo a riposo 90°
- M666 servo in posizione 120° che aziona la penna
- M777 servo in posizione 60° che aziona il cancellino
facendo partire PyCNC e lanciando uno dei comandi gcode sopra elencati il Raspberry invia dei segnali digitali ai pin precedentemente configurati.
nel file
/PyCNC/cnc/gmachine.pyho aggiunto le seguenti istruzioni
elif c == 'M333': # Mirco - aziona i driver dei motori
self._driver_on()
elif c == 'M444': # Mirco - spegne i driver dei motori
self._driver_off()
elif c == 'M666': # Mirco - aziona la penna
self._write()
elif c == 'M777': # Mirco - aziona il cancellino
self._erase()
elif c == 'M555': # Mirco - posizione di riposo
self._headup()
prendendo ad esempio il codice M666 sempre nello stesso file ho definito la funzione _write()
def _write(self):e nel file
hal.write()
PyCNC/cnc/hal_raspberry/hal.pyho aggiunto la nuova funzione
def write():
""" Abilito la penna con un output digitale al pin PEN_PIN
"""
logging.info("aziona la penna")
gpio.set(PEN_PIN)
gpio.clear(ERASER_PIN)
In linea di massima queste sono le modifiche principali che ho apportato per i miei scopi.
Per lanciare PyCNC a linea di comando basta entrare nella directory PyCNC e digitare
sudo ./pycnc
pi@raspiboard:~/Desktop/iBoard/scripts/PyCNC $ cd /var/www/html/iBoard/scripts/PyCNC/Dal momento che per azionare la penna o il cancellino servono comandi diversi dai classici M3 M5 sarà opportuno generare un gcode scritto ad hoc.
pi@raspiboard:/var/www/html/iBoard/scripts/PyCNC $ sudo ./pycnc
---- ads111x is not detected ----
*************** Welcome to iBoard! (powered by PyCNC) ***************
>
es. se vogliamo disegnare un quadrato il codice dovrà assomigliare a questo
M555Ho collegato 2 motori al volo e fatto qualche test di funzionamento...
G0 X10 Y10
M666
G1 X10 Y20
G1 X20 Y20
G1 X20 Y10
G0 X10 Y10
M555
Arduino
Lato Arduino le cose sono molto più semplici perchè è sufficiente configurare dei pin in ingresso e leggerne il valore digitale.
Ipotizziamo questa configurazione:
Ipotizziamo questa configurazione:
Comando Gcode M666 configurato sul GPIO24 come uscita digitale del raspberry
pin GPIO24 collegato al PIN7 di Arduino
pin GPIO24 collegato al PIN7 di Arduino
Quando digito l'istruzione Gcode M666 il Raspberry farà uscire un segnale digitale verso il PIN7 di Arduino, lo sketch di Arduino sa che quando arriva un segnale digitale sul PIN7 dovrà posizionare il servo sulla posizione 120° (poi riguardo alla posizione del servo ho avuti altri problemi di cui ne parlerò più avanti).
di seguito lo sketch che ho scritto e caricato su Arduino Uno
#include <Servo.h>
Servo myservo;
int pos = 0;
int inputEraser = 7;
int inputPen = 8;
int inputRele = 6;
int pinServo = 9;
int pinRele = 5;
int statusEraser = 0;
int statusPen = 0;
int statusRele = 0;
int servoVoidAngle = 90; // al momento non usato
int servoEraserAngle = 60; // al momento non usato
int servoPenAngle = 115; // al momento non usato
int current_angle = servoVoidAngle; // al momento non usato
int servoVoid_ms = 1750; // millisecondi per gestire la rotazione precisa a 90°
int servoEraser_ms = 1550; // millisecondi per gestire la rotazione precisa a 60°
int servoPen_ms = 1950; // millisecondi per gestire la rotazione precisa a 115°
int current_ms = servoVoid_ms;
String incomingByte = "";
void setup()
{
pinMode(inputEraser, INPUT);
pinMode(inputPen, INPUT);
pinMode(inputRele, INPUT);
pinMode(pinRele, OUTPUT);
Serial.begin(9600);
myservo.attach(pinServo);
}
void loop()
{
if (Serial.available() > 0) {
incomingByte = Serial.readString();
if(incomingByte) {
myservo.writeMicroseconds(incomingByte.toInt());
Serial.println(incomingByte);
}
}
if(true){
statusEraser = digitalRead(inputEraser);
statusPen = digitalRead(inputPen);
statusRele = digitalRead(inputRele);
if(statusRele==HIGH){
digitalWrite(pinRele, LOW);
}else{
digitalWrite(pinRele, HIGH);
}
if(statusPen==HIGH || statusEraser==HIGH){
if(statusPen==HIGH) {
current_ms = servoPen_ms;
myservo.writeMicroseconds(current_ms);
}
if(statusEraser==HIGH) {
current_ms = servoEraser_ms;
myservo.writeMicroseconds(current_ms);
}
}else{
current_ms = servoVoid_ms;
myservo.writeMicroseconds(current_ms);
}
}
}
Chi ha un pò di dimestichezza con gli sketch di Arduino avrà subito notato che per gestire la posizione del servo non ho specificato i gradi ma ho usato la funzione writeMicroseconds().
Il motivo di questa scelta è perchè quando specificavo una posizione di 90° il servo si posizionava a circa 80°, insomma non era preciso come volevo. La funzione writeMicroseconds permette di gestire la posizione in modo più accurato.
Il motivo di questa scelta è perchè quando specificavo una posizione di 90° il servo si posizionava a circa 80°, insomma non era preciso come volevo. La funzione writeMicroseconds permette di gestire la posizione in modo più accurato.
Il relè che avevo menzionato prima relativo alla gestione del risparmi di energia servirà per togliere corrente ai driver dei motori dopo un determinato periodo di inattività.
al momento il timer sul periodo di inattività non l'ho implementato nello sketch sopra ma lo farò più avanti a progetto concluso.
al momento il timer sul periodo di inattività non l'ho implementato nello sketch sopra ma lo farò più avanti a progetto concluso.
Conversione SVG -> Gcode
Per convertire un file SVG ci sono tanti modi e script opesource in giro per la rete e bene o male fanno tutti la stessa cosa per cui invece di perdere tempo a "reinventare l'acqua calda" (riscrivendolo da zero) ne ho preso uno a caso su GitHub in Python e l'ho fatto diventare mio cambiando alcuni pezzi di codice per adattarlo allo scopo.Lo script in questione si chiama svg2gcode ed è scaricabile da qui.
La prima cosa importante è editare il file config.py dove è possibile specificare l'area massima di lavoro e i prefissi e suffissi da applicare per ogni shape parsata.
questa qui sotto ad esempio è la configurazione che ho adottato io:
"""G-code emitted at the start of processing the SVG file"""
preamble = "g21\ng90\nm333\ng4 p1\ng28\nf9000"
"""G-code emitted at the end of processing the SVG file"""
postamble = "g4 p0.3"
"""G-code emitted before processing a SVG shape"""
shape_preamble = "g4 p0.1"
"""G-code emitted after processing a SVG shape"""
shape_postamble = "g4 p0.1\nm555"
"""Print bed width in mm"""
bed_max_x = 380
"""Print bed height in mm"""
bed_max_y = 220
"""
Used to control the smoothness/sharpness of the curves.
Smaller the value greater the sharpness. Make sure the
value is greater than 0.1
"""
smoothness = 0.1
Come dicevo poco fa anche in questa libreria mi sono trovato costretto ad apportare dei cambiamenti così ho fatto una copia del file chiamandola svg2gcodeMirco.py, questo sarà il file che chiamerò per generare il gcode adatto alle mie esigenze.
La parte che ho modificato è quella che si trova in fondo al file, in particolare ho aggiunto il comando M666, una pausa di 300ms (G4 p0.3) e un pò di commenti da inserire nel Gcode per fare debug.
print shape_preamble
p = point_generator(d, m, smoothness)
count = 1
for x,y in p:
if x > 0 and x < bed_max_x and y > 0 and y < bed_max_y:
if count == 2:
print "G4 p0.3\nM666\nG4 p0.3"
print "(startsegment)"
print "G1 X%0.1f Y%0.1f" % (scale_x*x, scale_y*y)
count += 1
else:
print "(fuori misure x%s y%s)" % (x,y)
print "(endsegment)"
print shape_postamble
Per convertire un file .svg in Gcode basta andare nella cartella principale dove si trovano i files di svg2gcode e lanciare questo comando
cat miofile.svg | python svg2gcode.py
il comando qui sopra "sputerà" a video il gcode appena generato per cui se lo vogliamo scrivere su un file basterà aggiungere in fondo il simbolo maggiore (>) ed il nome del file che vogliamo creare, es.
cat miofile.svg | python svg2gcode.py > miogcode.nc
Giunti a questo punto la strada è ormai in discesa perchè non resta altro che mettere insieme tutti i pezzi e farli lavorare a dovere.
Grecode
Generare il Gcode non basta perchè se ci pensate bene non è mai stato ancora specificato in che punto dell'area di lavoro dovrà essere posizionato il nostro disegno e oltre a questo nel gcode generato c'è un problema di codice specchiato nel senso che nel file SVG le coordinate provengono da quelle web e nella nostra macchina potrebbero non sempre coincidere.
Grecode è un'utile libreria che si occupa di rimanipolare il Gcode ad esempio spostando il disegno in una coordinata specifica, specchiarlo, ruotarlo, scalarlo, strecciarlo e tanto altro.
Quindi dopo aver generato il Gcode è possibile decidere se darlo in pasto a grecode per applicare delle modifiche.
Quindi dopo aver generato il Gcode è possibile decidere se darlo in pasto a grecode per applicare delle modifiche.
iBoard.class.php
Ho scritto questa classe PHP con il preciso compito di mettere insieme tutti i componenti descritti sopra e di farli lavorare all'unisono e comandare la lavagna.
La logica di funzionamento di questa classe è quello di generare un task (o job) per ogni disegno che viene fatto creando una cartella apposita con all'interno il singolo svg ed il Gcode generato.
Gestendo le cose in questo modo ho la possibilità di cancellare parzialmente la lavagna chiedendo la cancellazione di un preciso task.
Per la cancellazione parziale intendo che se ad esempio disegno una stella posso anche cancellarla senza dover passare tutta la lavagna da cima a fondo.
Come avviene la cancellazione parziale?
E' molto semplice, avendo il gcode salvato per ogni disegno quello che faccio è prendere le coordinate minime e massime del disegno parsando tutte le linee del gcode e costruendo al volo un altro file gcode che aziona il cancellino facendolo muovere a zigzag nell'area in cui si trovava il disegno.
E' molto semplice, avendo il gcode salvato per ogni disegno quello che faccio è prendere le coordinate minime e massime del disegno parsando tutte le linee del gcode e costruendo al volo un altro file gcode che aziona il cancellino facendolo muovere a zigzag nell'area in cui si trovava il disegno.
Oltre a queste funzioni di base ne ho aggiunte altre per eseguire codice pre-formattato come ad esempio un messaggio di benvenuto o la cancellazione totale della lavagna.
esempio di cancellazione parziale della lavagna
esempio di cancellazione parziale della lavagna
easysvg (generatore testi svg in PHP)
Qualcuno si starà chiedendo: ma perchè non generarli via web?
Il motivo è molto semplice, perchè generare via web un testo significa usare un apposito tag XML chiamato text all'interno del quale non sono presenti delle cordinate xy e quindi lo script svg2gcode non riuscirebbe a gestirlo.
Esiste una libreria Javascript (RaphaelJS) che manipola gli svg e che riesce a convertire un testo in path svg ma dopo alcune prove mi sono reso conto che è un pò pesante da gestire per il browser soprattutto in presenza di molto testo.
Il motivo è molto semplice, perchè generare via web un testo significa usare un apposito tag XML chiamato text all'interno del quale non sono presenti delle cordinate xy e quindi lo script svg2gcode non riuscirebbe a gestirlo.
Esiste una libreria Javascript (RaphaelJS) che manipola gli svg e che riesce a convertire un testo in path svg ma dopo alcune prove mi sono reso conto che è un pò pesante da gestire per il browser soprattutto in presenza di molto testo.
La soluzione che ho adottato è quella di inviare in POST alla mia classe iBoard.class.php solo il testo e qualche altro parametro come il font-family, il font-size, e l'allineamento, poi utilizzando la classe easysvg genero un svg da eseguire.
I font li genero con dei tool online che per mettono la conversione di un font .ttf in .svg creando quindi un webfont.
I font li genero con dei tool online che per mettono la conversione di un font .ttf in .svg creando quindi un webfont.
Se in un futuro troverò il modo per gestire in modo semplificato un testo in path svg lo implementerò e aggiornerò questo documento.
Il vantaggio di usare un generatore di testo svg in PHP è di automatizzare dei processi di scrittura sulla lavagna come ad esempio schedulare dei messaggi automatici tipo il meteo, qualche notizia presa via web o appuntamenti presi da Google Calendar.
usare easysvg è molto semplice
require 'easySVG.php';
$svg = new EasySVG();
$svg->setFont("om_telolet_om-webfont.svg", 100, '#000000');
$svg->addText("Simple text display");
$svg->addAttribute("width", "800px");
$svg->addAttribute("height", "120px");
echo $svg->asXML();
Console a linea di comando
Per poter gestire la scrittura automatica di testi ho sviluppato anche una console a linea di comando che utilizza sempre la classe iBoard.class.php ma che però può essere utilizzata in bash a linea di comando come ad esempio:php controller/cli.php wtriteText -text="ciao!" -align=top-left -font=comic -size=40l'istruzione qui sopra farà comparire sulla lavagna il testo "ciao!" alto 40 mm con il carattere comic posizionato in alto a sinistra.
Se volessi ad esempio schedulare la stampa delle ultime notizie principali prese da un feed RSS non serve altro che creare un CRON alle 8:00 di mattina che legge l'XML del feed RSS ed esegue il comando sopra con il testo della notizia, poi se volendo potrei scaricare le previsioni meteo da open weather e stamparlo sotto alle notizie. L'unico limite è la fantasia...
Lato Client
Lato client sarà disponibile una interfaccia web HTML basata su jQuery che permetterà all'utente di scrivere del testo o disegnare a mano libera con il mouse o con il touch screen dello smartphone.
Ho sviluppato una piccola classe javascript che ha il compito di dialogare via Ajax con il web server inviando il disegno in formato SVG.
Ho sviluppato una piccola classe javascript che ha il compito di dialogare via Ajax con il web server inviando il disegno in formato SVG.
Disegno a mano libera
Scrittura di testi
Considerazioni
Il progetto tutto sommato si è concluso con successo senza particolari intoppi; l'aspetto sul quale devo lavorare ancora è legato al pennarello che con passare delle ore tende ad asciugarsi e quindi a non scrivere più.
Devo ancora fare dei test per capire se esiste una posizione di riposo tale per cui l'inchiostro non si secchi. Allo stato attuale quando il pennarello è a riposo rimane in una posizione inclinata con la punta rivolta leggermente verso l'alto e non credo sia molto vantaggiosa, dovrei provare a tenere la lavagna stesa su un pia in modo che il pennarello rimanga quasi in verticale.
Se anche così il pennarello si secca si potrebbe fare una modifica alla lavagna in modo che nella posizione di riposo a X0 Y0 sia presente una specie di foro che funge da tappo sul piano nel quale la punta della penna si possa infilare evitando di restare a contatto con l'aria.
Spero abbiate gradito questa presentazione, grazie per la lettura e alla prossima...
Devo ancora fare dei test per capire se esiste una posizione di riposo tale per cui l'inchiostro non si secchi. Allo stato attuale quando il pennarello è a riposo rimane in una posizione inclinata con la punta rivolta leggermente verso l'alto e non credo sia molto vantaggiosa, dovrei provare a tenere la lavagna stesa su un pia in modo che il pennarello rimanga quasi in verticale.
Se anche così il pennarello si secca si potrebbe fare una modifica alla lavagna in modo che nella posizione di riposo a X0 Y0 sia presente una specie di foro che funge da tappo sul piano nel quale la punta della penna si possa infilare evitando di restare a contatto con l'aria.
Spero abbiate gradito questa presentazione, grazie per la lettura e alla prossima...
Progetto molto bello e articolato. Veramente complimenti per averlo sviluppato e portato a termine. Dubito che riuscirò a farlo ma sicuramente me lo studierò con attenzione. grazie per averlo condiviso. Saluti. Roberto
RispondiEliminaInvertire la posizione del pennarello magari ruotando il carrellino sotto sopra e un mini cappuccio automatico con lo stesso movimento del pennarello
RispondiEliminaConfermo, l'idea del cappuccio è molto buona
Eliminaciao, scusami una domanda, ci sarebbe la possibilità di far andare tutto tramite bluetooth anzivhe wifi?
RispondiEliminaciao, questo progetto è basato su un web server apache e necessita di una navigazione web per poter accedere all'interfaccia per cui tramite bluetooth non è possibile a meno che non si cambi tutto il software di comando.
Eliminaciao
Complimenti Mirko!
RispondiEliminaUn lavoro fatastico, ben progettato e spiegato. Grazie per averlo condiviso.
Non ho una printer 3D, ma vedrò come generare i pezzi. Alcuni li posso acquistare. Trovo particolarmente interessante la filosofia della semplicità e del box dal quale esce solo il cavo di alimentazione. A questo punto usato in verticale o in orizzontale non cambia, ma in verticale ottimizza incredibilmente gli spazi in workshop piccoli come il mio.
Hai suggerimenti in caso io volessi cambiare le dimensioni? Disegno chitarre per cui ho bisogno di un'area di disegno utile di almeno 80x60. A parte gli ovvii cambi nelle parti meccaniche e nella configurazione del software non mi pare di vedere altri impedimenti.
In alcuni casi potrei trovarmi ad avere già un file gcode in uscita da altri disegni. In quale parte del workflow credi potrei inserire manualmente il mio file, ammesso sia possibile? Altrimenti dovrò inventarmi qualcosa che funzioni come se lo avessi disegnato sul tablet.
Seguo anche gli altri tuoi lavori. Sei una fonte di ispirazione costante. Grazie!
Roberto
Ciao Roberto, praticamente quello che serve a te non è altro che un plotter giusto?
EliminaIl sistema che ho realizzato alla fine dei conti è un plotter per ed il software che lo pilota è originariamente stato progetto per essere usato nelle CNC per cui se gli dai in pasto un Gcode funziona alla grande, anzi ho aggiunto nell'interfaccia la possibilità di caricare un Gcode. forse quest'ultima aggiunta non la troverai nel progetto da scaricare però se me lo chiedi te la invio via email.
saluti
Ciao Mirco, scusa il ritardo. Grazie 100 per la risposta, soprattutto perché è quella che mi aspettavo... :-)
EliminaIn effetti sì, a me occorre sostanzialmente un plotter. Magari un domani, sulla stessa meccanica potrei montare la testa per un laserino per fare piccole incisioni nel legno sfruttando le stesse logiche, ma per ora faccio tutto a mano una volta che ho i disegni.
Inviami pure l'aggiornamento dell'interfaccia per fare upload diretto di un Gcode all'indirizzo: robertosciarra60@gmail.com
Grazie 1000!
Ciao!
Roberto
PS: vivo in UK, vicino a Liverpool, ma non fa una grossa differenza... :-)
Wonderful work you have!!
RispondiEliminaI have a little confusion in your wiring diagram :(
Can you explain more about it? On how to connect each parts?
Here is my email: dinhquoc2004@gmail.com
Thanks a lot for your amazing project!