Ya es momento de terminar la estructura. Al arco del lápiz le falta colocar el servo. Cogemos un listón de madera para posicionarlo a la altura correcta. Lo cortamos a la medida adecuada y pegamos el servo con un poco de termofusible.
El siguiente paso es colocar todo este arco sobre la base. Tenemos dudas porque no hemos previsto el movimiento de la base alrededor del punto donde está colocado el lápiz, pero una comprobación, y es correcto. Pegamos el arco con cola blanca y esperamos que seque para probarlo. Colocamos un rotulador para ver si es capaz de escribir.
Para probarlo todo preparamos un programa que admita coordenadas y dibuje líneas. Creamos una función que dibuje estas líneas rectas con una aplicación simple del algoritmo de Bresenham. En este paso nos ayuda el profesor, porque es complicado:
El resultado se ve en el siguiente video:
Por último, añadimos la escritura de letras. El programa es similar al de dibujar los triángulos, pero se definen las letras, usando una plantilla de 20 x 20 pulsos. Salen rectangulares porque uno de los dos motores tiene los pasos más amplio.
Para poder escribir, guardamos todas las letras definidas por sus puntos, con coordenadas X, Y y Z, en una matriz de puntos. Como las letras tienen diferente número de puntos, necesitamos otra matriz que indique en qué punto empieza cada letra. Las letras curvas las aproximamos por rectas. El programa recibe desde el ordenador la frase a escribir y la escribe letra a letra. Por sencillez, sólo hemos definido letras mayúsculas y el espacio:
// Programa para escribir caracteres en el trazador // Los caracteres se definen por un conjunto de líneas #include <Servo.h> // Definiciones de constantes #define X1 4 // Patillas de motor paso a paso eje X #define X2 5 #define X3 6 #define X4 7 #define Y1 8 // Patillas de motor paso a paso eje Y #define Y2 9 #define Y3 10 #define Y4 11 #define LAPIZ 3 // Patilla de conexión servo eje Z #define EJEX 0 // Definiciones de ejes de motores #define EJEY 1 #define LIMX 250 // Valores límites de pasos en cada eje #define LIMY 160 #define Z0 70 // Definiciones de alturas en eje Z para el lápiz, abajo #define Z1 90 // arriba #define dVelTrazador 10 // Pausa entre movimientos del trazador // Variables globales int paso[2]; // Contador de pasos de motores byte fase[2]; int Motor[2][4]; // Patillas de los motores Servo ServoZ; // Crea servo para control eje Z byte EstLapiz; // Estado del lápiz: Z0=abajo, Z1=arriba // Definiciones de letras int PosLetras[29]={0,6,17,24,32,39,45,54,61,64, 70,77,81,87,92,102,109,121,129,138, 143,150,154,160,165,171,176,183,184}; int letras[185][3]={{0,0,Z0}, // A {10,20,Z0}, {10,-20,Z1}, {-5,10,Z0}, {-10,0,Z1}, {20,-10,Z1}, {0,0,Z0}, // B {0,20,Z0}, {10,0,Z0}, {5,-5,Z0}, {-5,-5,Z0}, {-10,0,Z0}, {10,0,Z0}, {5,-5,Z0}, {-5,-5,Z0}, {-10,0,Z1}, {20,0,Z1}, {15,0,Z0}, // C {-10,0,Z0}, {-5,5,Z0}, {0,10,Z0}, {5,5,Z0}, {10,0,Z1}, {5,-20,Z1}, {0,0,Z0}, // D {0,20,Z0}, {10,0,Z0}, {5,-5,Z0}, {0,-10,Z0}, {-5,-5,Z0}, {-10,0,Z1}, {20,0,Z1}, {15,0,Z0}, // E {-15,0,Z0}, {0,20,Z0}, {15,0,Z1}, {-5,-10,Z0}, {-10,0,Z1}, {20,-10,Z1}, {0,0,Z0}, // F {0,20,Z0}, {15,0,Z1}, {-5,-10,Z0}, {-10,0,Z1}, {20,-10,Z1}, {15,20,Z0}, // G {-10,0,Z0}, {-5,-5,Z0}, {0,-10,Z0}, {5,-5,Z0}, {10,0,Z0}, {0,10,Z0}, {-5,0,Z1}, {10,-10,Z1}, {0,0,Z0}, // H {0,20,Z1}, {0,-10,Z0}, {15,0,Z1}, {0,10,Z0}, {0,-20,Z1}, {5,0,Z1}, {0,0,Z0}, // I {0,20,Z1}, {5,-20,Z0}, {0,5,Z0}, // J {5,-5,Z0}, {5,0,Z0}, {5,5,Z0}, {0,15,Z1}, {5,-20,Z1}, {0,0,Z1}, // K {0,20,Z1}, {0,-10,Z0}, {15,10,Z1}, {-15,-10,Z0}, {15,-10,Z1}, {5,0,Z1}, {0,20,Z0}, // L {0,-20,Z0}, {15,0,Z1}, {5,0,Z1}, {0,0,Z0}, // M {0,20,Z0}, {10,-10,Z0}, {10,10,Z0}, {0,-20,Z1}, {5,0,Z1}, {0,0,Z0}, // N {0,20,Z0}, {15,-20,Z0}, {0,20,Z1}, {5,-20,Z1}, {0,5,Z0}, // O {0,10,Z0}, {5,5,Z0}, {5,0,Z0}, {5,-5,Z0}, {0,-10,Z0}, {-5,-5,Z0}, {-5,0,Z0}, {-5,5,Z1}, {20,-5,Z1}, {0,0,Z0}, // P {0,20,Z0}, {10,0,Z0}, {5,-5,Z0}, {-5,-5,Z0}, {-10,0,Z1}, {20,-10,Z1}, {0,5,Z0}, // Q {0,10,Z0}, {5,5,Z0}, {5,0,Z0}, {5,-5,Z0}, {0,-10,Z0}, {-5,-5,Z0}, {-5,0,Z0}, {-5,5,Z1}, {10,0,Z0}, {5,-5,Z1}, {5,0,Z1}, {0,0,Z0}, // R {0,20,Z0}, {10,0,Z0}, {5,-5,Z0}, {-5,-5,Z0}, {-10,0,Z0}, {15,-10,Z1}, {5,0,Z1}, {0,5,Z0}, // S {5,-5,Z0}, {5,0,Z0}, {5,5,Z0}, {-15,10,Z0}, {5,5,Z0}, {5,0,Z0}, {5,-5,Z1}, {5,-15,Z1}, {0,20,Z0}, // T {15,0,Z1}, {-7,0,Z0}, {0,-20,Z1}, {12,0,Z1}, {0,20,Z0}, // U {0,-15,Z0}, {5,-5,Z0}, {5,0,Z0}, {5,5,Z0}, {0,15,Z1}, {5,-20,Z1}, {0,20,Z0}, // V {7,-20,Z0}, {8,20,Z0}, {5,-20,Z1}, {0,20,Z0}, // W {5,-20,Z0}, {5,10,Z0}, {5,-10,Z0}, {5,20,Z1}, {5,-20,Z1}, {0,20,Z0}, // X {15,-20,Z1}, {-15,0,Z0}, {15,20,Z1}, {5,-20,Z1}, {0,20,Z0}, // Y {7,-10,Z0}, {8,10,Z1}, {-8,-10,Z0}, {0,-10,Z1}, {13,0,Z1}, {0,20,Z0}, // Z {15,0,Z0}, {-15,-20,Z0}, {15,0,Z1}, {5,0,Z1}, {0,0,Z0}, // Ñ {0,16,Z0}, {15,-16,Z0}, {0,16,Z1}, {-10,4,Z0}, {10,0,Z1}, {10,-20,Z1}, {15,0,Z1} // ESPACIO }; //··································································· void setup () { int ii,jj; // Contadores // Define las patillas de los motores en la matriz Motor[0][0]=X1; Motor[0][1]=X3; Motor[0][2]=X2; Motor[0][3]=X4; Motor[1][0]=Y3; Motor[1][1]=Y1; Motor[1][2]=Y4; Motor[1][3]=Y2; // Define las patillas de control de los motores for(ii=0;ii<2;ii++) for(jj=0;jj<4;jj++) pinMode(Motor[ii][jj], OUTPUT); fase[0]=fase[1]=0; Serial.begin(115200); ServoZ.attach(LAPIZ); ServoZ.write(Z1); EstLapiz=Z1; // reset(); paso[0]=paso[1]=0; delay(1000); ParaMotor(EJEX); ParaMotor(EJEY); Serial.println("Trazador preparado"); delay(1000); } //··································································· void loop () { char cad[100]; int ii; if (Serial.available() > 0) { ii=0; while (Serial.available() > 0) { cad[ii]=Serial.read(); ii++; } cad[ii]=0; if (cad[0]>0) { // Gestiona comandos de control if (cad[0]=='*') { Comando(cad); } else { EscribeFrase(cad); Serial.println(cad); } } } delay(1000); } //··································································· void reset(void) { int ii; // Reset de eje X for (ii=0;ii<=LIMX;ii++) { PasoMotor(false,EJEX); delay(50); } // Reset de eje Y for (ii=0;ii<=LIMY;ii++) { PasoMotor(false,EJEY); delay(50); } paso[0]=paso[1]=0; } //··································································· void EscribeFrase(char *frase) { int ii=0; while(frase[ii]!=0) { EscribeLetra(frase[ii]); ii++; } } //··································································· void EscribeLetra(char letra) { int ii; int iletr=letra; // Caso especial de Ñ o ESPACIO if (iletr==-47) iletr=91; else if (iletr==32) iletr=92; for(ii=PosLetras[iletr-'A'];ii<PosLetras[iletr-'A'+1];ii++) { MueveEjes((int)letras[ii][0],(int)letras[ii][1]); if (letras[ii][2]!=EstLapiz) { ServoZ.write((int)letras[ii][2]); EstLapiz=(int)letras[ii][2]; delay(dVelTrazador); } } } //··································································· void Comando(char *cad) { switch(cad[1]) { case 'M': // Para motores ParaMotor(EJEX); ParaMotor(EJEY); break; case 'N': // Nueva línea MueveEjes(-paso[0],-25); break; } } //··································································· void MueveEjes(int MueveX,int MueveY) { // Definición y cálculo de parámetros de la línea int DistanciaX=abs(MueveX); int DistanciaY=abs(MueveY); int Distancia=max(DistanciaX,DistanciaY); int PasoX=(DistanciaX>0)? Distancia/DistanciaX : 0; int PasoY=(DistanciaY>0)? Distancia/DistanciaY : 0; int ii,iiX,iiY; // Mueve ejes simultáneamente para trazar la línea for(ii=iiX=iiY=0;ii<Distancia;ii++,iiX++,iiY++) { if ((iiX>=PasoX)&&(PasoX>0)) { if (MueveX>0) PasoMotor(true,EJEX); else PasoMotor(false,EJEX); iiX=0; } if ((iiY>=PasoY)&&(PasoY>0)) { if (MueveY>0) PasoMotor(false,EJEY); else PasoMotor(true,EJEY); iiY=0; } delay(dVelTrazador); } paso[0]+=MueveX; paso[1]+=MueveY; } //··································································· void update_motor(int eje) { int ii; for (ii = 0 ; ii < 4 ; ii++) digitalWrite (Motor[eje][ii], LOW) ; digitalWrite (Motor[eje][fase[eje]], HIGH) ; } //··································································· void PasoMotor(boolean dir,int eje) { if (dir) fase[eje] += 1 ; else fase[eje] -= 1 ; fase[eje] &= 3 ; update_motor(eje) ; } //··································································· void ParaMotor(int eje) { int ii; for (ii = 0 ; ii < 4 ; ii++) digitalWrite (Motor[eje][ii], LOW) ; }
Probamos el programa y escribe razonablemente bien:
Deja una respuesta