//Un Grand MERCI au forum : https://forum.arduino.cc/c/international/francais
//Pointeur vers RangMachine, voir: https://forum.arduino.cc/t/verifier-si-une-instance-de-bibliotheque-est-declaree/1117499/27
//Fonction avec argument(s) optioneel voir: https://forum.arduino.cc/t/fonction-avec-argument-optionnel-qui-compile-pas/1117046
//Connection du codeur voir: https://forum.arduino.cc/t/codeur-npn-5v-24v-sur-esps32-3-3v/1118626
#define version V0_4_02
//Multi-tâches, voir: http://tvaira.free.fr/esp32/esp32-freertos.html
// Description:
//
//Archithecture:
//Micro-contrôleur: ESP32_38pins
//Codeur: 600points/tour >> informe de la distance parcourue par la roue de la machine
//Pas-à-pas Nena../200step/tour >> entraine la roue doseuse du semoire
//Driver A4988 >> pilotage du moteur pas-à-pas. (avec ESP32, voir: https://www.youtube.com/watch?v=6rjTFtLgqZU)
//Boost-voltage 12-24V (optionnel) >> sert à transformer le ~12v du véhicule en 24v pour le moteur, plus grand régime avec 24v qu'avec les ~13,5v du véhicule)
//Pour chaque rang de la planteuse
//Un capteur de passage de plant >> sert à détecter si un plant à réellement été planté. (pour les pattates, j'utilise un switch sur la chaîne d'allimentation)
//Led témions-manque LED5mm_Rouge >> indicateur lumineux servent à avertire de chaque plant non détecté par le capteur de passage ou la mise en alarme du rang
//>>Pas encors paramètré<< //Led rang-actif LED3mm_verte >> indique si le rang de la planteuse est activé
//Les autres switchs (interrupteurs)
//[swSemeOn] >> active le semoire
//[swPlanteOn] >> active les rang de la planteuse
//[swMoteurOn] >> activation mannuel du moteur du semoire (pour purger le mécanisme, par exemple)
//[swAlReset] >> effacer les alarmes et réinitaliser les paramètres d'alarme après résolution du problème (les anciennes valeurs seront conservées pour les statistiques finals mais plus utilisées pour les alarmes)
// swBuzzerOff >> pour éteindre l'alarme sonor. (Brancher directement sur le câble d'allimentation du buzzer ou sur son relais)
//Les autres témoins
//Lampe Alarme central >> Relais activant un témions lumineux d'alarme centralisée
//Buzzer Alarme central >> Relais activant un témoins sonor d'alarme centralisée
//LedSemOn LED5mm_Vert >> allumée lorce-que le semoire est actif
//LedPlanteON LED5mm_vert >> allumée si tous les rang de la planteuse sont actif, clignotte si les rang sont partiellement actif.
//Modifications:
//V0_3_0 et V0_3_01
//-mise à jour de la position current du stepper à 2'146'000'111
//-lors de la mise à jour avec [setCurrentPosition()] ou [addCurrentPosition()], [getCurrentPosition()] prend un certin temps à ce stabiliser.
// ce temps de stabilisation fait perdre quelques pas au moteur. donc ma solution est de le faire le moins souvent possible
// je le fait que quand le compteur dépasse 2 milliard de stepp (ou nStepperTour dépasse 60'000).
//-correction de l'addition des stepps pour le calcul de la vitesse
//-correction du calcul de vitesse (ajout de la ligne :TempVtI ++;)pour tenir compte du dernier enregistrement
// [#define DEBUGcalculSpeed] pour vérifier le calcul de la vitesse
//-déplacement des Pins du codeur (à 0 et 2 celà empèche le téléverssement; déplacer au 26 et 27)
//-ajout variable nStepperTour: éviter que le moteur s'embale à cause d'une décélération trop lente
//-avec l'ancienne version, le moteur s'embalait lors d'arrêt brusque, il décélairait pas asseé vite et recommancait une nouvelle boucle ect...ect...
//-avec l'ajout de [nStepperTour] le retard/avance du moteur est calculé sur beaucoup-plus de tours.
//-amélioration du calcul de retard (lissage) à l'aide du traceur série ([#define DEBUGstepperValTraceur])
//V0_3_02
// mise à jours des variables de vitesse
// ajout des fonctios de vitesse
// ajout des fonctions de distance
// changement du calcul de vitesse du stepper (sans pris en charge de la vitesse d'avancement, "plus réactif")
// ALARME SUR-VITESSE : ajout d'une alarme de vitesse limite du stepper (rpm trop rapide)
// ajout lampe alarme centrale sur Pin 25
// remplacer [vtSteppSec] Par [vtSteppMin]
// ajout switch on-off plante et on-off seme >>[swPlanteOn] et [swSemeOn]
// Mise en place de la bibliothèque [rangMachine]
//V0_3_03
// transformer les rangMachine en tableau de pointeurs autoévolutif celon le nombre de rangs
//paramètrer le logitiel à la bibliothèque [rangMachine]
// corriger la fonction [majAlarme()]
// intégrer le buzzer à l'alarme central [majAlarme()]
// paramètrer switch on-off plante et on-off seme >>[swPlanteOn] et [swSemeOn]
// ajouter un switch purger [swMoteurOn] pour purger manuellement le semoir avant l'étalonage. (aussi utile pour un contrôle visuel de fonctionnement du semoir)
//V0_4_01
// refaire le Debouns switch dans [rangMachine::addPoints()] est réécriture des déclancheurs, ajout moyenne majEspacePlants
//V0_4_02
//Ajouter les fonction de moyennage dans le calcul de la vitesse du stepper
//Baculer le stepper sur le coeur1 [init(1);]
//Ajouter des delay(1) dans la loop() et moteurOnManuel, pour pouvoir utiliser le programme principal sur le coeur0 (watchdog)
// A tester: Envoyer les changements de vitesse au stepper au minimum toutes les 2millis()
//Modifier DEBUGstepperValTraceur pour l'utiliser avec SerialPlot
//>>> A FAIRE:
// terminer la bibliothèque [rangMachine]
// nettoyer la bibliothèque [rangMachine]
// faire les fonctions de statistiques de la planteuse (partielement fais)
// faire les fonctions de statistiques du semoire
// ajout distance semée (différant de distance plantée)>> [cptPntDistSeme] / [cptPntDistPlante] /global [cptPntDist]
// contrôler les calcules de vitesses, la vitesse du PàP me semble incoérante
// Ajouter un capteur de hall sur le rouleau pour contrôler le blocage du semoir et faire les fonctions en découlant
// CAN-BUS voir: https://www.locoduino.org/spip.php?article268
//FIN modif
#include <Arduino.h>
#include <FastAccelStepper.h>
FastAccelStepperEngine engine = FastAccelStepperEngine();
FastAccelStepper *stepper;
#include "rangMachine.h"
const uint8_t nbrlignePlanteuse = 0; // nombre de lignes de la planteuse >> actuellement maximum 4 lignes
//LES PINS
//codeur
const uint8_t codeurAPin = 14;//27;
const uint8_t codeurBPin = 27;//14;
//stepper
#define stepPinStepper 16
#define enablePinStepper 17
#define dirPinStepper 4
//rang planteuse (switch et led manque un plant)
const uint8_t rangPinSwitch[4]{23, 21, 18, 2};
const uint8_t rangPinLedManque[4]{22, 19, 5, 15};
//Old variante: rangMachine rang1(23,22);
//rangMachine rang2(21,19);
//rangMachine rang3(18,5);
//rangMachine rang4(2,15);
//switchs
const uint8_t swSemeOn = 36;//35;
const uint8_t swPlanteOn = 39;//32;
const uint8_t swAlReset = 35;//25;
const uint8_t swMoteurOn = 34;//33;
// swBuzzerOff >> Brancher directement sur le câble d'allimentation du buzzer ou sur son relais
//témoins
//const uint8_t ledStepper = 18; >> branchée sur enablePinStepper et VC
const uint8_t ledAlCentral = 32;
const uint8_t buzzAlCentral = 33;
const uint8_t ledSemeOn = 26;
const uint8_t ledPlanteOn = 25;
//FIN des pins
#define DEBUG
#ifdef DEBUG
//#define DEBUGloopStepp_stepp
//#define DEBUGloopSpeed //V0.3.4 Environ de 60'400 loop/s; V0.4.0(2rangs) ~59'000 loop/s
//#define DEBUGAlarme
//#define DEBUGswitch
//#define DEBUGcodeur
//#define DEBUGcodeurSpeed
//#define DEBUGcalculSpeed
//#define DEBUGstepper
//#define DEBUGenableOutputs
//#define DEBUGstepperValeurs
#define DEBUGstepperValTraceur //comme [DEBUGstepperValeurs] mais sur le traceur série
//#define DEBUGstepperSpeed
//#define DEBUGmanques
#endif
#ifdef DEBUGloopSpeed
uint16_t DebugCptLoop = 1;
uint16_t DebugCptLoopMultiple = 1;
uint32_t DebugTimmerLoop = millis();
#endif
#ifdef DEBUGAlarme
byte DebugAlarme1 = 99;
uint8_t DebugAlOld_cptManqueRapide = 0;
uint32_t DebugAlOld_cptManque = 0;
uint64_t DebugAlOld_cptPlant = 0;
#endif
//FIN debug
//#define InfoSerialMoniteur //Afficher les information importante du déroulement du programmme sur le moniteur série
//Eeprom
#include <EEPROM.h>
#define EEPROM_SIZE 1 // define the number of bytes you want to access
struct saveEeprom{
uint16_t SaveSteppTour;
uint16_t SavePntSteppTour;
uint32_t SavePnt100m;
int8_t SaveValeurPnt;
uint16_t SaveTimelapseVt;
uint8_t SaveNbrlignePlanteuse;
int16_t SaveMiniSteppSpeed = 5;
int16_t SaveMaxiSteppSpeed = 1667;
};
//LES VARIABLES :
//Variables Etalonnage
const uint16_t steppTour = 2000; //nombre de pas pour un tour machine (peut-hêtre varier pour modifier la precision de l'étalonnage. Ici = 10 tours du moteur pas-à-pas.)
const uint16_t pntSteppTour = 3000; //nombre de points de codeur pour un tour machine (1[steppTour]).
const uint32_t pnt100m = 100000; //nombre de points du codeur pour une distance de 100 mètres.
const int8_t valeurPnt = -1; //valeur d'un point; 1 = horaire; -1 = anti-horaire
const uint16_t timelapseVt = 16; //temps entre deux mesure de vitesse (ne pas déssendre en dessous de 10 pour une vitesse stable)
//Varible Planteuse
rangMachine* lignePlanteuse[nbrlignePlanteuse];
const uint16_t distancePlant = 570; // distance en points entre chaque plants
//const uint16_t debouncePlante = distancePlant/3; // distance de passage d'un plant sous le switch (1pnt ~ 1mm d'avancement de la planteuse)
byte valRangAlarme[nbrlignePlanteuse];
byte oldValRangAlarme[nbrlignePlanteuse];
//Variables points et stepps
int16_t codeurPnt = 0 ; //nombre de points enregistrés par le codeur pas encors traités dans la boucle
int16_t newPnt = 0; //nombre de points traités par la boucle en cour d'exécution.
int16_t newPntStepper = 0; // nombre de points pour le semoir
int32_t lastPntPos = 0; //position du codeur (tour machine) lors de la boucle précédante.
int32_t lastSteppPos = 0; //position du stepper (tour machine) lors de la boucle précédante.
uint16_t nStepperTour = 0; //nombre de fois [steppTour] à enlever à [stepper->getCurrentPosition] pour avoir ça position "angulaire"
int16_t newStepp = 0; //nombre de pas à ajouter pour la boucle en cour d'exécution.
uint16_t cptPntVt = 0; //nombre absolut de points à ajouter pour le calcul de la vitesse { += abs(newPnt)}.
int32_t cptPntDist = 0; //nombre de points du compteur de distance parcourue. Compteur vidé tous les kilo-mètres dans [cptPntKm].
int16_t cptPntKm = 0; //nombre de kilomètres parcourus par la machine.
int32_t cptPntDistSeme = 0; //nombre de points du compteur de distance parcourue. Compteur vidé tous les kilo-mètres dans [cptPntKmSeme].
int16_t cptPntKmSeme = 0; //nombre de kilomètres parcourus par la machine.
int32_t cptPntDistPlante = 0; //nombre de points du compteur de distance parcourue. Compteur vidé tous les kilo-mètres dans [cptPntKmPlante].
int16_t cptPntKmPlante = 0; //nombre de kilomètres parcourus par la machine.
//Variables temps et vitesses
uint32_t lastTime = millis(); //milliseconde de référence lors de la boucle précédante.
uint32_t newTime = lastTime; //milliseconde de référence lors de la boucle en cour d'exécution.
uint32_t newTimelapseVt = millis() + timelapseVt; //délais pour la prochaine mesure de vitesse += [timelapseVt]
uint16_t tblPntVt[21]; // tableau pour le stockage du nombre de points vitesse mesurés. (Utilisé pour lissage de la vitesse mesurée).
int8_t iTblPntVt = -20; //position de la case du tableau en cour d'écriture.
bool jTblPntVt = true; //première ou deusième mesure de vitesse pour moyenner la case en cour d'écriture. (chaque case du tableau contient les somme des deuxdirnière mesures, sauf au démarrage, il y a une mesure fois deux dans chaque case pour gagner en vitesse de mise à jour)
uint32_t vtPntMin; //vitesse d'avancement en points/minutte.
int32_t vtSteppMin; //vitesse moteur en stepp/minutte
float vtMsec; //vitesse d'avancement en mètres/seconde
//Avertissement et communications: ->lampes témoins; signal sonore; communication avec le boitier de commande; communication avec le GPS; ...
//Variables alarmes
uint32_t lastTimeAlBlink = millis(); //dernière fois que la lampe alarme centrale à été allumée
uint32_t lastTimeAlBuzz = millis();
int8_t etatAlLampe = LOW; // état de la lampe alarme centrale >> 0 = éteinte; 1 = allumée
int8_t etatAlBuzz = LOW;
byte alarme1 = 0; //bit0 = alarmeOn;
byte oldAlarme1 = 0;//bit1 = alarme ligne 1;
//bit2 = alarme ligne 2;
//bit3 = alarme ligne 3;
//bit4 = alarme ligne 4;
//bit5 = PàP trop vite;
//bit6 = PàP bloqué;
//bit7 = buzzerOn;
//bit à bit Voir: https://www.locoduino.org/spip.php?article70
////bitWrite(x, n, b) permet d’écrire un bit. Le premier argument, x est la donnée où on écrit le bit, le second argument, n est le numéro du bit et le 3e, b est la valeur à écrire, 0 ou 1.
//bitRead(x, n) permet de lire un bit. Le premier argument, x est la donnée d’où on lit le bit, le second argument, n est le numéro du bit.
//bitSet(x, n) permet de mettre à 1 un bit. Le premier argument, x est la donnée où on écrit le bit, le second argument, n est le numéro du bit
//bitClear(x, n) permet de mettre à 0 un bit. Le premier argument, x est la donnée où on écrit le bit, le second argument, n est le numéro du bit
//Autres variables
//Switch pilotage
bool swSeme = false;// = digitalRead(swSemeOn);
bool swPlante = false;// = digitalRead(swPlanteOn);
uint32_t swSemPlanDebounce = 0;
//bool alReset = false;
//bool saveSD = false;
//Compteurs de manques: -> contrôle si un planton déclanche le switch tous les x centimètres sur chaque ligne de la planteuse
//>>> Remplacer par la bibliothèque [rangMachine]
//Variables Stepper
int16_t miniSteppSpeed = 5;
int16_t maxiSteppSpeed = 1667; //1667 = 500RPM; 1500 = 450RPM; 1333 = 400RPM; ...
int32_t newSpeedStepp = 0;
int32_t retardStepp = 0;
int32_t lastRetardStepp = 0;
int32_t majSpeedStepp = 0;
bool stepperOn = false;
// //Ancienne version: int8_t iMajStepperCurrentPos = 0; //compteur pour éviter la re-mise-à-jour du compteur de position du PàP avant son activation complette
//FIN des variables
void manuelMoteurOn(uint16_t ManuelOnSpeed = 500); //Voir: https://forum.arduino.cc/t/fonction-avec-argument-optionnel-qui-compile-pas/1117046/5
void setup() {
//#if (defined DEBUG || defined InfoSerialMoniteur)
Serial.begin(115200);
delay (5);
#ifdef DEBUG
#ifdef DEBUGstepperValTraceur
Serial.print("vitesse:");
Serial.print(" \tretard:");
Serial.println(" \tmoyenne retard:");
#else
Serial.println("\t\t S T A R T (setup)");
#endif
#endif
//#endif//DEBUG
//Pins Mode
pinMode(codeurAPin, INPUT_PULLUP);
pinMode(codeurBPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(codeurAPin), comptePnt, RISING); //RISING ; CHANGE);
pinMode(swSemeOn, INPUT); // pull-up externe >>INPUT_PULLUP);
pinMode(swPlanteOn, INPUT); // pull-up externe >>INPUT_PULLUP);
pinMode(swAlReset, INPUT); // pull-up externe >>INPUT_PULLUP);
pinMode(swMoteurOn, INPUT); // pull-up externe >>INPUT_PULLUP);
pinMode(ledAlCentral, OUTPUT);
pinMode(buzzAlCentral, OUTPUT);
pinMode(ledSemeOn, OUTPUT);
pinMode(ledPlanteOn, OUTPUT);
digitalWrite(ledAlCentral, etatAlLampe);
//Initialiser les rang
memset(lignePlanteuse, 0, sizeof lignePlanteuse); //=> Initialise les pointeurs créés ci-dessus à NULL
memset(valRangAlarme, 0, sizeof valRangAlarme);
memset(oldValRangAlarme, 0, sizeof oldValRangAlarme);
for (uint8_t i = 0; i < nbrlignePlanteuse; i++) {
lignePlanteuse[i] = new rangMachine (rangPinSwitch[i], rangPinLedManque[i]);
}
//Initialiser le Pas_à_pas
//engine.init(); //utiliser le Coeur par défaud pour gérer le stepper. (ESP32 par défaud c'est le coeur0)
engine.init(1); //utiliser le Coeur 1 pour gérer le stepper
stepper = engine.stepperConnectToPin(stepPinStepper); // ### ESP32 * allows up to 200000 generated steps per second
if (stepper) {
stepper->setDirectionPin(dirPinStepper);
stepper->setEnablePin(enablePinStepper);
stepper->setSpeedInHz(10);
stepper->setAcceleration(6000); //steps/s²
stepper->setCurrentPosition(0);
stepper->setAutoEnable(true); //void setAutoEnable(bool auto_enable);
stepper->setDelayToEnable(60); //int8_t setDelayToEnable(uint32_t delay_us);
stepper->setDelayToDisable(1500); //void setDelayToDisable(uint16_t delay_ms);
// if (stepper->getCurrentPosition() >= steppTour) {
// nStepperTour = int(stepper->getCurrentPosition() / steppTour);
// }
}
#ifdef InfoSerialMoniteur
Serial.println ("Informations sur le moniteur série activées");
#endif
#ifdef DEBUG
#ifndef DEBUGstepperValTraceur
Serial.println ("Mode DEBUG activé");
#endif
#endif
#if (defined DEBUG || defined InfoSerialMoniteur)
#ifndef DEBUGstepperValTraceur
Serial.println("*********************************************************END SETUP***");
#endif
#endif
delay(5);
}
void loop() {
delay(1); //Mise à jour du chein de garde Core0 //>> voir: https://forum.arduino.cc/t/while-task-watchdog-got-triggered-avec-esp32-coeur0/1121766/18
//Initialise les varibles traitées pou cette boucle
#ifdef DEBUGloopStepp_stepp
Serial.print("DEBUGloopStepp_stepp: A01, ");
#endif//DEBUG
newPnt = codeurPnt;
newTime = millis();
//Contrôle les switchs
#ifdef DEBUGloopStepp_stepp
Serial.print("02, "); //A_02
#endif//DEBUG
if(swSemPlanDebounce < millis()){
bool _TempSwRead = false;
if(digitalRead(swSemeOn) == LOW) {_TempSwRead = true;}
if(swSeme != _TempSwRead){
swSeme = _TempSwRead;
// if(!swSeme != digitalRead(swSemeOn)){ //Manupulation pas tès catholique pour comparer un bool et un int
// swSeme = digitalRead(swSemeOn); swSeme = !swSeme;
swSemPlanDebounce = millis()+20;
#ifdef DEBUGswitch
if(swSeme) Serial.println("Seme ON"); else Serial.println("Seme OFF");
#endif
}
if(digitalRead(swPlanteOn) == LOW) {_TempSwRead = true;} else {_TempSwRead = false;}
if(swPlante != _TempSwRead){
swPlante = _TempSwRead;
swSemPlanDebounce = millis()+20;
#ifdef DEBUGswitch
if(swPlante) Serial.println("Plante ON"); else Serial.println("Plante OFF");
#endif
}
}
#ifdef DEBUGloopStepp_stepp
Serial.print("03, ");
#endif//DEBUG
if (!digitalRead(swAlReset)) alarmeReset();
#ifdef DEBUGloopStepp_stepp
Serial.print("04, ");
#endif//DEBUG
if (!digitalRead(swMoteurOn)) manuelMoteurOn();
//Calcul de la distance et vitesse d'avancement
#ifdef DEBUGloopStepp_stepp
Serial.print("| C01, ");
#endif//DEBUG
if (newPnt != 0) {
addDistance();
}
else newPntStepper = 0;
cptPntVt += abs(newPnt);
if (newTimelapseVt <= newTime) {
addVt();
newTimelapseVt += timelapseVt;
// #ifdef DEBUGstepperValTraceur
// Serial.print(""); Serial.print(retardStepp);
// Serial.print(" , "); Serial.print(majSpeedStepp);
// Serial.print(" , "); Serial.print(newSpeedStepp);
// Serial.print(" , "); Serial.println(vtSteppMin/60);
// #endif
}
//Convetie les points en stepp >> newStepp = nombre de points à ajouter au moteur
#ifdef DEBUGloopStepp_stepp
Serial.print("| B01, ");
#endif//DEBUG
newStepp = ((lastPntPos + newPntStepper) * steppTour / pntSteppTour) - lastSteppPos;
if(newStepp < 1) { //éviter au moteur de tourner en arrière
newStepp = 0;
}
//Evoye les points aux rangs et contrôle les alarmes manques
#ifdef DEBUGloopStepp_stepp
Serial.print("| D01, ");
#endif//DEBUG
for(int i = 0; i < nbrlignePlanteuse; i ++){
valRangAlarme[i] = lignePlanteuse[i]->addPoints(newPnt, true); //.addPoints(nombre_points_a_ajouter, rang_activé) retourne: byte rang_Alarmes (voir bibliothèque pour détails)
if(valRangAlarme[i] > 1) {bitSet(alarme1, i+1);}
else if(valRangAlarme[i] == 1) { }
else {bitClear(alarme1, i+1);}
}
//Controle le retard et adapte la vitesse du moteur
#ifdef DEBUGloopStepp_stepp
Serial.print("| E01, ");
#endif//DEBUG
int32_t TempStepperAngle = stepper->getCurrentPosition() - nStepperTour * steppTour;
// Set the current position of the stepper - either in standstill or while moving.
// for esp32: the implementation uses getCurrentPosition(), which does not
// consider the steps of the current command
// => recommend to use only in standstill
int32_t reelSpeedMoteur = 0;
if(swSeme) {
reelSpeedMoteur = stepper->getCurrentSpeedInMilliHz()/1000;
}
#ifdef DEBUGstepperValTraceur
if(swSeme) {
//Serial.print(" Millis: ");Serial.println(millis());
//Serial.print(">motor_speed:");
}
#endif
retardStepp = lastSteppPos - TempStepperAngle;
#ifdef DEBUGstepperValTraceur
if(swSeme) {
Serial.print(reelSpeedMoteur); Serial.print(","); //Serial.print(">retard: ");
Serial.print(retardStepp); Serial.print(",");
}
#endif
// Moyenner la valeur ci-dessus pour lisser le retard
retardStepp = lisageRetard(retardStepp);
#ifdef DEBUGstepperValTraceur
if(swSeme) {
Serial.print(retardStepp); Serial.print(","); //Serial.print(">retard_moyen: ");
Serial.print(newStepp); Serial.print(","); //Serial.print(">Stepp_Ajouter: ");
}
#endif
int16_t _TempLisNewStepp = lisageNewStepp(newStepp);
majSpeedStepp = lisageCurSpeed(abs(reelSpeedMoteur))/35; // [x10] pour compensser dans le 10èmme de seconde // [-vtSteppMin/60 / Y] pour avoir un temp de décélération
newSpeedStepp = (retardStepp + _TempLisNewStepp - majSpeedStepp) * 12;
if (newSpeedStepp < miniSteppSpeed) {
newSpeedStepp = 0;
}
else if (newSpeedStepp > maxiSteppSpeed) {
newSpeedStepp = maxiSteppSpeed;
}
#ifdef DEBUGstepperValTraceur
if(swSeme) {
Serial.println(newSpeedStepp); Serial.print(","); //Serial.print(">commande_speed: ");
}
#endif
if(newSpeedStepp + 50 < reelSpeedMoteur && newSpeedStepp >= 0) {stepper->setAcceleration(10000);} //Mode décélération rapide
else if (reelSpeedMoteur > 1500) {stepper->setAcceleration(2000);}
else if (reelSpeedMoteur < 1400 && reelSpeedMoteur > 1100) {stepper->setAcceleration(5000);}
else {stepper->setAcceleration(10000);}
// //Test vélossité : vitesse envoyé - vitesse réelle >>> voir version 0_3_02
#ifdef DEBUGstepperSpeed
//Serial.print("points de retard "); Serial.print(retardStepp);
//Serial.print("\tpoints logitiel "); Serial.print(lastSteppPos);
//Serial.print("\tpoints moteur "); Serial.print(stepper->getCurrentPosition());
//Serial.print("\tmise à jour vitesse "); Serial.print(majSpeedStepp);
Serial.print("\tvitesse calculcodeur ");
Serial.print(vtSteppMin/60);
Serial.print("\tvitesse points/s ");
Serial.print(vtPntMin/60);
#endif
//envoye la nouvelle vitesse au moteur //>> newSpeedStepp = vitesse à envoyer au moteur
#ifdef DEBUGloopStepp_stepp
Serial.print("| F01, ");
#endif//DEBUG
stepperOn = stepper->isRunning(); //Renvoye vrai pendant l'arrêt du moteur (décélération jusqu'au stop)
if (newSpeedStepp != 0) {
stepper->setSpeedInHz(newSpeedStepp);
if (!stepperOn) {
stepper->runForward();
}
else {
stepper->applySpeedAcceleration();
}
//stepper->move(newStepp); //le PaP est régulé uniquement par la vitesse. (le nombre de pas influence la vitesse par l'intermédiaire du [retardStepp])
#ifdef DEBUGstepperSpeed
Serial.print(" | newSpeedStepp\t");
Serial.print(newSpeedStepp);
#endif
}
else {
if (stepperOn) {
stepper->applySpeedAcceleration(); //Pour appliquer la valeur de décélération pendant l'arrêt du moteur
stepper->stopMove();
#ifdef DEBUGstepperSpeed
Serial.print("\tArrêt du moteur envoyé");
#endif
}
else {
//else if (stepper->isEnableStepper()) { //Trouver la fonction qui renvoie l'état de la pin enable du moteur !! getEnablePinHighActive()ne fonctionne pas
#ifdef DEBUGstepperSpeed
Serial.print("\tMoteur est à l'arrêt et il est désactivé");
#endif
if (stepper->getCurrentPosition() > 2000111222){ // ~ 147'000'000 de stepp avant le bouclage automatique du comteur [int32_t]
majStepperCurrentPos(); //profiter de l'arrêt du PàP pour remettre "à zéro" son compteur de position
}
else if (nStepperTour > 55000) {
majStepperCurrentPos(); //profiter de l'arrêt du PàP pour remettre "à zéro" son compteur de position
}
}
#ifdef DEBUGstepperSpeed
Serial.print("\tnewSpeedStepp :\t");
Serial.print(newSpeedStepp);
#endif
}
#ifdef DEBUGstepperSpeed
Serial.println();
#endif
#ifdef DEBUGenableOutputs
//Serial.println(stepper->enableOutputs());
//Serial.println(stepper->disableOutputs());
#endif
#ifdef DEBUGstepperValeurs
Serial.print("> isRunning "); Serial.print(stepper->isRunning());
Serial.print("\tisStopping "); Serial.print(stepper->isStopping());
//Serial.print("\t||\tretard "); Serial.print(stepper->disableOutputs());//>>Modifie la valeur Enable à false //bool disableOutputs();returns true, if disabled
//Serial.print("\tenableOutputs "); Serial.print(stepper->enableOutputs());//>>Modifie la valeur Enable à true //bool enableOutputs();returns true, if enabled
Serial.print("\t||\tretard "); Serial.print(retardStepp);
Serial.print("\tmajSpeedStepp "); Serial.print(majSpeedStepp);
Serial.print("\tnewSpeedStepp "); Serial.print(newSpeedStepp);
Serial.print("\tvtSteppSec "); Serial.print(vtSteppMin/60);
Serial.print("\tvtPntMin "); Serial.print(vtPntMin);
Serial.print("\tgetSpeedInHz "); Serial.print(stepper->getSpeedInMilliHz()/1000);//uint32_t getSpeedInMilliHz()
//Serial.print("\txxx "); Serial.print(xxx);
#endif
//Contrôle du steppermotor
#ifdef DEBUGloopStepp_stepp
Serial.print("| G01, ");
#endif//DEBUG
if (stepperOn){
if (newSpeedStepp >= maxiSteppSpeed || vtSteppMin/60 > maxiSteppSpeed *18/20){
bitSet(alarme1, 5); //Alarme On
}
else if (bitRead(alarme1, 5)){
if (newSpeedStepp < maxiSteppSpeed *19/20 && vtSteppMin/60 < maxiSteppSpeed *26/30){
bitClear(alarme1, 5); //AlarmeOff
}
}
}
//Réinitialisation des variables
#ifdef DEBUGloopStepp_stepp
Serial.print("| H01, ");
#endif//DEBUG
lastTime = newTime;
codeurPnt -= newPnt;
lastPntPos += newPntStepper;
lastSteppPos += newStepp;
if (lastPntPos >= pntSteppTour) {
lastPntPos -= pntSteppTour;
lastSteppPos -= steppTour;
nStepperTour ++;
//Si le compteur arrive à ça limite, vidange des compteurs. (normalement se fait avant d'arriver à ce stade de remplissage, quand le moteur est à l'arrêt)
if (stepper->getCurrentPosition() > 2146000123 || nStepperTour > 64000) {
majStepperCurrentPos();
}
}
lastRetardStepp = retardStepp;
if (alarme1 != 0) majAlarme(); //ATTEENTION, c'est majAlarme qui doit metre le 1er bit à zéro pour permettre l'extinction de l'alarme
//#ifdef DEBUG...
#ifdef DEBUGloopStepp_stepp
Serial.println("| I01, ");
#endif//DEBUG
#ifdef DEBUGloopSpeed
DebugCptLoop ++;
if(DebugCptLoop>10000){
Serial.print("*");
DebugCptLoop = 1;
DebugCptLoopMultiple ++;
if(DebugCptLoopMultiple>100){
DebugCptLoopMultiple = 1;
Serial.println( "1'000'000 de loop");
Serial.print(" (millis pour 1*10^6 loop = ");
Serial.print(millis()- DebugTimmerLoop);
Serial.print(" | loop/s = ");
Serial.print(1000000000 / (millis()- DebugTimmerLoop));
Serial.println(" )");
DebugTimmerLoop = millis();
}
}
#endif
#ifdef DEBUGAlarme
//Rang à analyser:
#define _TempRang 1
#ifdef _TempRang
if(lignePlanteuse[_TempRang] != NULL) {
if(lignePlanteuse[_TempRang]->getNbrPlanter() != DebugAlOld_cptPlant){
Serial.print("O");
DebugAlOld_cptPlant = lignePlanteuse[_TempRang]->getNbrPlanter();
}
//else if(lignePlanteuse[_TempRang]->getNbrManquer() != DebugAlOld_cptManque){
if(lignePlanteuse[_TempRang]->getNbrManquer() != DebugAlOld_cptManque){
Serial.print("X");
//testDEBUG: Serial.println(lignePlanteuse[_TempRang]->getNbrManquer()); delay(300);
DebugAlOld_cptManque = lignePlanteuse[_TempRang]->getNbrManquer();
}
//else {Serial.print(".");}
}
#endif
if (alarme1 != DebugAlarme1){
Serial.print ("byte alarme1 = "); Serial.print(alarme1);
if(bitRead(alarme1, 1)) Serial.print ("\t>> alarme ligne1");
if(bitRead(alarme1, 2)) Serial.print ("\t>> alarme ligne2");
if(bitRead(alarme1, 3)) Serial.print ("\t>> alarme ligne3");
if(bitRead(alarme1, 4)) Serial.print ("\t>> alarme ligne4");
if(bitRead(alarme1, 5)) Serial.print ("\t>> alarme trop vite");
if(bitRead(alarme1, 6)) Serial.print ("\t>> alarme semoir bloqué");
for(int i = 0; i < nbrlignePlanteuse; i ++){
if(bitRead(alarme1, i+1)){
byte _TempAlarmeRangByte = lignePlanteuse[i]->getAlarme();
Serial.print ("\n >>> byte alarme ligne "); Serial.print(i+1); Serial.print(" = "); Serial.print(_TempAlarmeRangByte);
if(bitRead(_TempAlarmeRangByte, 0)) Serial.print ("\t>> Manque un plant");
if(bitRead(_TempAlarmeRangByte, 1)) Serial.print ("\t>> alarme manques répétés");
if(bitRead(_TempAlarmeRangByte, 2)) Serial.print ("\t>> alarme % manque dépassé");
if(bitRead(_TempAlarmeRangByte, 3)) Serial.print ("\t>> alarme capteur bloqué à ON");
if(bitRead(_TempAlarmeRangByte, 4)) Serial.print ("\t>> alarme plants trop proche"); //Alarme pas encors programmée
if(bitRead(_TempAlarmeRangByte, 5)) Serial.print ("\t>> alarme bit5"); //Alarme pas utilisée
if(bitRead(_TempAlarmeRangByte, 6)) Serial.print ("\t>> alarme bit6"); //Alarme pas utilisée
if(bitRead(_TempAlarmeRangByte, 7)) Serial.print ("\t>> alarme bit7"); //Alarme pas utilisée
}
}
DebugAlarme1 = alarme1;
Serial.println();
}
#endif
#ifdef DEBUGstepperValeurs
Serial.println(" >> next loop >>");
#endif
#ifdef InfoSerialMoniteur
printInfoSerialMoniteur();
#endif
}
void majStepperCurrentPos(){
if (nStepperTour > 2){ //Contrôle si la mise à jour à u le temp de s'activer;
int32_t TempStepperPos = stepper->getCurrentPosition();
stepper->setCurrentPosition(TempStepperPos - nStepperTour * steppTour);
nStepperTour = 0;
#ifdef DEBUG
Serial.println("\n\n*****************************************************");
Serial.print("stepper->getCurrentPosition() :\t");
Serial.println(TempStepperPos);
Serial.println("\n\tMise à jour de la position de moteur pas à pas\n");
delay(5);
Serial.print("stepper->getCurrentPosition() :\t");
Serial.println(stepper->getCurrentPosition());
Serial.println("\n*****************************************************\n");
#endif
} else {
#ifdef DEBUG
Serial.println("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
Serial.println("\tmaj ANNULEE de la position de moteur pas à pas\n");
Serial.print("stepper->getCurrentPosition() :\t");
Serial.println(stepper->getCurrentPosition());
Serial.println("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
#endif
}
}
int32_t lisageRetard(int32_t _retardStepp){
const int8_t __nbrTblRetardStepp = 12;
int8_t __nbrIRetardStepp = __nbrTblRetardStepp;
int32_t __somRetardStepp = 0;
static int8_t _iRetatdStepp = -1 * __nbrTblRetardStepp;
static int32_t _tblRetardStepp[__nbrTblRetardStepp];
if(_iRetatdStepp < 0){ //Evite de moyenner avec les 0 au démarrage = plus réactif
__nbrIRetardStepp = _iRetatdStepp + __nbrTblRetardStepp;
_tblRetardStepp[__nbrIRetardStepp] = _retardStepp;
__nbrIRetardStepp ++;
}
else {
_tblRetardStepp[_iRetatdStepp] = _retardStepp;
// if(newStepp == 0 && __nbrTblRetardStepp > 3){ //A tester: dessente rapide
// _iRetatdStepp ++;
// if(_iRetatdStepp >= __nbrTblRetardStepp) _iRetatdStepp = 0;
// _tblRetardStepp[_iRetatdStepp] = 0;
// }
}
_iRetatdStepp ++;
if(_iRetatdStepp >= __nbrTblRetardStepp) _iRetatdStepp = 0;
for(int i = 0; i < __nbrIRetardStepp; i++){
__somRetardStepp += _tblRetardStepp[i];
}
if(__somRetardStepp == 0) _iRetatdStepp = -1 * __nbrTblRetardStepp;
return (__somRetardStepp / __nbrIRetardStepp);
}
int32_t lisageNewStepp(int32_t _NewStepp){
const int8_t __nbrTblNewStepp = 10;
int8_t __nbrINewStepp = __nbrTblNewStepp;
int32_t __somNewStepp = 0;
static int8_t _iNewStepp = -1 * __nbrTblNewStepp;
static int32_t _tblNewStepp[__nbrTblNewStepp];
if(_iNewStepp < 0){ //Evite de moyenner avec les 0 au démarrage = plus réactif
__nbrINewStepp = _iNewStepp + __nbrTblNewStepp;
_tblNewStepp[__nbrINewStepp] = _NewStepp;
__nbrINewStepp ++;
}
else {
_tblNewStepp[_iNewStepp] = _NewStepp;
if(_NewStepp == 0){ //Dessente rapide
_iNewStepp ++;
if(_iNewStepp >= __nbrTblNewStepp) _iNewStepp = 0;
_tblNewStepp[_iNewStepp] = _NewStepp;
if(__nbrTblNewStepp > 5){
_iNewStepp ++;
if(_iNewStepp >= __nbrTblNewStepp) _iNewStepp = 0;
_tblNewStepp[_iNewStepp] = _NewStepp;
}
}
}
_iNewStepp ++;
if(_iNewStepp >= __nbrTblNewStepp) _iNewStepp = 0;
for(int i = 0; i < __nbrINewStepp; i++){
__somNewStepp += _tblNewStepp[i];
}
int32_t _T_Retour = -1;
if(__somNewStepp == 0) {
_iNewStepp = -1 * __nbrTblNewStepp;
}
else if(__somNewStepp / __nbrINewStepp != 0) {
_T_Retour = __somNewStepp / __nbrINewStepp;
}
return _T_Retour;
}
int32_t lisageCurSpeed(int32_t _CurentSpeed){
const int8_t __nbrTblCurSpeed = 10;
int8_t __nbrICurSpeed = __nbrTblCurSpeed;
int32_t __somCurSpeed = 0;
static int8_t _iCurSpeed = -1 * __nbrTblCurSpeed;
static int32_t _tblCurSpeed[__nbrTblCurSpeed];
if(_iCurSpeed < 0){ //Evite de moyenner avec les 0 au démarrage = plus réactif
__nbrICurSpeed = _iCurSpeed + __nbrTblCurSpeed;
_tblCurSpeed[__nbrICurSpeed] = _CurentSpeed;
__nbrICurSpeed ++;
}
else {
_tblCurSpeed[_iCurSpeed] = _CurentSpeed;
}
_iCurSpeed ++;
if(_iCurSpeed >= __nbrTblCurSpeed) _iCurSpeed = 0;
for(int i = 0; i < __nbrICurSpeed; i++){
__somCurSpeed += _tblCurSpeed[i];
}
int32_t _T_Retour = -1;
if(__somCurSpeed == 0) {
_iCurSpeed = -1 * __nbrTblCurSpeed;
}
else if(__somCurSpeed / __nbrICurSpeed != 0) {
_T_Retour = __somCurSpeed / __nbrICurSpeed;
}
return _T_Retour;
}
void addDistance(){
if (swSeme) newPntStepper = newPnt; else newPntStepper = 0;
if (newPnt < 0){
if (cptPntDist > newPnt * -1) {
cptPntDist += newPnt;
}
else if (cptPntKm > 0){
cptPntDist += pnt100m * 10;
cptPntKm --;
cptPntDist += newPnt;
}
else {cptPntDist = 0;}
if(swSeme){
if (cptPntDistSeme > newPnt * -1) {
cptPntDistSeme += newPnt;
}
else if (cptPntKmSeme > 0){
cptPntDistSeme += pnt100m * 10;
cptPntKmSeme --;
cptPntDistSeme += newPnt;
}
else {cptPntDistSeme = 0;}
}
else {cptPntDistSeme = 0;}
if(swPlante){
if (cptPntDistPlante > newPnt * -1) {
cptPntDistPlante += newPnt;
}
else if (cptPntKmPlante > 0){
cptPntDistPlante += pnt100m * 10;
cptPntKmPlante --;
cptPntDistPlante += newPnt;
}
else {cptPntDistPlante = 0;}
}
else {cptPntDistPlante = 0;}
}
else {
cptPntDist += newPnt; //nombre de points du compteur de distance parcourue. Compteur vidé tous les kilo-mètres dans [cptPntKm].
if(swSeme) cptPntDistSeme += newPnt;
if(swPlante) cptPntDistPlante += newPnt;
}
if (cptPntDist >= pnt100m * 10) {
cptPntKm ++; //nombre de kilomètres parcourus par la machine.
cptPntDist -= pnt100m * 10;
}
if (cptPntDistSeme >= pnt100m * 10) {
cptPntKmSeme ++; //nombre de kilomètres parcourus par la machine.
cptPntDistSeme -= pnt100m * 10;
}
if (cptPntDistPlante >= pnt100m * 10) {
cptPntKmPlante ++; //nombre de kilomètres parcourus par la machine.
cptPntDistPlante -= pnt100m * 10;
}
}
void addVt(){
int8_t TempVtI = 20;
int32_t TempVtSommePnt = 0;
if (iTblPntVt < 0){ //enregistrement simple au demarrage
TempVtI += iTblPntVt;
tblPntVt[TempVtI] = cptPntVt * 2;
iTblPntVt ++;
TempVtI ++;
jTblPntVt = true;
}
else { //Enregistrement double si différent de 0 points / seconde (pour faire désendre plus rapidement lors d'arrêt brusque)
//>> implique qu'il y est aumoins 1 point pendant timelapseVt[millis] pour la vitesse minimum
if (jTblPntVt) {
tblPntVt[iTblPntVt] = cptPntVt * 2;
if (cptPntVt == 0) {
iTblPntVt ++;
}
else {
jTblPntVt = false;
}
}
else {
// uint16_t TempTblVal = tblPntVt[iTblPntVt] / 2;
// tblPntVt[iTblPntVt] = TempTblVal + cptPntVt;
tblPntVt[iTblPntVt] = tblPntVt[iTblPntVt] / 2 + cptPntVt;
iTblPntVt ++;
jTblPntVt = true;
}
}
if (iTblPntVt > 19) {
iTblPntVt = 0;
}
//Calculs
for (int i=0; i<TempVtI; i++) {
TempVtSommePnt += tblPntVt[i];
}
vtPntMin = TempVtSommePnt * 60000 / timelapseVt / 40; //en [pnt/min] >> pnt = TempVtSommePnt >> temps[min] = 40[enregistrements] *timelapseVt[millis] /60'000 [millis/minutte]
vtSteppMin = vtPntMin * steppTour / pntSteppTour;
//vtMsec = int((TempVtSommePnt*10000*1000/timelapseVt/40)/pnt100m)/100;
//Test print Vitesse: printVtKmH(); Serial.print(" km/h\t");printVtMs(); Serial.print(" m/s\t");Serial.print(vtPntMin/60);Serial.print(" pnt/s\t|\t"); Serial.print(vtSteppMin/200); Serial.print(" RPM moteur\t"); printDistMpalnter(); Serial.println(" mètres plantés");
#ifdef DEBUGcalculSpeed
Serial.print("\niTblPntVt ");
Serial.print(iTblPntVt );
Serial.print("\tcptPntVt ");
Serial.print(cptPntVt);
Serial.print("\tvtSteppMin ");
Serial.print(vtSteppMin);
Serial.print("\tvtPntMin ");
Serial.print(vtPntMin);
Serial.print("\tvtkm/h "); printVtKmH();
Serial.print("\tTempVtSommePnt ");
Serial.println(TempVtSommePnt);
#endif
if (TempVtSommePnt == 0) {iTblPntVt = -20;}
cptPntVt = 0;
}
void printVtKmH() { //vitesse d'avancement en kilomètres / heure
uint32_t TempVtMH = vtPntMin*60*100/pnt100m;
uint32_t TempVtMHDecimal = int(TempVtMH/10 - int(TempVtMH/1000)*100);
Serial.print(int(TempVtMH/1000));
Serial.print(".");
// pour 2 décimales: if (TempVtMHDecimal < 10) {Serial.print("0");}
// pour 2 décimales: Serial.print(TempVtMHDecimal);
// pour 1 décimale:
Serial.print(TempVtMHDecimal/10);
//serial.print(" km/h");
}
void printVtMs() { //vitesse d'avancement en mètres / seconde
uint32_t TempVtCmS = vtPntMin *10000 / pnt100m /60;
uint32_t TempVtCmSDecimal = TempVtCmS - int(TempVtCmS/100)*100;
Serial.print(int(TempVtCmS/100));
Serial.print(".");
if (TempVtCmSDecimal < 10) Serial.print("0");
Serial.print(TempVtCmSDecimal);
//serial.print(" m/s");
}
void printDistMpalnter() { //>>> A adapter à la bibliothèque <<<
uint16_t TempMPlanter = nbrlignePlanteuse * cptPntDist * 100 / pnt100m;
uint16_t TempiKm = 0;
while (TempMPlanter > 999){
TempiKm ++;
TempMPlanter -= 1000;
}
TempiKm += nbrlignePlanteuse * cptPntKm;
if(TempiKm >= 1000) {
Serial.print(int(TempiKm/1000));
Serial.print("'");
Serial.print(TempiKm - int(TempiKm /1000)*1000);
}
else {
Serial.print(TempiKm);
}
Serial.print(".");
if (TempMPlanter < 100) Serial.print(0);
if (TempMPlanter < 10) Serial.print(0);
Serial.print(TempMPlanter);
//serial.print(" m plantés")
}
bool majAlarme(){ //>>> A adapter à la bibliothèque <<<
int8_t TempCptAlarme = 0;
bool TempReponce;
if (bitRead(alarme1, 5)) TempCptAlarme +=1; //PàP trop vite
if (bitRead(alarme1, 6)) TempCptAlarme +=10; //PàP bloqué
if (bitRead(alarme1, 1)) TempCptAlarme +=5; //alarme ligne 1
if (bitRead(alarme1, 2)) TempCptAlarme +=5; //alarme ligne 2
if (bitRead(alarme1, 3)) TempCptAlarme +=5; //alarme ligne 3
if (bitRead(alarme1, 4)) TempCptAlarme +=5; //alarme ligne 4
if (TempCptAlarme == 0){ //AlarmeSTOP
bitWrite(alarme1, 0, 0);
bitClear(alarme1, 7); //BuzzerOFF
//alarmecentralBlink(false);
TempReponce = false;
}
else if (!bitRead(alarme1, 0)) { //AlarmeSTART
bitWrite(alarme1, 0, 1);
//alarmecentralBlink(true);
TempReponce = true;
}
else { //AlarmeON
//alarmecentralBlink(true);
if(TempCptAlarme > 1){
bitWrite(alarme1, 7, 1); //BuzzerON
}
TempReponce = true;
}
alarmecentral(alarme1);
return TempReponce;
}
void alarmecentral(byte AlarmeEtat) {
if (bitRead(AlarmeEtat, 0)){
if(etatAlLampe){
if (lastTimeAlBlink + 120 <= millis()){
etatAlLampe = LOW;
}
}
else {
if (lastTimeAlBlink + 200 <= millis()){
lastTimeAlBlink = millis();
etatAlLampe = HIGH;
}
}
}
else {
etatAlLampe = LOW;
//etatAlBuzzer = LOW;
}
digitalWrite(ledAlCentral, etatAlLampe);
if (bitRead(AlarmeEtat, 7)){
if(etatAlBuzz){
if (lastTimeAlBuzz + 100 <= millis()){
etatAlBuzz = LOW;
}
}
else {
if (lastTimeAlBuzz + 300 <= millis()){
lastTimeAlBuzz = millis();
etatAlBuzz = HIGH;
}
}
}
else {
etatAlBuzz = LOW;
}
digitalWrite(buzzAlCentral, etatAlBuzz);
}
void alarmeReset(){
delay(20); //Anti-rebond bloquant mais suffisant, l'action ne s'execute qu'exceptionnellement, la loop arrive à rattrapper le retard...
if (digitalRead(swAlReset)) return;
#ifdef DEBUGAlarme
Serial.print ("START_reset_alarme byte alarme1 = "); Serial.println(alarme1);
#endif
#ifdef DEBUGswitch
Serial.print("Reset alarme Start");
#endif
while (!digitalRead(swAlReset)) { } //Attend que le bouton soit relâcher pour éviter de faire le reset en boucle
// #ifdef DEBUGloopStepp_stepp >>>SAns bouton c'est normal que ça bloque !!!
// Serial.print("b"); //A_03_b
// #endif//DEBUG
for (int i = 0; i< nbrlignePlanteuse; i++){
//Old variante: alarmeResetRang(i+1);
lignePlanteuse[i]->resetAlarme();
}
alarme1 = 0;
majAlarme();
#ifdef DEBUGswitch
Serial.println("\t Reset alarme END");
#endif
#ifdef DEBUGAlarme
Serial.print ("END_reset_alarme byte alarme1 = "); Serial.println(alarme1);
#endif
delay(5);
}
void alarmeResetRang(const uint8_t nrRang){
lignePlanteuse[nrRang]->resetAlarme();
}
void manuelMoteurOn(uint16_t ManuelOnSpeed){ //active le moteur du semoir lentement (vitesse = 100step/s, accélération = 30step/s²)
delay(20); //Anti-rebond bloquant mais suffisant, la fonction s'execute à l'arrêt de la machine
if (digitalRead(swMoteurOn)) return;
#ifdef DEBUGswitch
Serial.print("manuel moteur ON");
#endif
stepper->stopMove();
while (stepper->isRunning()) { }
delay(2);
int32_t _tempStepperCurrentPos = stepper->getCurrentPosition();
uint32_t _tempStepperCurrentAccel = stepper->getAcceleration();
uint32_t _tempStepperSpeed = stepper->getSpeedInMilliHz();
stepper->setSpeedInHz(ManuelOnSpeed);
stepper->setAcceleration(30); //steps/s²
stepper->applySpeedAcceleration();
stepper->runForward();
while (digitalRead(swMoteurOn)==LOW) { //Réinitialise pas assé vite le "Task watchdog got triggered" de la loop()
delay(1); //Pour réinitialiser le Watchdog (voir: https://forum.arduino.cc/t/while-task-watchdog-got-triggered-avec-esp32-coeur0/1121766/2)
}
stepper->setAcceleration(200); //steps/s²
stepper->applySpeedAcceleration();
stepper->stopMove();
while (stepper->isRunning()) {delay(1);}
delay(2);
stepper->setSpeedInMilliHz(_tempStepperSpeed);
stepper->setAcceleration(_tempStepperCurrentAccel); //steps/s²
stepper->setCurrentPosition(_tempStepperCurrentPos);
stepper->applySpeedAcceleration();
#ifdef DEBUGswitch
Serial.println("\t manuel moteur OFF");
#endif
}
void comptePnt() {
if (digitalRead(codeurAPin) == digitalRead(codeurBPin)) {
codeurPnt += valeurPnt;
}
else {
codeurPnt -= valeurPnt;
}
}
#ifdef InfoSerialMoniteur
uint32_t infoSerialMoniteurTimmer = 0;
bool infoSerialMoniteurActualiser = true;
void printInfoSerialMoniteur(){ //Affiche les information importantes sur le moniteur serie
//Afficher les valeurs actuelles de la machine
if(infoSerialMoniteurActualiser){
if(infoSerialMoniteurTimmer < millis()){ //Actualise les données toutes les 10 secondes
infoSerialMoniteurTimmer = millis() + 2000;
uint16_t _TempManqueMilleTotal = 0;
uint16_t _TempSpacePlantTotal = 0;
uint64_t _TempNbrPlanteTotal = 0;
uint64_t _TempNbrManqueTotal = 0;
for(int i = 0; i < nbrlignePlanteuse; i++){
_TempManqueMilleTotal += lignePlanteuse[i]->getManquePourMille();
_TempSpacePlantTotal += lignePlanteuse[i]->getMoyenSpacePlant();
_TempNbrPlanteTotal += lignePlanteuse[i]->getNbrPlanter();
_TempNbrManqueTotal += lignePlanteuse[i]->getNbrManquer();
}
if(_TempManqueMilleTotal > 0) _TempManqueMilleTotal = _TempManqueMilleTotal / nbrlignePlanteuse;
if(_TempSpacePlantTotal > 0) _TempSpacePlantTotal = _TempSpacePlantTotal * 100 / nbrlignePlanteuse * 100 / pnt100m; //*100 pour passer en mètre, *100 pour passer en cm / pnt100m
//1ère ligne
Serial.println("\n*** Actualisations des valeurs **********************");
Serial.print("** Vitesse: "); printVtKmH(); Serial.print("km/h");
Serial.print("\tdistance parcourue: "); printDistMpalnter(); Serial.print("km");
Serial.print("\tdistance entre plans: "); Serial.print(_TempSpacePlantTotal); Serial.print("cm");
Serial.print("\tRPM stepper: "); Serial.print(stepper->getCurrentSpeedInMilliHz()/1000*60/200); Serial.print(" tour/min");
Serial.println();
//Ligne 2
Serial.print("** Plants manqués: "); Serial.print(int(_TempManqueMilleTotal / 10));
Serial.print("."); Serial.print(_TempManqueMilleTotal - (10 * int(_TempManqueMilleTotal / 10))); Serial.print("%");
Serial.print("\tPlants plantés: "); Serial.print(_TempNbrPlanteTotal); Serial.print("pce");
Serial.print("\tPlants manqués: "); Serial.print(_TempNbrManqueTotal); Serial.print("pce");
Serial.print("\tPlanteuse active: "); if(swPlante){Serial.print("OUI");} else{Serial.print("NON");}
Serial.print("\tSemoir actif: "); if(swSeme){Serial.print("OUI");} else{Serial.print("NON");}
Serial.println("\n*********************");
// Effacer les oldALARME pour réafficher les alarme en court
oldAlarme1 = 0;
memset(oldValRangAlarme, 0, sizeof oldValRangAlarme);
}
}
//Contrôler et afficher les ALARMES
//Alarmes Rang
for(int i = 0; i < nbrlignePlanteuse; i++){
if(valRangAlarme[i] != oldValRangAlarme[i]){
if(valRangAlarme[i] <= 1){
if(oldValRangAlarme[i] > 1){ //Aficher l'extinction (la fin) d'une alarme majeure
//if(bitRead(oldValRangAlarme[i],1)) Serial.print("\n<<< Fin de l'alarme ... sur le rang "); Serial.print(i+1);
Serial.print("\n... Le rang "); Serial.print(i+1); Serial.println(" >> n'a plus d'alarme");
}
if(valRangAlarme[i] == 1){ // il y a juste un plant de manqué, c'est pas une grosse alarme
Serial.print(" , "); Serial.print(i+1); //j'affiche juste le n° du rang ou il manque un planté
} //j'affiche rien à l'extinction de cette alarme
}
else { //Une alarme importante et signalée
if(abs(valRangAlarme[i] - oldValRangAlarme[i]) > 1){ //Contrôle que pas seulement le bit1 à changé
Serial.print("\n!!! ALARME Rang "); Serial.print(i+1);
if(bitRead(valRangAlarme[i],1) << bitRead(oldValRangAlarme[i],1)) Serial.print(" ||\tmanques répétés");
if(bitRead(valRangAlarme[i],2) << bitRead(oldValRangAlarme[i],2)) Serial.print(" ||\t% manque dépassé");
if(bitRead(valRangAlarme[i],3) << bitRead(oldValRangAlarme[i],3)) Serial.print(" ||\tcapteur bloqué à ON");
if(bitRead(valRangAlarme[i],4) << bitRead(oldValRangAlarme[i],4)) Serial.print(" ||\tplants trop proche");
if(bitRead(valRangAlarme[i],5) << bitRead(oldValRangAlarme[i],5)) Serial.print(" ||\tbit5");
if(bitRead(valRangAlarme[i],6) << bitRead(oldValRangAlarme[i],6)) Serial.print(" ||\tbit6");
if(bitRead(valRangAlarme[i],7) << bitRead(oldValRangAlarme[i],7)) Serial.print(" ||\tbit7");
if(bitRead(valRangAlarme[i],1) >> bitRead(oldValRangAlarme[i],1)) Serial.print(" ..\tRésolue manques répétés");
if(bitRead(valRangAlarme[i],2) >> bitRead(oldValRangAlarme[i],2)) Serial.print(" ..\tRésolue % manque dépassé");
if(bitRead(valRangAlarme[i],3) >> bitRead(oldValRangAlarme[i],3)) Serial.print(" ..\tRésolue capteur bloqué à ON");
if(bitRead(valRangAlarme[i],4) >> bitRead(oldValRangAlarme[i],4)) Serial.print(" ..\tRésolue plants trop proche");
if(bitRead(valRangAlarme[i],5) >> bitRead(oldValRangAlarme[i],5)) Serial.print(" ..\tRésolue bit5");
if(bitRead(valRangAlarme[i],6) >> bitRead(oldValRangAlarme[i],6)) Serial.print(" ..\tRésolue tbit6");
if(bitRead(valRangAlarme[i],7) >> bitRead(oldValRangAlarme[i],7)) Serial.print(" ..\tRésolue tbit7");
Serial.println();
if(bitRead(valRangAlarme[i],0)) Serial.print(" , "); Serial.print(i+1);
}
else if(bitRead(valRangAlarme[i],0)) Serial.print(" , "); Serial.print(i+1);
}
oldValRangAlarme[i] = valRangAlarme[i];
}
//delay(1);//Pour réinitialiser le Watchdog (voir: https://forum.arduino.cc/t/while-task-watchdog-got-triggered-avec-esp32-coeur0/1121766/2)
}
//Alarmes semoir
if(bitRead(alarme1, 5) || bitRead(alarme1, 6)){ //Contrôler si il y a une alarme pour le semoir
if(bitRead(alarme1, 5) != bitRead(oldAlarme1, 5) || bitRead(alarme1, 6) != bitRead(oldAlarme1, 6)){ //Contrôler si elle n'a pas déjà été annoncée
Serial.print("\n>>> ALARME Semoir");
if(bitRead(alarme1, 5)) Serial.print("\t>> Vous roulez trop vite");
if(bitRead(alarme1, 6)) Serial.print("\t>> STOP le semoir est bolqué");
Serial.println();
}
}
else if(bitRead(oldAlarme1, 5) || bitRead(oldAlarme1, 6)){
Serial.print("\n... Le semoir "); Serial.println(" >> n'a plus d'alarme");
}
// bitWrite(oldAlarme1, 5, bitRead(alarme1, 5));
// bitWrite(oldAlarme1, 6, bitRead(alarme1, 6));
oldAlarme1 = alarme1;
if(alarme1 == 0){infoSerialMoniteurActualiser = true;}
else {infoSerialMoniteurActualiser = false;}
}
#endif //defined (InfoSerialMoniteur)
//FIN