Voici notre code :
#include <Adafruit_MotorShield.h>
#include <Adafruit_PWMServoDriver.h>
#include "config.h"
#include <Servo.h>
#define PEN_UP_ANGLE (170)
#define PEN_DOWN_ANGLE (0)
#define PEN_DELAY (250)
static Servo s1;
char buffer[MAX_BUF];
int sofar;
float px, py, pz;
float fr=0;
long step_delay;
char mode_abs=1;
/**
- delai pour le nombre approprié de ms
- le nombre entré est le temps qu'on veut attendre en ms
*/
void pause(long ms) {
delay(ms/1000);
delayMicroseconds(ms%1000);
}
void setPenAngle(int pen_angle) {
if(pz!=pen_angle) {
pz=pen_angle;
if(pz<PEN_DOWN_ANGLE) pz=PEN_DOWN_ANGLE;
if(pz>PEN_UP_ANGLE ) pz=PEN_UP_ANGLE;
s1.write( (int)pz );
delay(PEN_DELAY);
}
}
/**
- Configurer le feedrate (vitesse à laquelle les moteurs vont bouger)
- le nombre entré est la nouvelle vitesse en steps/sec
*/
void feedrate(float nfr) {
if(fr==nfr) return;
if(nfr>MAX_FEEDRATE || nfr<MIN_FEEDRATE) {
Serial.print(F("Le nouveau feedrate doit etre plus grand que "));
Serial.print(MIN_FEEDRATE);
Serial.print(F("steps/s et moins que "));
Serial.print(MAX_FEEDRATE);
Serial.println(F("steps/s."));
return;
}
step_delay = 1000000.0/nfr;
fr=nfr;
}
/**
- Configurer la position logique
- l'entrée npx sera la nouvelle position x
- l'entrée npy sera la nouvelle position y
*/
void position(float npx,float npy) {
// ici est un bon endroit pour ajouter des tests de sanité 
px=npx;
py=npy;
}
/**
- Utilise l'algorithme de la ligne de bresenham pour bouger les deux moteurs
- l'entrée newx sera la destination d'x
- l'entrée newy sera la destination d'y
**/
void line(float newx,float newy, float z) {
long dx=newx-px;
long dy=newy-py;
int dirx=dx>0?1:-1;
int diry=dy>0?-1:1;
dx=abs(dx);
dy=abs(dy);
long i;
long over=0;
setPenAngle((int)z);
if(dx>dy) {
for(i=0;i<dx;++i) {
m1step(dirx);
over+=dy;
if(over>=dx) {
over-=dx;
m2step(diry);
}
pause(step_delay);
}
} else {
for(i=0;i<dy;++i) {
m2step(diry);
over+=dx;
if(over>=dy) {
over-=dy;
m1step(dirx);
}
pause(step_delay);
}
}
px=newx;
py=newy;
}
static float atan3(float dy,float dx) {
float a=atan2(dy,dx);
if(a<0) a=(PI*2.0)+a;
return a;
}
static void arc(float cx,float cy,float x,float y, float z, float dir) {
float dx = px - cx;
float dy = py - cy;
float radius=sqrt(dxdx+dydy);
float angle1=atan3(dy,dx);
float angle2=atan3(y-cy,x-cx);
float theta=angle2-angle1;
if(dir>0 && theta<0) angle2+=2PI;
else if(dir<0 && theta>0) angle1+=2PI;
theta=angle2-angle1;
float len = abs(theta) * radius;
int i, segments = ceil( len * MM_PER_SEGMENT );
float nx, ny, nz, angle3, scale;
for(i=0;i<segments;++i) {
scale = ((float)i)/((float)segments);
angle3 = ( theta * scale ) + angle1;
nx = cx + cos(angle3) * radius;
ny = cy + sin(angle3) * radius;
nz = ( z - pz ) * scale + pz;
line(nx,ny,nz);
}
line(x,y,z);
}
/**
- Chercher le caractère /code/ dans le buffer et lire le float qui le suit immédiatement après.
- retourne la valeur trouvée. Si rien n'est trouvé, /val/ est retourné.
- l'entrée code est le caractère qu'on cherche.
- l'entrée val est la valeur de retour si /code/ n'est pas trouvé.
**/
float parsenumber(char code,float val) {
char *ptr=buffer;
while(ptr && *ptr && ptr<buffer+sofar) {
if(*ptr==code) {
return atof(ptr+1);
}
ptr=strchr(ptr,' ')+1;
}
return val;
}
/**
- envoyer une chaîne suivie d'un float à la ligne série. Pratique pour débugger .
- l'entrée code est la chaîne.
- l'entrée val est le float.
*/
void output(char *code,float val) {
Serial.print(code);
Serial.println(val);
}
/**
- envoyer la position actuelle, le feedrate, et le mode absolu.
*/
void where() {
output("X",px);
output("Y",py);
output("Z",pz);
output("F",fr);
Serial.println(mode_abs?"ABS":"REL");
}
/**
- affiche des informations utiles
*/
void help() {
Serial.print(F("GcodeCNCDemo2AxisV"));
Serial.println(VERSION);
Serial.println(F("Commandes:"));
Serial.println(F("G00 [X(steps)] [Y(steps)] [F(feedrate)]; - ligne"));
Serial.println(F("G01 [X(steps)] [Y(steps)] [F(feedrate)]; - ligne"));
Serial.println(F("G02 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - arc de cercle direction horaire"));
Serial.println(F("G03 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - arc de cercle direction anti-horaire"));
Serial.println(F("G04 P[secondes]; - delai"));
Serial.println(F("G90; - mode absolu"));
Serial.println(F("G91; - mode relatif"));
Serial.println(F("G92 [X(steps)] [Y(steps)]; - change la position logique"));
Serial.println(F("M18; - desactiver les moteurs"));
Serial.println(F("M100; - re-afficher ce message"));
Serial.println(F("M114; - donne la position actuelle et le feedrate"));
Serial.println(F("Toutes les commandes finissent par un retour a la ligne."));
}
/**
- Lit le buffer d'entrée et cherche n'importe quelle commande reconnaissable. Un seul G OU M par ligne.
*/
void processCommand() {
int cmd = parsenumber('G',-1);
switch(cmd) {
case 0: {
feedrate(parsenumber('F',fr));
line( parsenumber('X',(mode_abs?px:0)) + (mode_abs?0:px),
parsenumber('Y',(mode_abs?py:0)) + (mode_abs?0:py),
parsenumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz));
break;
}
case 1: {
feedrate(parsenumber('F',fr));
line( parsenumber('X',(mode_abs?px:0)) + (mode_abs?0:px),
parsenumber('Y',(mode_abs?py:0)) + (mode_abs?0:py),
parsenumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz));
break;
}
case 2: {
feedrate(parsenumber('F',fr));
arc(parsenumber('I',(mode_abs?px:0)) + (mode_abs?0:px),
parsenumber('J',(mode_abs?py:0)) + (mode_abs?0:py),
parsenumber('X',(mode_abs?px:0)) + (mode_abs?0:px),
parsenumber('Y',(mode_abs?py:0)) + (mode_abs?0:py),
parsenumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz),
(cmd==2) ? -1 : 1);
break;
}
case 3: {
feedrate(parsenumber('F',fr));
arc(parsenumber('I',(mode_abs?px:0)) + (mode_abs?0:px),
parsenumber('J',(mode_abs?py:0)) + (mode_abs?0:py),
parsenumber('X',(mode_abs?px:0)) + (mode_abs?0:px),
parsenumber('Y',(mode_abs?py:0)) + (mode_abs?0:py),
parsenumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz),
(cmd==2) ? -1 : 1);
break;
}
case 4: pause(parsenumber('P',0)*1000); break;
case 90: mode_abs=1; break;
case 91: mode_abs=0; break;
case 92:
position( parsenumber('X',0),
parsenumber('Y',0) );
break;
default: break;
}
cmd = parsenumber('M',-1);
switch(cmd) {
case 18:
disable();
break;
case 100: help(); break;
case 114: where(); break;
default: break;
}
}
/**
- prépare le buffer d'entrée à recevoir un nouveau message et dire à la liaison série que nous sommes prêt pour plus.
*/
void ready() {
sofar=0;
Serial.print(F(">"));
}
/**
- Première chose que la machine exécute au démarrage. Ne se lance qu'une seule fois.
*/
void setup() {
s1.attach(10);
setPenAngle(PEN_UP_ANGLE);
Serial.begin(BAUD);
setup_controller();
feedrate((MAX_FEEDRATE + MIN_FEEDRATE)/2);
help();
ready();
}
/**
- Après setup() cette machine répètera le loop() indéfinniment.
*/
void loop() {
while(Serial.available() > 0) {
char c=Serial.read();
Serial.print(c);
if(sofar<MAX_BUF-1) buffer[sofar++]=c; // enregistre le
if(c=='\n') {
buffer[sofar]=0; // arrête le buffer comme ça les fonctions chaînes fonctionnent correctement
Serial.print(F("\r\n")); // retourne un écho pour les humains
processCommand(); // faire quelque chose avec la commande
ready();
}
}
}
/**
- This file is part of GcodeCNCDemo.
-
- GcodeCNCDemo is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- GcodeCNCDemo is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Foobar. If not, see http://www.gnu.org/licenses/.
*/
Voici notre de code d'erreur:
C:\Users\Art3fact Lab\Desktop\drawbot\drawbot ART3FACTLAB\GcodeCNCjulien\ams2.ino:18:45: fatal error: utility/Adafruit_PWMServoDriver.h: No such file or directory
#include "utility/Adafruit_PWMServoDriver.h"
^
compilation terminated.
exit status 1
Error compiling.
A library named Adafruit-PWM-Servo-Driver-Library-master already exists