Aide pour automatiser (programmer) une coupeuse de fil de fer fabrication maison

Bonjour à tous,
Je cherche une aide en programmation sur Arduino méga,
dans le département du Gard où de l'Hérault idéalement, afin de finaliser un asservissement sur une machine que j'ai réalisée pour m'aider dans ma petite activité artisanale.
Je suis pas du tout à l'aise avec le langage C++ et la programmation tout court.
Pour quelqu'un qui maitrise la programmation, je pense que mon projet est pas très sorcier, mais surement nécessite de faire des crach test en live d'où l'idéal de trouver pas trop loin de chez moi.
j'ai juste besoin de faire fonctionner cette machine et non de devenir programmeur.
J'ai commencé un début de code avec un ami mais ça marche pas malgré beaucoup de temps passé, donc on sollicite l'aide d'une bonne âme !
merci d'avance à qui repondra....à mon S.O.S..
CDLT...

Comme tu ne cherches pas d'aide pour t'aider à programmer ou debugger, le mieux serait que tu poste dans la section de proposition d'emplois.

Si vous ne trouvez pas, postez plus d’infos ici sur la machine et le besoin, et éventuellement votre code (avec les balises) et dessin du circuit ça aidera à qualifier la complexité du code nécessaire

Ma machine sert à recycler du fil de fer.
pour faire simple, je recupere des bobines de fil de fer de vignes arrachées et ma machine nettoie, redresse et coupe en baguette de longueur entre 30 et 99cm de long à la demande.
L'asservissement, consiste en un pupitre de programmation ou je paramètre mes valeurs de coupe souhaitées, puis la machine entraine le fil au signal d'une commande par pédale switch on/off, arrête l'entrainement lorsque la longueur est atteinte et déclenche alors la coupe de la baguette, puis repart et ainsi de suite...
Les composants machine sont,
entraineur moteur 24vcc à balais.
cisaille pneumatique commandée par un distributeur 24vcc également.

La partie asservissement, Arduino Méga,
1 pupitre de commande comprenant,

1 switch permanent 2 positions, pour la mise sous tension et l'arrêt de l'asservissement.
1 switch permanent 2 positions, selectionneur de mode ( prog, marche auto, marche forcée)
1 switch poussoir / rotatif infini, pour entrer les valeurs de coupe
3 afficheurs numeriques à 2 chiffres couplés en parallelle, ( je ne veux pas forcement toujour couper des baguettes de longueurs identique, mais plutot des serie de coupe sequentielles. le premier afficheur selectionne la coupe de longeur minimale de 20à99, le second afficheur selectionne la frquence de coupe de 1à10, le troisieme afficheur selectionne la longueur max de 20à99).
Ce qui donne si je fait la selection 30/4/42 que la machine coupera à 30, 34, 38, 42 puis reviendra à 30, 34...etc et realisera des boucles infini à ces valeurs.
1 switch poussoir, servant de "reset"
1 afficheur numerique à 4 chiffres, compteur de coupe.

coté entrée capteur,
une fourche optique mesure la course de l'entraineur de fil
le switch pédale de commande
un fin de course pour l'état d'ouverture de la pince coupante

en sortie,
relais commandant l'ouverture et fermeture de la pince coupante et entraineur.

voilà, grosso modo, la description de la bête..

Bonjour ducoinlucien

S'il n'y a qu'une fourche, cela veut dire que la roue qui entraîne le fil a une série de trous qui permet de mesurer la quantité de fil déroulé ?

Cordialement
jpbbricole

Quelles sont les sécurités prévues ?
La machine a-t-elle besoin d'un agrément "Ministère du Travail" ?

Le cas sera différent si tu es le seul à manœuvrer la machine que tu as conçue pour ton usage personnel, de celui où elle sera manœuvrée par un salarié ou simplement un ami.

Sympa la bête

Où rencontrez vous des soucis de programmation?

à jpbbricole, oui j'ai une roue avec des entailles, taillée dans un disque alu de disque dur SATA.
85 entailles au total car la course de mon entraineur développe par tour 85mm

à 68tjs, non, pas d'agrément de sécurité, c'est vraiment pour une activité artisanale perso et les risques sont plus dans les réactions de ressort des rouleaux de fil de fer aciérés qui peuvent vite t'éborgner quand tu déroule que la machine elle même.
Elle s'utilise en marche forcée pour engager le fil et après on s'occupe juste du bon déroulement de la bobine en gérant l'avalement du fil avec la pédale switch en mode auto.

