Bonjour bernie31
Comment va ton Assistant?
Voilà, j'ai ajouté la possibilité de jouer les émotion dans les 2 sens et de par là, le homing également, ça se règle ici:
DIR inverted
concerne le câblage et commande s'il faut "inverser les fils" et est testé par les commandes en mode trace MOTCW et MOTCCW, ces 2 commandes ne tiennent pas compte de emot inverted
.
emot inverted
dit s'il faut inverser toutes les opérations de ce moteur (je viens de m'apercevoir que emot inverted
n'est pas très bon comme dénomination je vais changer ça), y compris le homing.
Essaies ça:
Le programme:
/*
Name: bernie31_TeteDeCheval.ino
Created: 18.02.2024
Author: jpbbricole/bernie31
https://forum.arduino.cc/t/configuration-pour-animation-tete-cheval/1225121
Remarque: Animation d'une tête de chaval aved des moteurs pas à pas
19.02.2024 Première version #25
04.05.2024 Ajout des servo (4 moteurs 1 servo) #271
20.05.2024 Modification introduction au mode trace #271
21.05.2024 En mode trace test LED
Modifié homing avec pushButt #295
02.07.2024 AccelStepper et MultiStepper en local #431
17.07.2024 Introduction des groupes de moteurs #445
02.09.2024 Ajout de Dernière réception BT dans mode trace #478
09.09.2024 Ajout enregistrement des macro (10) #482
18.09.2024 Ajout commande des macro depuis MAI #489
04.10.2024 Ajout modifications du post #500/#501
30.10.2024 Toutes les bibliothèques dans le dossier src #536
16.11.2024 Ajout séquence de homing #584
18.11.2024 Ajout séquence de homing individuel
En mode trace commandes via Bluetooth
Paramètres servo avec #if #593
24.11.2024 en mode trace, ajout commande AUTO et TRACE
Corrigé bug du homing moteur part à l'envers
Commande de l'alimentation des servo #621
29.11.2024 Possibilité d'émotion sense CCW #649
*/
#include "src/AccelStepper.h" // https://www.pjrc.com/teensy/td_libs_AccelStepper.html
#include "src/MultiStepper.h" // https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html
#include "src/JC_Button.h">" // https://github.com/JChristensen/JC_Button Gestion du bouton poussoir du bouton rotatif
#include "src/Adafruit_NeoPixel.h" // Gestion des LED RGB Neopixel https://github.com/adafruit/Adafruit_NeoPixel
#include "src/VarSpeedServo.h" // https://github.com/netlabtoolkit/VarSpeedServo
#include <EEPROM.h> // Pour sauvegarde des paramètres en mémoire EEPROM
#define bernie31 // Pour activer les paramètres de bernie31
//------------------------------------- Etats du programme
const String prgEtatLabel[] = {"En Attente", "Joue", "Manuel", "En travail", "Warning"};
enum {prgEtatEnAttente, prgEtatPlaying, prgEtatManual, prgEtatEnTravail, prgEtatWarning}; // Liste des divers etats du programme
int prgEtat; // Etat en cours du programme
//------------------------------------- Moteur pas à pas (mpap) et groupes de moteurs
enum {mpapGroupe1, mpapGroupe2, mpapGroupeNombre}; // Liste des groupes de moteurs
struct mpapParamDef // Définition des paramètres des mpap
{
const long pasTour; // Nombre de pas par tout
const int microPas; // Nombre de micro pas
float speed; // Vitesse mximum
float acceleration; // Accélération
long zeroOffset; // Déplacement entre le homing et la position de départ
const int dirPin; // Direction
const int stepPin; // Pas
const int homingPin; // Position de départ
const bool dirInverted; // Direction inversée
const bool emotInverted; // Si le jeu de l'émotion est dans le sens inversé
int groupe; // Groupe de moteurs
};
mpapParamDef mpapParam[] =
{
#ifdef bernie31
// Pas/tour micro pas vitesse acceleration zero Offset DIR STEP HOME DIR invert emot invert Groupe
{200, 1, 750.0, 800.0, 10, 22, 23, A0, false, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 24, 25, A1, false, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 26, 27, A2, false, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 28, 29, A3, true, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 30, 31, A4, true, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 32, 33, A5, true, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 34, 35, A6, true, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 36, 37, A7, false, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 38, 39, A8, true, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 40, 41, A9, false, false, mpapGroupe1},
{200, 1, 750.0, 800.0, 10, 42, 43, A10, false, false, mpapGroupe2},
{200, 1, 750.0, 800.0, 10, 44, 45, A11, false, false, mpapGroupe2},
{200, 1, 750.0, 800.0, 10, 46, 47, A12, false, false, mpapGroupe2},
#else
{200, 1, 250.0, 800.0, 10, 22, 23, A0, true, false, mpapGroupe1},
{200, 1, 250.0, 800.0, 10, 24, 25, A1, false, false, mpapGroupe1},
{200, 1, 250.0, 800.0, 10, 26, 27, A2, false, false, mpapGroupe2},
{200, 1, 250.0, 800.0, 10, 28, 29, A3, true, true, mpapGroupe2},
#endif
};
const int mpapNombre = sizeof(mpapParam) / sizeof(mpapParam[0]); // Nombre de moteurs
/*
Tablesu des pin d'enable des A4988, la dernière position est ENABLE en permanence
les premières, seulement quand nécessaire
*/
const int driverEnablePin[] = {8, 9, 10}; // Pin ENABLE, la dernière est active en permanence
const int driverEnablePinNombre = sizeof(driverEnablePin) / sizeof(driverEnablePin[0]); // Nombre de pin enable
const int driverENApinEtatOn = LOW; // Pin ENABLE etat actif
const int mpapEnaSet = true; // Pour activer ENABLE
const int mpapEnaPartiel = true; // Pour activer ENABLE partiel, toutes sauf la dernière
const int mpapHomingEtatOn = LOW; // Etat quand homing actif actif
enum {mpapDirCw, mpapDirCcw}; // Direstions des moteurs
//------------------------------------- Séquence du homing
#ifdef bernie31
const int homingSequence[] = {0, 1, 3, 2, 4, 5, 6, 8, 7, 9, 10, 11, 12}; // Ordre des moteur pour le homing
#else
const int homingSequence[] = {3, 2, 1, 0}; // Ordre des moteur pour le homing
#endif
//------------------------------------- Tableau des moteurs
AccelStepper mpap[] =
{
#ifdef bernie31
{AccelStepper::DRIVER, mpapParam[0].stepPin, mpapParam[0].dirPin},
{AccelStepper::DRIVER, mpapParam[1].stepPin, mpapParam[1].dirPin},
{AccelStepper::DRIVER, mpapParam[2].stepPin, mpapParam[2].dirPin},
{AccelStepper::DRIVER, mpapParam[3].stepPin, mpapParam[3].dirPin},
{AccelStepper::DRIVER, mpapParam[4].stepPin, mpapParam[4].dirPin},
{AccelStepper::DRIVER, mpapParam[5].stepPin, mpapParam[5].dirPin},
{AccelStepper::DRIVER, mpapParam[6].stepPin, mpapParam[6].dirPin},
{AccelStepper::DRIVER, mpapParam[7].stepPin, mpapParam[7].dirPin},
{AccelStepper::DRIVER, mpapParam[8].stepPin, mpapParam[8].dirPin},
{AccelStepper::DRIVER, mpapParam[9].stepPin, mpapParam[9].dirPin},
{AccelStepper::DRIVER, mpapParam[10].stepPin, mpapParam[10].dirPin},
{AccelStepper::DRIVER, mpapParam[11].stepPin, mpapParam[11].dirPin},
{AccelStepper::DRIVER, mpapParam[12].stepPin, mpapParam[12].dirPin},
#else
{AccelStepper::DRIVER, mpapParam[0].stepPin, mpapParam[0].dirPin},
{AccelStepper::DRIVER, mpapParam[1].stepPin, mpapParam[1].dirPin},
{AccelStepper::DRIVER, mpapParam[2].stepPin, mpapParam[2].dirPin},
{AccelStepper::DRIVER, mpapParam[3].stepPin, mpapParam[3].dirPin},
#endif
};
MultiStepper mpapGroupe[mpapGroupeNombre]; // Groupes de moteurs
//------------------------------------- Servomoteurs (servo)
struct servoParamDef // Définition des paramètres des servo
{
const int pin; // Pin de connexion
int posMin; // Position minimum en microsecondes
int posMax; // Position maximum en microsecondes
byte speed; // Vitesse du servo 0-255
boolean wait; // Si attendre fin du mouvement
const int angleMax; // Angle maximum du servo
int zeroOffset; // Déplacement entre le homing et la position de d part
};
//------------------------------------- Tableau des servo
servoParamDef servoParam[] =
{
#ifdef bernie31
// Pin Pos min Pos Max Speed Wait angle Zero offset
{ 50, 800, 2200, 25, false, 120, 90},
};
#else
{ 50, 800, 2200, 25, false, 120, 0},
};
#endif
const int servoNombre = sizeof(servoParam) / sizeof(servoParam[0]); // Nombre de servo
VarSpeedServo servo[servoNombre]; // Tableau des servo
const int servoPowerSwitchPin = 5; // Activation de l'alimentation des servo
const int servoPowerSwitchOn = HIGH; // Etat pour activer
/*------------------------------------- Interfaces (intf)
ce tableau contient la répartition des divers ressources MPAP, servo ...
pour constituer l'ensemble nécessaire à l'animation
L'index est la position du MPAP dans le tableau des MPAP mpapParam[]
ou du servo dans le tableau servoParam[]
*/
enum {intfTypeMoteur, intfTypeServo, intfTypeInconnu}; // Liste des types d'interfaces
struct intfDef // Définition des paramètres des interfaces
{
const int type; // Type de l'interface
const int index; // Index dans tableau de la resource mpapParam[] ou servoParam[]
};
intfDef intf[] =
{
#ifdef bernie31
{intfTypeMoteur, 0},
{intfTypeMoteur, 1},
{intfTypeMoteur, 2},
{intfTypeMoteur, 3},
{intfTypeMoteur, 4},
{intfTypeMoteur, 5},
{intfTypeMoteur, 6},
{intfTypeMoteur, 7},
{intfTypeMoteur, 8},
{intfTypeMoteur, 9},
{intfTypeMoteur, 10},
{intfTypeMoteur, 11},
{intfTypeMoteur, 12},
{intfTypeServo, 0},
#else
{intfTypeMoteur, 0},
{intfTypeMoteur, 1},
{intfTypeMoteur, 2},
{intfTypeMoteur, 3},
{intfTypeServo, 0},
#endif
};
const int intfNombre = sizeof(intf) / sizeof(intf[0]); // Nombre d'interfaces
struct intfParamDef // Pour stocker les paramètres de l'interface en cours
{
int type; // Type de l'interface
int index; // Index dans tableau de la resource
};
intfParamDef intfParam;
const int emotNombre = 6;
int emotNum; // Emotion en cours
//------------------------------------- Manuel
const int buttPpin = 7; // Pin du bouton poussoir du codeur rotatif
const boolean buttPullup = true; // PULLUP internes
const boolean buttInvert = true; // Actif à LOW
const int buttDebounce = 20; // Temps anti rebonds
Button pushButt(buttPpin, buttPullup, buttInvert, buttDebounce);
//------------------------------------- LED signalisation (signLed)
enum signLedIndex {signLedFctInfo, signLedFctWarning, signLedFctNombre};
const int signLedBusPin = 12; // Bus des LED Neopixel
const int signLebBrightMax = 5; // LED Luminosité maximum
Adafruit_NeoPixel signLed = Adafruit_NeoPixel(signLedFctNombre, signLedBusPin, NEO_GRB + NEO_KHZ800); // Création de l'objet Neopixel signLed
enum signLedColorsIndex {signColGreen, signColBlue, signColRed, signColOrange, signColYellow, signColWithe, signColOff, signColLatest};
uint32_t signLedColors[signColLatest]; // Valeurs RGB pour les couleurs (Tableau)
const unsigned long signledBlinkTempo = 250; // Periode de clignotement
unsigned long signledBlinkMillis = millis(); // Periode de clignotement, chrono
//------------------------------------- Communications externes (extser)
#define externSerial Serial2 // Connexion série externe
const String extFeedbSep = ","; // Feedback, séparateur des paramètres
//------------------------------------- Communications Bluetooth
#define btSerial Serial3 // Connexion série Bluetooth
//------------------------------------- Macro commandes (mac)
String macCmdRx = ""; // Macro reçue
const String macCmdSeparator = "|"; // Séparateur des commandes dans la macro
unsigned long macTimerTempo = 0; // Temporisation dans une macro (Commande TEMP)
unsigned long macTimerMillis = 0; // Temporisation dans une macro, chrono
boolean macIsRunning = false; // Si une macro est en cours d'exéécution
const int macArraySize = 10; // Taille du tableau des macro
const int macArrayLenght = 40; // Taille maximum d'une macro en tableau
//------------------------------------- Divers
const int traceModeOnPin = 11; // Pin pour declencher le mode trace/mise au point
const int traceModeOnPinEtatOn = LOW; // Etat quand actif
boolean traceAuto = true; // Affiche toutes les traceLedTempo millisecondes, la trace
//------------------------------------- Paramètres en EEPROM (eeparam)
struct eeparamDef // Définition des paramètres en EEPROM
{
int prgEtat; // Etat du programme au moment de la sauvegarde
int emotNum; // Num ro de l'émotion au moment de la sauvegarde
long intfEmotPos[emotNombre][intfNombre]; // Position des interfaces pour les n emotions
long zeroOffset[intfNombre]; // Déplacement entre le homing et la position de départ
char macArray[macArraySize][macArrayLenght]; // Tableau des macro
};
eeparamDef eeprParam; // Paramàtres sauvés en EEPROM
const word eeprCheckWord = 0xCAFE; // Pour repérer si c'est un premier usage
const int eeprOffsetCheckWord = 0; // Adresse du début de la mémoire
const int eeprOffeeprParam = eeprOffsetCheckWord + sizeof(eeprCheckWord); // Adresse du début de la mémoire des UID
void setup()
{
Serial.begin(115200);
btSerial.begin(9600);
delay(500);
Serial.println("Version:\t" + systemGetVersion());
Serial.println("\t\t13 moteurs max.");
pinMode(servoPowerSwitchPin, OUTPUT); // Commande de l'alimentation des servo
digitalWrite(servoPowerSwitchPin, !servoPowerSwitchOn); // Couper l'alimentation
pinMode(traceModeOnPin, INPUT_PULLUP);
if (digitalRead(traceModeOnPin) != traceModeOnPinEtatOn) // Si pas mode trace
{
//--------------------------------- Initialisation EEPROM
word eeprCheck; // Mot de test
EEPROM.get(eeprOffsetCheckWord, eeprCheck); // Lecture du mot test
EEPROM.get(eeprOffeeprParam, eeprParam); // Restauration des paramètres
if (eeprCheck != eeprCheckWord) // Si premier usage
{
EEPROM.put(eeprOffsetCheckWord, eeprCheckWord); // Ecriture du mot de test
Serial.println(F("\n!!!! PREMIER USAGE !!!!"));
Serial.println(F("\tNecessite un homing !!!"));
prgEtatChange(prgEtatWarning);
}
else
{
Serial.println(F("\tEEPROM OK"));
}
//--------------------------------- Contrôle des conditions d'arret du programme
if (eeprParam.prgEtat != prgEtatEnAttente) // S'il y a eu crash ou reset
{
Serial.println(F("\nNecessite un homing !!!"));
Serial.println(F("Maintenez le bouton poussoir presse et faites un reset !!!"));
Serial.println(F("ou"));
Serial.println(F("Lancez la commande HOMING !!!"));
prgEtatChange(prgEtatWarning);
}
else
{
emotRestore(eeprParam.emotNum); // Restauration de l'émotion
prgEtatChange(eeprParam.prgEtat);
}
}
//-------------------------------- LED de signalisation
signLedInitialisation();
signLedDisplay(signLedFctInfo, signColBlue, 0);
signLedDisplay(signLedFctWarning, signColRed, 0);
Serial.println("\nAnimation avec " + String(intfNombre) + " interfaces");
//------------------------------------ initialisation des moteurs
for (int e = 0; e < driverEnablePinNombre; e ++)
{
pinMode(driverEnablePin[e], OUTPUT);
}
mpapDriverEnable(mpapEnaSet, !mpapEnaPartiel);
for (int m = 0; m < mpapNombre; m ++)
{
mpap[m].setSpeed(mpapParam[m].speed);
mpap[m].setMaxSpeed(mpapParam[m].speed);
mpap[m].setAcceleration(mpapParam[m].acceleration);
if (mpapParam[m].emotInverted) // Si émotion jouée CCW
{
mpap[m].setPinsInverted(!mpapParam[m].dirInverted); // Inverser le sens du moteur
}
else
{
mpap[m].setPinsInverted(mpapParam[m].dirInverted); // Inverser le sens du moteur
}
mpapGroupe[mpapParam[m].groupe].addStepper(mpap[m]); // Ajout de ce moteur au groupe
pinMode(mpapParam[m].homingPin, INPUT_PULLUP); // Pin du homing
}
//------------------------------------ initialisation des servo
for (int s = 0; s < servoNombre; s ++)
{
servo[s].attach(servoParam[s].pin,servoParam[s].posMin, servoParam[s].posMax); // Activation des servo
}
delay(1500);
if (digitalRead(traceModeOnPin) != traceModeOnPinEtatOn) // Si pas mode trace
{
prgEtatChange(eeprParam.prgEtat);
pushButt.read();
if (pushButt.isPressed()) // Si BP est pressé = homing
{
commandeExecute("HOMING");
}
}
else
{
traceModeStart();
}
digitalWrite(servoPowerSwitchPin, servoPowerSwitchOn); // Alimenter les servo
#ifdef bernie31 // Si l'utilisateur est
#else
//settingJpbbricole();
#endif
}
void loop()
{
//--------------------------------- Commandes moniteur
if (Serial.available())
{
String cmdRx = Serial.readStringUntil('\n'); // Réception de la commande terminée par Nouvelle ligne
commandeExecute(cmdRx);
}
//--------------------------------- Commandes externes
if (btSerial.available())
{
String cmdRx = btSerial.readStringUntil('\n'); // Réception de la commande terminée par Nouvelle ligne
commandeExecute(cmdRx);
}
//--------------------------------- Commande des moteurs par groupe
for (int g = 0; g < mpapGroupeNombre; g ++) // Liste des groupes
{
mpapGroupe[g].run(); // Marche des groupes
}
//--------------------------------- Surveillance des moteurs
if (prgEtat == prgEtatPlaying)
{
int mpapRunningNbr = 0;
for (int m = 0; m < mpapNombre; m ++)
{
if (mpap[m].distanceToGo() != 0) // Si moteur pas arrivé
{
mpapRunningNbr ++; // Compter ce moteur
}
}
if (mpapRunningNbr == 0) // Si tout les moteurs arrivés
{
prgEtatChange(prgEtatEnAttente);
}
}
//------------------------------------ Lecture du bouton poussoir
pushButt.read();
if (pushButt.pressedFor(1000)) // Si BP presse 1 seconde
{
if(prgEtat == prgEtatEnAttente) // Si en mode en attente
{
prgEtatChange(prgEtatManual); // Retour en mode manuel
}
}
else if (pushButt.wasPressed()) // Si BP a été pressé
{
if (prgEtat == prgEtatManual) // Si en mode manuel, passer en attente
{
prgEtatChange(prgEtatEnAttente); // Retour en mode en attente
}
}
//--------------------------------- Clignotement LED warning
if (prgEtat == prgEtatManual || prgEtat == prgEtatWarning)
{
if (millis() - signledBlinkMillis >= signledBlinkTempo) // Si periode clignotement
{
static boolean blinkOn;
if (blinkOn)
{
signLedDisplay(signLedFctWarning, signColRed, 0); // Allumer la LED warning
}
else
{
signLedDisplay(signLedFctWarning, signColOff, 0); // Eteindre la LED warning
}
blinkOn = !blinkOn;
signledBlinkMillis = millis();
}
}
//--------------------------------- Macro Commandes
if (prgEtat == prgEtatEnAttente)
{
if (macTimerTempo == 0 && macIsRunning) // Si pas de tempo en route et reste des macro à exécuter
{
macExecuteNext(); // Exécuter la macro suivante
}
}
//--------------------------------- Macro Temporisation
if (macTimerTempo != 0 && (millis() - macTimerMillis >= macTimerTempo))
{
Serial.println(F("Tempo FIN"));
macTimerTempo = 0; // Arrêt de la temporisation
}
}
void emotPlay(int emotIndex) // Jouer une émotion
{
Serial.println("Jouer emotion : " + String(emotIndex));
long mpapGrPos[mpapGroupeNombre][mpapNombre]; // Positions du groupe de moteurs
int groupeIntPosition[mpapGroupeNombre]; // Position dans le groupe
for (int g = 0; g < mpapGroupeNombre; g ++)
{
groupeIntPosition[g] = 0;
}
emotNum = emotIndex;
for (int i = 0; i < intfNombre; i ++) // Lister les interfaces
{
intfParam = intfParamGet(i); // Recherche des paramètres de cet interface
if (intfParam.type == intfTypeMoteur) // Si c'est un moteur
{
int groupeIndex = mpapParam[intfParam.index].groupe;
mpapGrPos[groupeIndex][groupeIntPosition[groupeIndex]] = eeprParam.intfEmotPos[emotIndex][i] * mpapParam[intfParam.index].microPas;
groupeIntPosition[groupeIndex] ++; // Position suivante dans le groupe
}
else if (intfParam.type == intfTypeServo) // Si c'est un servo
{
servoGotoAngle(intfParam.index, eeprParam.intfEmotPos[emotIndex][i]);
}
}
for (int g = 0; g < mpapGroupeNombre; g ++)
{
mpapGroupe[g].moveTo(mpapGrPos[g]);
}
}
void emotLearn(int emotNum) // Apprentissage d'une émotion
{
Serial.println("Apprentissage emotion : " + String(emotNum));
String emotPosListe = ""; // Liste des positions
for (int i = 0; i < intfNombre; i ++) // Lister les interfaces
{
intfParam = intfParamGet(i); // Recherche des paramètres de cet interface
if (intfParam.type == intfTypeMoteur) // Si c'est un moteur
{
eeprParam.intfEmotPos[emotNum][i] = mpapLearning(emotNum, intfParam.index); // Lecture de la position du moteur m
emotPosListe = emotPosListe +String(eeprParam.intfEmotPos[emotNum][intfParam.index]) + ",";
}
else if (intfParam.type == intfTypeServo) // Si c'est un servo
{
}
}
Serial.println("\tPositions : " + emotPosListe);
exterFeedback("LEARN" + extFeedbSep + String(emotNum) + extFeedbSep + emotPosListe);
}
void emotRecord(String cmdRx) // Enregistremenbt d'une émotion par commande emrec01,912, 33, 404, 55, 94
{
String subCmd = cmdRx.substring(0, cmdRx.indexOf(","));
int emotRec = subCmd.toInt();
subCmd = cmdRx.substring(cmdRx.indexOf(",") +1);
Serial.println("Enregistrement emotion : " + String(emotRec));
int intfNum = 0; // Numéro de l'interface
String charStep;
String intfPos = "";
subCmd += ",";
for (int l = 0; l < subCmd.length(); l ++)
{
charStep = subCmd.substring(l, l+1);
if (charStep == ",") // Si séparateur de pas de macro
{
if (intfNum < intfNombre)
{
eeprParam.intfEmotPos[emotRec][intfNum] = intfPos.toInt();
}
intfPos = "";
intfNum ++;
}
else
{
intfPos +=charStep;
}
}
}
void emotRestore(int emotIndex)
{
if (emotIndex > 0) // Si n'était pas home
{
Serial.println("Restauration de l'emotion : " + String(emotIndex));
emotNum = emotIndex;
for (int i = 0; i < intfNombre; i ++) // Lister les interfaces
{
intfParam = intfParamGet(i); // Recherche des paramètres de cet interface
if (intfParam.type == intfTypeMoteur) // Si c'est un moteur
{
mpap[intfParam.index].setCurrentPosition(eeprParam.intfEmotPos[emotIndex][i]); // Moteurs aux positions de l'émotion
}
else if (intfParam.type == intfTypeServo) // Si c'est un servo
{
servoGotoAngle(intfParam.index, eeprParam.intfEmotPos[emotIndex][i]);
}
}
}
else
{
Serial.println(F("Restauration de la position : HOME"));
for (int m = 0; m < mpapNombre; m ++)
{
mpap[m].setCurrentPosition(0); // Moteurs aux positions de l'émotion
}
}
}
void emotList() // Liszet les positions des émotions
{
Serial.println(F("\nListe des positions pour backup:"));
for (int e = 0; e < emotNombre; e ++)
{
String emotPosBackup = "EMREC" + String(e) + ",";
for (int i = 0; i < intfNombre; i ++)
{
emotPosBackup = emotPosBackup + String(eeprParam.intfEmotPos[e][i]) + ",";
}
Serial.println(emotPosBackup);
}
Serial.println("");
}
void prgEtatChange(int etatNum)
{
prgEtat = etatNum;
Serial.println("Etat du programme: " + prgEtatLabel[etatNum]);
if (prgEtat == prgEtatEnAttente)
{
mpapDriverEnable(!mpapEnaSet, mpapEnaPartiel); // Désactiver les premiers moteurs
signLedDisplay(signLedFctInfo, signColGreen, 0);
signLedDisplay(signLedFctWarning, signColGreen, 0);
}
else if (prgEtat == prgEtatPlaying)
{
mpapDriverEnable(mpapEnaSet, mpapEnaPartiel); // Activer les premiers moteurs
signLedDisplay(signLedFctInfo, signColBlue, 0);
}
else if (prgEtat == prgEtatEnTravail)
{
mpapDriverEnable(mpapEnaSet, mpapEnaPartiel); // Activer les premiers moteurs
signLedDisplay(signLedFctInfo, signColBlue, 0);
}
else if (prgEtat == prgEtatManual)
{
mpapDriverEnable(mpapEnaSet, mpapEnaPartiel); // Désactiver les premiers moteurs
signLedDisplay(signLedFctInfo, signColYellow, 0);
mpapDriverEnable(!mpapEnaSet, !mpapEnaPartiel); // Désactiver les moteurs
}
prgSettingSaveEEPROM();
}
//------------------------------------- Paramètres par défaut
void prgSettingDefault()
{
Serial.println(F("!!! Parametres par defaut"));
for (int e = 1; e < emotNombre; e ++)
{
for (int i = 0; i < intfNombre; i ++)
{
intfParam = intfParamGet(i); // Recherche des paramètres de cet interface
if (intfParam.type == intfTypeMoteur) // Si c'est un moteur
{
eeprParam.intfEmotPos[e][i] = mpapParam[intfParam.index].zeroOffset;
}
else if (intfParam.type == intfTypeServo) // Si c'est un servo
{
eeprParam.intfEmotPos[e][i] = servoParam[intfParam.index].zeroOffset;
}
}
}
macArrayInit(); // Initialisation de tablesu des macro
prgEtatChange(prgEtatEnAttente);
}
void prgSettingSaveEEPROM() // Sauvegarde des paramètres
{
Serial.println("Sauvegarde setting, Etat " + prgEtatLabel[prgEtat]);
eeprParam.prgEtat = prgEtat; // Sauvegarde de l'état du programme
eeprParam.emotNum = emotNum; // Sauvegarde de l'émotion en cours
EEPROM.put(eeprOffeeprParam, eeprParam); // Sauvegarde des paramètres
}
//------------------------------------- Moteurs
void mpapDriverEnable(bool enable, boolean partiel) // Pin ENABLE, si partial, toutesa dernière
{
int eLoop = (partiel == true) ? driverEnablePinNombre -1 : driverEnablePinNombre;
//Serial.println(eLoop);
for (int e = 0; e < eLoop; e ++)
{
digitalWrite(driverEnablePin[e], (enable == true) ? driverENApinEtatOn : !driverENApinEtatOn);
}
Serial.print("Drivers : ");
Serial.println((enable == true) ? "Enabled" : "Disabled");
}
long mpapHoming(int mpapNum) // Retour position 0, retourne le nombre de pas
{
signLedDisplay(signLedFctInfo, signColBlue, 0);
Serial.println("\tHoming moteur " + String(mpapNum));
mpap[mpapNum].setCurrentPosition(0); // Moteur position 0
long stepsToHome; // Mémoire de la position actuelle
mpap[mpapNum].moveTo(-32768);
while (true)
{
if (digitalRead(mpapParam[mpapNum].homingPin) == mpapHomingEtatOn) // Si moteur sur contact.
{
stepsToHome = abs(mpap[mpapNum].currentPosition()); // + mpapParam[mpapNum].zeroOffset;
mpap[mpapNum].stop();
mpap[mpapNum].setCurrentPosition(0); // Moteur position 0
break;
}
mpap[mpapNum].run();
}
signLedDisplay(signLedFctInfo, signColGreen, 0);
return stepsToHome;
}
long mpapHomingAndOffset(int mpapNum) // Retour position 0 + offset0
{
long stepsToHome = mpapHoming(mpapNum); // Mémoire de la position actuelle
mpap[mpapNum].runToNewPosition(mpapParam[mpapNum].zeroOffset * mpapParam[mpapNum].microPas);
return stepsToHome;
}
long mpapLearning(int emotNum, int mpapNum) // Pour mémoriser la position du moteur
{
long posActuelle;
if (emotNum == 0) // Si homing
{
posActuelle = mpap[mpapNum].currentPosition();
}
else
{
posActuelle = mpapHoming(mpapNum); // - (mpapParam[mpapNum].zeroOffset * mpapParam[mpapNum].microPas);
}
Serial.println("\t\tPosition apprise Emotion " + String(emotNum));
Serial.println("\t\tMoteur " + String(mpapNum) + " " + String(posActuelle) + " pas");
mpap[mpapNum].runToNewPosition(posActuelle); // + (mpapParam[mpapNum].zeroOffset * mpapParam[mpapNum].microPas));
return posActuelle;
}
void mpapTestCwCcw(int mpapDir, String mpapCmd) // Test des moteurs
{
Serial.println(mpapCmd);
int mpapNum = mpapCmd.substring(0, 2).toInt();
long mpapSteps = mpapCmd.substring(2).toInt();
Serial.println(mpapNum);
if (mpapParam[mpapNum].emotInverted) // Si émotion CCW
{
mpapSteps = (mpapDir == mpapDirCw) ? -mpapSteps : mpapSteps;
}
else
{
mpapSteps = (mpapDir == mpapDirCw) ? mpapSteps : -mpapSteps;
}
Serial.println(mpapSteps);
mpap[mpapNum].move(mpapSteps * mpapParam[mpapNum].microPas);
}
//------------------------------------- Servo
void servoGotoAngle(int servoNum, int servoAngle) // Angle en degrés
{
Serial.println("\tServo " + String(servoNum) + " > " + String(servoAngle));
servo[servoNum].write(servoAngle, servoParam[servoNum].speed, servoParam[servoNum].wait);
}
void servoTest(String servoCmd) // Test des servo
{
int servoNum = servoCmd.substring(0, 2).toInt();
int servoAngle = servoCmd.substring(2).toInt();
servoGotoAngle(servoNum, servoAngle);
}
//------------------------------------- Interfaces (intf)
intfParamDef intfParamGet(int intfNum) // Recherche des paramètres de l'interface
{
intfParamDef param;
param.type = intfTypeInconnu;
if (intfNum >= intfNombre)
{
param.type == intfTypeInconnu;
}
else
{
param.type = intf[intfNum].type;
param.index = intf[intfNum].index;
}
return param;
}
//------------------------------------- Macro (mac)
void macExecuteNext() // Exécute la macro suivante
{
String macCmd = macCmdRx.substring(0, macCmdRx.indexOf(macCmdSeparator)); // Recherche jusqu'au prochain séparatweur
macCmdRx = macCmdRx.substring(macCmdRx.indexOf(macCmdSeparator) +1); // Supprimer la commande qui va s'exécuter
if (macCmd.length() < 3)
{
macCmdRx = ""; // Macro terminée
Serial.println(F("\t\tMacro Terminee"));
exterFeedback("MACOK");
macIsRunning = false;
}
else
{
Serial.println("Macro Comande " + macCmd);
commandeExecute(macCmd);
}
}
void macArrayRecord(String macro) // Enregistrement d'une macro
{
int macroIndex = macro.substring(0, 1).toInt();
macroIndex = constrain(macroIndex, 0, macArraySize -1); // Limiterl'index
Serial.println("\t Macro #" + String(macroIndex));
macro = macro.substring(2); // Supprimer l'index et la virgule
Serial.println("\t " + macro);
strcpy(eeprParam.macArray[macroIndex], macro.c_str());
}
void macArrayInit()
{
for (int m = 0; m < macArraySize; m ++)
{
strcpy(eeprParam.macArray[m], "EM0|EM1|EM0|EM1|EM0|EM1|");
}
}
/*
Commandes depuis le moniteur:
HOMING Retour sur la position de départ + zeroOffset
EMn Joue l'émotion n
EMREC Enregistrement d'une émotion EMRECee,I1pos, I2pos, I3pos (I = interface) EMREC02,60, 70, 90, 100, 95
LEARNMn Apprend l'émotion n par enregistrement de la position des moteurs
LEARNSeeiiaaa Apprend l'angle du servo de l'émotion ee, de l'interface ii et de l'angle aaa
LIST Lister les positions des interfaces pour backup
MOTDISn 1 = moteurs désactivés 0 = activés
Attention !!! si un ou des moteurs ont été bougés, faire un HOMING ou un LEARNn
SERVOssaaa Fait aller le servo ss à l'angle aaa voir posMin, posMax et angleMax
DELnn Temporisation de nn millisecondes
% 0 macro
%RECn %REC8,EM4|em5|EM2|EM1|EM3|EM1| Pour enregistrer la macro 8 (0 à 9)
%PLAYn Jouer la macro n
%LIST Lister les macro pour backup
FACTORY Remet les paramètres du programme comme au départ
*/
void commandeExecute(String cmdRx)
{
cmdRx.trim(); // Nettoyage des caractères indésirables, CR, LF, TAB... et les espace de début et de fin
cmdRx.toUpperCase(); // Tout en majuscule
cmdRx.replace(" ", ""); // Supprimer les espaces
if (cmdRx.startsWith(F("EM"))) // Emotion
{
cmdRx.replace(F("EM"), ""); // On ne garde que le numéro de l'émotion
if (cmdRx.startsWith(F("REC"))) // Si c'est pour enregistrer une émotion
{
cmdRx.replace(F("REC"), "");
emotRecord(cmdRx); // Enregistrement de l'émotion
prgSettingSaveEEPROM(); // Sauvegarde de la nouvelle configuration
}
else // Jouer une émotion
{
int emotNum = cmdRx.toInt();
if (emotNum >= emotNombre)
{
Serial.println("\tNumero invalide " + String(emotNum));
signLedWarning(6, 150); // LED Warning
}
else
{
emotPlay(emotNum);
prgEtatChange(prgEtatPlaying);
}
}
}
else if (cmdRx.startsWith(F("HOMING"))) // Tout lkes moteurs au départ + zero offset
{
cmdRx.replace(F("HOMING"), "");
Serial.println(F("Homing moteurs"));
prgEtatChange(prgEtatEnTravail);
if (cmdRx == "") // Si pas de paramètres
{
for (int m = 0; m < mpapNombre; m ++)
{
mpap[m].setCurrentPosition(0);
}
for (int m = 0; m < mpapNombre; m ++)
{
//mpapHomingAndOffset(m);
mpapHomingAndOffset(homingSequence[m]); // Selon ordre des moteurs
eeprParam.intfEmotPos[0][m] = mpapLearning(0, m); // Lecture de la position du moteur m
}
}
else
{
int homeMotNum = cmdRx.toInt();
if (homeMotNum < 0 || homeMotNum >= mpapNombre)
{
Serial.println("\tHoming moteur # invalide: " + String(homeMotNum));
}
else
{
Serial.println("\tHoming moteur : " + String(homeMotNum));
mpapHomingAndOffset(homeMotNum); // Selon ordre des moteurs
eeprParam.intfEmotPos[0][homeMotNum] = mpapLearning(0, homeMotNum); // Lecture de la position du moteur m
}
}
prgEtatChange(prgEtatEnAttente);
}
else if (cmdRx.startsWith(F("LEARNM"))) // Apprentissage d'une émotion, moteurs
{
Serial.println(F("Learning positions"));
prgEtatChange(prgEtatEnTravail);
cmdRx.replace(F("LEARNM"), "");
int emotNum = cmdRx.toInt(); // Numéro de l'émotion
if (emotNum >= emotNombre)
{
Serial.println("\tNumero invalide " + String(emotNum));
signLedWarning(6, 150); // LED Warning
}
else
{
emotLearn(emotNum);
}
prgEtatChange(prgEtatEnAttente);
}
else if (cmdRx.startsWith(F("LEARNS"))) // Apprentissage d'une émotion, servo ee ii aa
{
Serial.print(F("Learning positions Servo")); // learns0104123
prgEtatChange(prgEtatEnTravail);
cmdRx.replace(F("LEARNS"), "");
int emotNum = cmdRx.substring(0, 2).toInt(); // Numéro de l'émotion
int intfNum = cmdRx.substring(2, 4).toInt(); // Numéro de l'interface
int servoAngle = cmdRx.substring(4).toInt(); // Angle du servo
intfParam = intfParamGet(intfNum);
if (intfParam.type == intfTypeServo) // Si c'est un servo
{
servoGotoAngle(intfParam.index, servoAngle);
eeprParam.intfEmotPos[emotNum][intfNum] = servoAngle; // Sauvegarde de l'angle
}
else
{
Serial.println("\nL'interface " + String(intfNum) + " n'est pas un SERVO !!!!\n");
}
prgEtatChange(prgEtatEnAttente);
}
else if (cmdRx.startsWith(F("LIST"))) // Lister les positions des émotions
{
emotList();
}
else if (cmdRx.startsWith(F("MOTDIS"))) // Désactiver/Activer les moteurs
{
prgEtatChange(prgEtatEnTravail);
Serial.print(F("Moteurs disable "));
cmdRx.replace(F("MOTDIS"), "");
int disableMode = cmdRx.toInt(); // Mode Disable
if (disableMode == 1) // Disable motors
{
Serial.println(F(" OFF"));
mpapDriverEnable(mpapEnaSet, !mpapEnaPartiel);
prgEtatChange(prgEtatManual); // En mode manuel
}
else
{
Serial.println(F(" ON"));
prgEtatChange(prgEtatEnAttente);
}
}
else if (cmdRx.startsWith(F("%"))) // Macro
{
cmdRx = cmdRx.substring(1); // Pour supprimer le %
if (cmdRx.startsWith(F("LIST"))) // Lister les macro
{
Serial.println(F("Macro liste pour backup"));
for (int m = 0; m < macArraySize; m ++)
{
Serial.print("%REC" + String(m) + ",");
Serial.println(eeprParam.macArray[m]);
}
}
else if (cmdRx.startsWith(F("REC"))) // Enregistrer une macro
{
Serial.println(F("Macro Enregistrement "));
macArrayRecord(cmdRx.substring(3)); // Supprimer REC
prgEtatChange(prgEtatEnAttente);
}
else if (cmdRx.startsWith(F("PLAY"))) // Jouer une macro sauvée dans tableau
{
int macroIndex = cmdRx.substring(4).toInt(); // Supprimer PLAY
macroIndex = constrain(macroIndex, 0, macArraySize -1); // Limiterl'index
Serial.println("Macro jouer # " + String(macroIndex));
commandeExecute("%" + (String)eeprParam.macArray[macroIndex]);
//macArrayRecord(cmdRx.substring(3)); // Supprimer REC
prgEtatChange(prgEtatEnAttente);
}
else
{
Serial.println("Macro joue " + cmdRx);
macCmdRx += cmdRx + macCmdSeparator; // Ajout aux macro en cours
Serial.println("\t" + macCmdRx);
macIsRunning = true;
exterFeedback("MACSTART");
}
}
else if (cmdRx.startsWith(F("DEL"))) // Temporisation macro
{
cmdRx.replace(F("DEL"), "");
macTimerTempo = cmdRx.toInt(); // Temps de la temporisation
Serial.print(F("Temporisation "));
Serial.println(macTimerTempo);
macTimerMillis = millis(); // Démarrage du chrono
}
//else if (cmdRx.startsWith(F("MOTCW"))) // Test moteur sens des aiguilles d'une montre
//{
//Serial.print(F("Moteurs CW "));
//prgEtatChange(prgEtatEnTravail);
//
//cmdRx.replace(F("MOTCW"), "");
//mpapTestCwCcw(mpapDirCw, cmdRx);
//
//prgEtatChange(prgEtatEnAttente);
//}
//else if (cmdRx.startsWith(F("MOTCCW"))) // Test moteur sens contraire des aiguilles d'une montre
//{
//Serial.print(F("Moteurs CCW "));
//prgEtatChange(prgEtatEnTravail);
//
//cmdRx.replace(F("MOTCCW"), "");
//mpapTestCwCcw(mpapDirCcw, cmdRx);
//
//prgEtatChange(prgEtatEnAttente);
//}
else if (cmdRx.startsWith(F("SERVO"))) // Test des servo
{
Serial.print(F("Servo "));
prgEtatChange(prgEtatEnTravail);
cmdRx.replace(F("SERVO"), "");
servoTest(cmdRx);
prgEtatChange(prgEtatEnAttente);
}
else if (cmdRx.startsWith(F("TRACE"))) // Provisoire pour feedback
{
}
else if (cmdRx.startsWith(F("FACTORY"))) // Paramètres par défaut
{
Serial.println("Factory setting");
eeprParam.prgEtat = prgEtatWarning;
eeprParam.emotNum = 0;
//EEPROM.put(eeprOffeeprParam, eeprParam); // Sauvegarde des paramètres
prgSettingDefault();
EEPROM.put(eeprOffsetCheckWord, eeprCheckWord -1); // Effacement du mot de test
Serial.println(F("!!!! LE PROGRAMME DOIT REDEMARRER"));
while(true)
{
signLedDisplay(signLedFctWarning, signColRed, 0); // Allumer la LED warning
signLedDisplay(signLedFctInfo, signColOff, 0); // Allumer la LED info
delay(250);
signLedDisplay(signLedFctWarning, signColOff, 0); // Allumer la LED warning
signLedDisplay(signLedFctInfo, signColRed, 0); // Allumer la LED info
delay(250);
}
}
else if (cmdRx == F("TEST")) //
{
Serial.println(F("Test fonction"));
}
else if (cmdRx == F("RESTAURE")) //
{
Serial.println(F("Restaurer les paramètres"));
commandeExecute(F("EMREC1,42,46,45,19,46,"));
commandeExecute(F("EMREC2,66,62,90,35,66,"));
commandeExecute(F("EMREC3,94,98,110,67,94,"));
commandeExecute(F("EMREC4,138,146,150,19,146,"));
commandeExecute(F("EMREC5,170,178,180,47,170,"));
macArrayInit();
}
else
{
Serial.println("\t\t !!! Commande inconnue : " + cmdRx);
signLedWarning(6, 150); // LED Warning
}
}
//------------------------------------- Communications externes (extser)
void exterFeedback(String feedbText)
{
//Serial.println("> > > > > > > > " + feedbText);
//externSerial.println("TRACE=" + feedbText);
}
//------------------------------------- LED de signalisation
void signLedDisplay(int ledIndex, int colorIndex, int timeDispl)
{
signLed.setPixelColor(ledIndex, signLedColors[colorIndex]);
signLed.show();
if (timeDispl > 0) // Si timeDispol > 0 millisec.
{
delay(timeDispl);
signLed.setPixelColor(ledIndex, signLedColors[signColOff]);
signLed.show();
}
}
//------------------------------------- Commande de la LED warning
void signLedWarning(int ledLoop, unsigned long ledTime) // Commande de la LED de warning
{
for (int l = 0; l < (ledLoop *2); l ++)
{
if (l % 2 == 0) // Une fois sur deux
{
signLedDisplay(signLedFctWarning, signColRed, ledTime);
}
else
{
signLedDisplay(signLedFctWarning, signColOff, ledTime);
}
}
signLed.setPixelColor(signLedFctWarning, signLedColors[signColGreen]);
signLed.show();
}
void signledTest(String ledCmd) // Test des LED LED01R pour LED 1 en rouge
{
Serial.println(ledCmd);
int ledNum = ledCmd.substring(0, 2).toInt();
String ledCouleur = ledCmd.substring(2);
Serial.println(ledCouleur + "*");
if (ledCouleur == "R")
{
signLedDisplay(ledNum, signColRed, 3000);
}
else if (ledCouleur == "V")
{
signLedDisplay(ledNum, signColGreen, 3000);
}
else if (ledCouleur == "B")
{
signLedDisplay(ledNum, signColBlue, 3000);
}
else
{
signLedDisplay(ledNum, signColOff, 3000);
}
}
void signLedInitialisation()
{
signLedColors[signColRed] = signLed.Color(255, 0, 0); // Définition des couleurs
signLedColors[signColGreen] = signLed.Color(0, 255, 0);
signLedColors[signColBlue] = signLed.Color(0, 0, 255);
signLedColors[signColYellow] = signLed.Color(255, 255, 0);
signLedColors[signColOrange] = signLed.Color(255, 165, 0);
signLedColors[signColWithe] = signLed.Color(255, 255, 255);
signLedColors[signColOff] = signLed.Color(0, 0, 0);
signLed.begin();
signLed.setBrightness(signLebBrightMax);
}
//------------------------------------- Syst me de trace pour la mise au point
void traceModeStart()
{
Serial.println(F("\n> > > > >MODE TRACE !!!"));
delay(3000);
const unsigned long traceLedTempo = 250; // Tempo du clignotement
unsigned long traceLedMillis = millis(); // Tempo du clignotement, chrono
boolean traceLedToggle = true; // Pour l'alternance
String btRx = "-"; // Réception de BT
const unsigned long traceDisplayTempo = 2000; // Tempo d'affichage
unsigned long traceDisplayMillis = millis(); // Tempo d'affichage, chrono
while (true) // Boucle infinie pour en sortie faire un reset de l'Arduino
{
if (digitalRead(traceModeOnPin) == traceModeOnPinEtatOn)
{
if (millis() - traceLedMillis >= traceLedTempo) // Affichage des LED
{
if (traceLedToggle)
{
signLedDisplay(signLedFctWarning, signColBlue, 0); // Allumer la LED warning
signLedDisplay(signLedFctInfo, signColOff, 0); // Allumer la LED info
}
else
{
signLedDisplay(signLedFctWarning, signColOff, 0); // Allumer la LED warning
signLedDisplay(signLedFctInfo, signColBlue, 0); // Allumer la LED info
}
traceLedToggle = !traceLedToggle;
traceLedMillis = millis();
}
if (traceAuto && (millis() - traceDisplayMillis >= traceDisplayTempo)) // Affichage des informations
{
traceAll();
traceDisplayMillis = millis();
}
//--------------------------------- Commandes moniteur
if (Serial.available())
{
traceCmdExecute(Serial.readStringUntil('\n'));
}
//------------------------- Réception Bluatooth
if (btSerial.available())
{
traceCmdExecute(btSerial.readStringUntil('\n'));
}
for (int m = 0; m < mpapNombre; m ++)
{
mpap[m].run();
}
}
}
}
void traceAll()
{
traceFdcStatus();
traceBoutonPoussoir();
traceDriversEnable();
//Serial.print(F("Derniere reception Bluetooth;"));
//Serial.println("\t" + btRx);
}
/*
MOTCWnnpppp Fait tourner le moteur nn de pppp pas sens des aiguilles d'une montre
MOTCCWnnpppp Fait tourner le moteur nn de pppp pas sens inverse des aiguilles d'une montre
*/
void traceCmdExecute(String cmdRx)
{
cmdRx.trim(); // Nettoyer la chaîne
cmdRx.toUpperCase(); // Commande recue en majuscules
if (cmdRx.startsWith(F("MOTCW"))) // Test moteur sens des aiguilles d'une montre
{
Serial.print(F("Moteurs CW "));
//prgEtatChange(prgEtatEnTravail);
cmdRx.replace(F("MOTCW"), "");
mpapTestCwCcw(mpapDirCw, cmdRx);
//prgEtatChange(prgEtatEnAttente);
}
else if (cmdRx.startsWith(F("MOTCCW"))) // Test moteur sens contraire des aiguilles d'une montre
{
Serial.print(F("Moteurs CCW "));
//prgEtatChange(prgEtatEnTravail);
cmdRx.replace(F("MOTCCW"), "");
mpapTestCwCcw(mpapDirCcw, cmdRx);
//prgEtatChange(prgEtatEnAttente);
}
else if (cmdRx.startsWith(F("SERVO"))) // Test des servo
{
Serial.println("Trace commande servo : " + cmdRx);
cmdRx.replace(F("SERVO"), "");
servoTest(cmdRx);
}
else if (cmdRx.startsWith(F("LED"))) // Test des LED
{
Serial.println("Essai LED : " + cmdRx);
cmdRx.replace(F("LED"), "");
signledTest(cmdRx);
}
else if (cmdRx.startsWith(F("HOMING"))) // Homing des moteurs
{
commandeExecute(cmdRx);
}
else if (cmdRx.startsWith(F("FACTORY"))) // Test des servo
{
Serial.println("FACTORY !!! ");
commandeExecute(F("FACTORY"));
}
else if (cmdRx == (F("TRACE"))) // Trace
{
traceAll();
}
else if (cmdRx == (F("AUTO"))) // Si trace auto toggle
{
traceAuto = !traceAuto; // Toggle
Serial.print(F("\nTrace auto "));
Serial.println((traceAuto == true) ? "ON" : "OFF");
}
else
{
}
}
void traceFdcStatus() // Affichage de l'état des fin de course
{
Serial.println(F("\nEtat des contacts de homing"));
for (int m = 0; m < mpapNombre; m ++) //***
{
Serial.print(String(m) + "=");
Serial.print((digitalRead(mpapParam[m].homingPin) == mpapHomingEtatOn) ? "ON" : "OFF");
Serial.print(", ");
if (m % 3 == 2)
{
Serial.println("");
}
}
Serial.println("");
}
void traceBoutonPoussoir()
{
Serial.print(F("\nEtat du bouton poussoir : "));
pushButt.read();
if (pushButt.isPressed()) // Si BP est pressé = homing
{
Serial.println("PRESSE");
}
else
{
Serial.println("NON presse");
}
}
void traceDriversEnable()
{
Serial.println(F("\nEtat d'ENABLE des drivers : "));
for (int e = 0; e < driverEnablePinNombre; e ++)
{
Serial.print("Driver sur pin " + String(driverEnablePin[e]));
Serial.println((digitalRead(driverEnablePin[e]) == driverENApinEtatOn) ? " ENABLE" : " Disable");
}
}
String systemGetVersion()
{
return String(mpapNombre) + "M" + String(servoNombre) + "S" + String(mpapGroupeNombre) + "GR-HIPS"; // Homing Individuel et Partiel., Servo alim commandée
}
void settingJpbbricole()
{
commandeExecute("EMREC5,170,178,180,47,170,");
commandeExecute("EMREC1,42,46,45,19,46,");
commandeExecute("EMREC2,66,62,90,35,66,");
commandeExecute("EMREC3,94,98,110,67,94,");
commandeExecute("EMREC4,138,146,150,19,146,");
commandeExecute("EMREC5,170,178,180,47,170,");
commandeExecute("%REC1,EM4|em5|EM2|EM1|EM3|EM1|");
commandeExecute("%REC2|EM4|DEL2000|EM2|EM3|DEL1000|EM1|");
}
/*
// bernie31
EMREC0,10,10,10,10,10,10,10,10,10,10,10,0,
EMREC1,170,330,0,89,233,361,0,258,970,1355,554,0,
EMREC2,106,330,0,0,137,361,0,326,1418,1706,778,0,
EMREC3,0,0,0,0,0,0,0,0,0,0,0,0,
EMREC4,0,0,0,0,0,0,0,0,0,0,0,0,
EMREC5,0,0,0,0,0,0,0,0,0,0,0,0,
// jpbbricole
EMREC0,10,10,10,10,10,
EMREC1,42,46,45,19,46,
EMREC2,66,62,90,35,66,
EMREC3,94,98,110,67,94,
EMREC4,138,146,150,19,146,
EMREC5,170,178,180,47,170,
Macro: %EM2|DEL2000|EM1|EM3|DEL1000|EM1|
%EM2|EM1|EM3|EM1|EM4|em5|
%REC8,EM4|em5|EM2|EM1|EM3|EM1|
*/
Une toute belle journée à vous deux!
jpbbricole