à J-M-L, oui la bête est pas piquée des hannetons comme on dit, entièrement moulée sur la cuisse, fabriquée avec pas mal de récup, moteur de machine à laver, réserve d'air avec bouteille de gaz fibre, carcasse avec une vielle armoire électrique, etc..
toute la partie mécanique est assez fiable malgré l'apparence grosse bidouille.
Là où je rencontre un soucis avec la programmation c'est que je n'y connais vraiment rien, mon ami lui bien plus que moi, c'était son boulot en programmation ordi de bord sur véhicule chez PSA mais en pleine reconversion professionnelle il doit s'occuper de ces affaires qui sont pas simples et plus trop le temps pour des récréations.
il m'a fait un script prévus sur Arduino uno, mais comme on était à court de port d'entrée il avait trouvé sur des forums je pense la possibilité de passer par un serial.
de plus on avait des composant de fonction genre capteur de pression de cuve, dont on les avait foutu à gérer par le script alors que c'était pas utile, rendant le script plus complexe et bouffant des entrées.
Depuis je suis passé sur Arduino méga, donc plus de soucis de port, j'en ai de reste et tous les capteurs fonctionnel je les ai tous branchés en logique câblée, en série donc boucle fermée la machine avance, boucle ouverte la machine bouge pas et là un contrôle visuel permet de tout de suite voir ce qui ne va pas.
Donc tout est simplifié au max avec tout de même des fonctions sympa.
Mais même simple, pour moi c'est très compliqué, j'ai l'impression de devoir apprendre à parler un japonais couramment pour les besoins d'une semaine de vacance...c'est pas que c'est pas sympa le japonais, mais…
Alors je me retrouve en possession d'un script en cours de modif dont je comprends 4% de son contenu, dont je pense que il y a surement pas mal de chose à conserver, mais… là je suis en mode Champollion avec la perspective d'une somme de travail à abattre colossale alors que un initié y passera peut être juste quelques heures!
peut être je me trompe mais ...vraiment j'en sais rien, quand je lis des post sur ce Forum, j'ai quand même l'impression que y'a du level et que mon projet c'est pas la NASA tout de même.
je vous poste le sketch là où il en est .. :grimacing:

#include <ShiftRegister74HC595.h>

// >>>>> PIN pupitre <<<<<
// selecteur-modes
const int mode_PROG 2
const int mode_RUN 3
const int mode_SOFT 4
// reset
const int reset 5
// selecteur-valeurs
const int poussoir_selecteur_valeurs 6
const int rotatif_S1 7
const int rotatif_S2 8
// afficheurs-valeurs
const int afficheur_valeurs_DATA 9
const int afficheur_valeurs_LOAD 10
const int afficheur_valeurs_SCLK 11
// afficheur-compteur-coupes
const int afficheur_compteur_coupe_DATA 12
const int afficheur_compteur_coupe_LOAD 13
const int afficheur_compteur_coupe_SCLK 14

// >>>>> PIN entrees/sorties annexes <<<<<
// entrees
const int poussoir_pedale 15
const int fourche_optique 16
volatile int nbImpulsions = 0;
const int capteur_fermeture_pince 17
// sorties
const int fermeture_pince 18
const int ouverture_pince 19
const int avance_moteur_entraineur 20
// PIN non-occupees
const int NOT_USED 21>>53

// >>>>> CONSTANTES <<<<<
// constantes selecteur modes
const bool MODE_PROG = HIGH;
const bool MODE_RUN = HIGH;
const bool MODE_MARCHE FORCE = HIGH;
// constantes afficheur
const byte MIN_AFFICHEUR = 0;
const byte MAX_AFFICHEUR = 1;
const byte FREQ_AFFICHEUR = 2;
// constante poussoir reset
const bool reset = HIGH
// Constantes gestion avance moteur
const int FACTOR_CONVERT_IMPUL = 10;
const int LENGHT_OFFSET = 10; //10 impulsions inertie moteur
// constante poussoir-pedale
const bool poussoir_pedale = HIGH;
// constantes pince
const bool fermeture_pince = HIGH;
const bool ouverture_pince = HIGH;


// >>>>> VARIABLES <<<<<
// bouton rotatif variables gestion de front de signal
bool clkState  = LOW;
bool clkLast  = HIGH;
bool swState  = HIGH;
bool swLast  = HIGH;
boolean stateBP = false;
//variables de stockage MIN MAX FREQ
byte rotVal  = 0;
byte initParameter = 0;
byte consigne_MIN = 0;
byte consigne_FREQ = 0;
byte consigne_MAX = 0;
int impulsions_MIN = 0;
int impulsions_FREQ = 0;
int impulsions_MAX = 0;
int impulsions_MIN_HOLD = 0;
int impulsions_FREQ_HOLD = 0;
int impulsions_MAX_HOLD = 0;
int N_Segments = 0;
//bool bp_Pressed = true;

// <<<<< Creation objet de gestion des afficheurs 7 segments >>>>>
const int DIGITS 6 // gestion de 6 digits 7 segments

int value,digit1,digit2,digit3,digit4,digit5,digit6; 
uint8_t  numberB[] = {B11000000, //0
                      B11111001, //1 
                      B10100100, //2
                      B10110000, //3 
                      B10011001, //4
                      B10010010, //5
                      B10000010, //6 
                      B11111000, //7
                      B10000000, //8
                      B10010000, //9
                      B01111111 //.
                     };
int number=10;          


void setup() {
 Serial.begin(9600);
 Serial.println(F("Initialize System"));
 
// <<<<< Init Rotatifs reglage longueur frequence >>>>>
 pinMode(clkPin_S2,INPUT);
 pinMode(dtPin_S1,INPUT);
 pinMode(boutonPoussoir,INPUT_PULLUP);
 clkLast = digitalRead(clkPin_S2);
 
// <<<<< fourche optique >>>>>
 pinMode(EtatFourche, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(EtatFourche), decrementeImpulsion, RISING);
}

void loop() {
  // <<<<< Code execute en boucle infini >>>>>
 Serial.print("valeur capteur : ");
 byte capteurAndMode = readCapteurs();
 Serial.println(capteurAndMode, BIN);
 if ((capteurAndMode & MODE_SETUP) == MODE_SETUP)
     {
        readRotatif(initParameter, MODE_SETUP);
     } 
 else if ((capteurAndMode & MODE_RUN) == MODE_RUN)
      {
        if ((impulsions_MIN_HOLD != impulsions_MIN)||(impulsions_MAX_HOLD != impulsions_MAX)||(impulsions_FREQ_HOLD != impulsions_FREQ)){
            fixLenghtMAX();
            convertAndloadLenghtToPulse();
            Serial.println(F("Mode run"));
            delay(1000);
        }
        fowardAndCut();
        delay (500);
      }
}
// <<<<< Fonction Avance, condition pédale >>>>>
void fowardAndCut (){
   byte indexCoupe = 0;
   while (indexCoupe <= N_Segments){
      int impulseToDecrement = impulsions_MIN_HOLD + (impulsions_FREQ * indexCoupe);
      nbImpulsions = impulseToDecrement;
      while (nbImpulsions>0){
         byte capteurAndMode = readCapteurs();
         while (poussoir_pedale = HIGH);{
            digitalWrite(avance_moteur_entraineur, HIGH);
         }
      }
      delay (2000);
      coupe();
      indexCoupe++;
   }
}
// <<<<< Fonction coupe, condition pédale et pression >>>>>
void coupe (){
    byte Mode_run = readCapteurs();
    while (poussoir_pedale, HIGH);{ 
        digitalWrite(FERMETURE_PINCE, HIGH);
        delay (1000);
        digitalWrite(OUVERTURE_PINCE, HIGH);
    }
}

// <<<<< Fonction décrémente les impulsions de la roue optique >>>>> 
void decrementeImpulsion(){
    nbImpulsions--;
}

// <<<<< Acquisition des valeurs MIN MAX FREQ >>>>>

void readRotatif(int pParameter, int pMode) { /* function readRotary */
   int parameter = pParameter;
   while ((pMode & MODE_SETUP) == MODE_SETUP){
       //bp_Pressed = true;
       pMode = readCapteurs();
       clkState = digitalRead(clkPin_S2);
         if (clkLast != clkState && clkState == HIGH) {//rotary moving
           Serial.print("Parameter selected :  ");
           Serial.print(parameter);
           if (digitalRead(dtPin_S1) != clkState) {
                 if (parameter == MIN_AFFICHEUR){
                  consigne_MIN--;
                  rotVal = consigne_MIN;
                  if (rotVal<0){
                    rotVal=0;
                    affiche(parameter, rotVal);
                  } else {
                    affiche(parameter, rotVal);
                  }
                 } else if (parameter == MAX_AFFICHEUR){
                  consigne_MAX--;
                  rotVal = consigne_MAX;
                  if (rotVal<0){
                    rotVal=0;
                    affiche(parameter, rotVal);
                  } else {
                    affiche(parameter, rotVal);
                  }
                 }  else if (parameter == FREQ_AFFICHEUR){
                  consigne_FREQ--;
                  rotVal = consigne_FREQ;
                  if (rotVal<0){
                    rotVal=0;
                    affiche(parameter, rotVal);
                  } else {
                    affiche(parameter, rotVal);
                  }
                 }
            } else {
                if (parameter == MIN_AFFICHEUR){
                  consigne_MIN++;
                  rotVal = consigne_MIN;
                  if (rotVal>99){
                    rotVal=99;
                    affiche(parameter, rotVal);
                  } else {
                    affiche(parameter, rotVal);
                  }
               } else if (parameter == MAX_AFFICHEUR){
                  consigne_MAX++;
                  rotVal = consigne_MAX;
                  if (rotVal>99){
                    rotVal=99;
                    affiche(parameter, rotVal);
                  } else {
                    affiche(parameter, rotVal);
                  }
               }  else if (parameter == FREQ_AFFICHEUR){
                  consigne_FREQ++;
                  rotVal = consigne_FREQ;
                  if (rotVal>99){
                    rotVal=99;
                    affiche(parameter, rotVal);
                  } else {
                    affiche(parameter, rotVal);
                  }
               }
             }
           }
    //Serial.println(rotVal);
    clkLast = clkState;
    parameter = handleBpRotaParameter(parameter);
    delay(10);
    }
    //bp_Pressed = true;
  }

int handleBpRotaParameter(int pParameter){
 //bool statuToReturn = true;
// Serial.print("Begin handleBpRotaParameter pParameter");
// Serial.println(pParameter);
 int parameterToReturn = pParameter;
 swState = digitalRead(boutonPoussoir);
 if (swState == LOW && swLast == HIGH) {
   parameterToReturn = parameterToReturn+1;
   if (parameterToReturn > 2){
      Serial.print("parameterToReturn > 2 return 00");
      Serial.println(parameterToReturn);
      delay(200);
      return 0;
   }
//   Serial.print("Rotary pressed into handleBpRotaParameter");
//   Serial.println(parameterToReturn);
   delay(200);//debounce
   //statuToReturn = false;
   return parameterToReturn;
 }
 swLast = swState;
 rotVal = 0;
 //delay (50);
 return parameterToReturn;
}

// <<<<< Envoi les données de longueur en cm vers le numéro d'afficheur MIN MAX FREQ >>>>>
void affiche (int parameter, int pValue){
//  digit2=pValue % 10 ;
//  digit1=(pValue / 10) % 10 ;
//  uint8_t numberToPrint[]= {numberB[10],numberB[10],numberB[digit2],numberB[digit1]};
  if (parameter == MIN_AFFICHEUR){
    Serial.print("MIN affiche parameter:");
    Serial.println(parameter);
    digit2=pValue % 10 ;
    digit1=(pValue / 10) % 10 ;
    digit4=consigne_FREQ % 10 ;
    digit3=(consigne_FREQ / 10) % 10 ;
    digit6=consigne_MAX % 10 ;
    digit5=(consigne_MAX / 10) % 10 ;
    uint8_t numberToPrint[]= {numberB[digit6],numberB[digit5],numberB[digit4],numberB[digit3],numberB[digit2],numberB[digit1]};
    afficheur.setAll(numberToPrint);

  } else if (parameter == MAX_AFFICHEUR){
    Serial.print("MAX affiche parameter:");
    Serial.println(pValue);
    digit2=consigne_MIN % 10 ;
    digit1=(consigne_MIN / 10) % 10 ;
    digit4=pValue % 10 ;
    digit3=(pValue / 10) % 10 ;
    digit6=consigne_FREQ % 10 ;
    digit5=(consigne_FREQ / 10) % 10 ;
    uint8_t numberToPrint[]= {numberB[digit6],numberB[digit5],numberB[digit4],numberB[digit3],numberB[digit2],numberB[digit1]};
    afficheur.setAll(numberToPrint);
    
  } else if (parameter == FREQ_AFFICHEUR){
    Serial.print("FREQ affiche parameter:");
    Serial.println(parameter);
    digit2=consigne_MIN % 10 ;
    digit1=(consigne_MIN / 10) % 10 ;
    digit4=consigne_MAX % 10 ;
    digit3=(consigne_MAX / 10) % 10 ;
    digit6=pValue % 10 ;
    digit5=(pValue / 10) % 10 ;
    uint8_t numberToPrint[]= {numberB[digit6],numberB[digit5],numberB[digit4],numberB[digit3],numberB[digit2],numberB[digit1]};
    afficheur.setAll(numberToPrint);
  }
  digit1=0;
  digit2=0;
}
// <<<<< corrige la longueur MAX pour affichage seulement >>>>>
void fixLenghtMAX () {
  int segments = 0;
  int diff = consigne_MAX - consigne_MIN;
  Serial.print("Diff = ");
  Serial.println(diff);
  int modulo = diff*10%consigne_FREQ;
  Serial.print("modulo= ");
  Serial.println(modulo);
  if (modulo>0){
    segments = diff*10/consigne_FREQ;
//    Serial.print("nombre de segments = ");
//    Serial.println(segments);
  }
  N_Segments = segments+1;
  int maxFixed = consigne_MIN*10+((segments+1)*consigne_FREQ);
  affiche (MAX_AFFICHEUR, maxFixed/10);
}

// <<<<< Convertit et stock les longueurs en impulsions >>>>>
void convertAndloadLenghtToPulse () {
  impulsions_MIN = consigne_MIN*FACTOR_CONVERT_IMPUL;
  impulsions_FREQ = consigne_FREQ*FACTOR_CONVERT_IMPUL;
  impulsions_MAX = consigne_MAX*FACTOR_CONVERT_IMPUL;
  //    Serial.print("impulsions_MIN = ");
//    Serial.println(impulsions_MIN);
//    Serial.print("impulsions_FREQ = ");
//    Serial.println(impulsions_FREQ);
//    Serial.print("impulsions_MAX = ");
//    Serial.println(impulsions_MAX);
  impulsions_MIN_HOLD = impulsions_MIN;
  impulsions_FREQ_HOLD = impulsions_FREQ;
  impulsions_MAX_HOLD = impulsions_MAX;
}

vous pourriez nous faire un dessin du circuit ?

un dessin du circuit de cablage et des composant ?

Bonjour @ducoinlucien

un schéma , même à main levée , dans lequel les élements seraient sommairement représentés par des rectangles avec le nom de leurs entrées /sorties utilisées et les liaisons entre elles.

Plus un schéma de principe qu'un plan de câblage
A ce stade il n'est pas esseentiel de montrer tous les fils entre les sorties HC595 et afficheurs 7 segments, il s'agit de montrer la logique d'ensemble et la confronter avec celle qui transparait dans le programme.

ok, je poste çà dans la journée, en attendant, quelques photos de la bête :wink:

C'est un schéma fonctionnel global très utile. qui donne une bonne vue d'ensemble du système sur le plan matériel (hors alimentations en énérgie) !

Il pourrait être complété en donnant des vues un peu plus détaillées des liaisons entre certains sous-ensembles commepar exemple l'association Arduino + Pupitre de Commande (sans aller jusqu'a représenter tous les fils)

Comment sont alimentés les divers éléments ?

il doit manquer du code car ça ne peut pas compiler tel quel

vous avez la référence ? ils ont un 74HC595 embarqué ?

une approche serait de commencer à faire fonctionner les sous systèmes indépendamment pour s'assurer que vous avez tout ce qu'il faut pour piloter le système

un LCD serait sans doute plus simple pour gérer tout l'affichage

Changer le titre du sujet pourrait intéresser plus de candidats pour aider à mener à bien ce projet ...
Par exemple "Aide pour automatiser (programmer) une découpeuse de fil de fer maison".

Coté alimentation, effectivement j'ai pas précisé car j'ai pas jugé utile mais, alimentation en 8vcc pour l'Arduino méga via un transfo et pont de diode.
Je récupère une sortie en 5vcc de l'Arduino pour alimenter un bornier pour tous les petits composants sous 5vcc (fourche optique, switch pupitre, afficheur...).
Alimentation 24vcc pour le distributeur pneumatique, l'entraineur et son relais de puissance via un bon transfo et pont de diode également.
Les afficheur sont effectivement avec 74HC595 embarqué.
Entièrement d'accord avec toi J-M-L, l'idée de faire fonctionner les sous systeme indépendamment pour commencer.
Déjà avoir un sketch qui me fasse tourner l'encodeur rotatif et les afficheurs serait un bon bout de plombé.
Je vous mets un schéma des relations câblées pupitre/Arduino/Composants Satellites et vous donne en soirée l'organigramme du fonctionnement de la machine pour l'operateur en situation de travail.
Si je peux poster, étant tout neuf sur le Forum, Je suis bridé... :joy:
J'ai pas le permis qu'on me dit, pour aller vite..!

vous avez mis des capa pour éviter les rebonds sur les switch ?