INCLINAISON MOTORISÉE D'UN BANC DE MUSCULATION

Bonjour,

Dans le cadre de mon projet de science d'ingénieur mon groupe et moi-même aimerions automatiser au mieux un banc de musculation, une partie du projet est de rendre le dossier inclinable grâce à un moteur, l'angle d'inclinaison serait déterminé par un pupitre.

Pour ce faire, ma première idée était qu’on utilise un inclinomètre et que l'inclinomètre obtienne l'inclinaison et que celle-ci soit transformée en une variable appelée "Inclinaison_Actuelle" par exemple. Ensuite, l'utilisateur fixe une inclinaison qu'il souhaite et on en fait aussi une variable appelée "Inclinaison_Souhaitée" par exemple. Ensuite, en fonction de si "Inclinaison_Actuelle" < "Inclinaison_Souhaitée", le moteur tourne soit dans le sens des aiguilles d'une montre, soit dans le sens inverse jusqu'à ce que "Inclinaison_Actuelle" = "Inclinaison_Souhaitée".

Le problème est que je ne sais pas quel composants utiliser et comment je pourrais les coder…

Toute aide serait profondément appréciée !!

Bonne soirée!

Cette rubrique est réservée aux "Tutoriels et cours".
STP utilise le lien "Report to moderator" pour demander au modo de déplacer ton message dans le forum principal.

Je m'excuse et c'est fait!

En général pour mesurer un angle, on utilise un potentiomètre ou un codeur de position. C'est plus courant, c'est moins cher.

pour bien débuter avec l’arduino, un bon point de départ c’est de lire les tutos d’eskimon

Commencez par ça et regardez les potentiomètres

Ensuite faudra sans doute un ou deux vérins pour bouger le dossier. Il y a pleins de tutos sur les vérins

olivier_pecheux:
En général pour mesurer un angle, on utilise un potentiomètre ou un codeur de position. C'est plus courant, c'est moins cher.

Pourriez-vous expliquer comment l'encodeur rotatif fonctionnerait dans ce système, de la même façon que le potentiomètre?

Merci d'avance

Pour le potentiomètre rotatif vous le mettez de façon à ce que son axe corresponde à l'axe de rotation autour duquel le dossier tourne et vous solidarisez le bouton au dossier. La lecture de la résistance vous donne alors une représentation de l'angle autour de l'axe

Pour un encodeur rotatif quadratique c'est le même principe mais c'est moins pratique car vous n'avez pas une valeur absolue de position, juste de déplacement. C'est utilisable si vous avez donc un détecteur de fin de course. La calibration commence par bouger l'objet jusqu'au détecteur et ça devient la position 0. ensuite chaque "tick" sera un pas fait dans une direction

J-M-L:
pour bien débuter avec l’arduino, un bon point de départ c’est de lire les tutos d’eskimon

Commencez par ça et regardez les potentiomètres

Ensuite faudra sans doute un ou deux vérins pour bouger le dossier. Il y a pleins de tutos sur les vérins

Ca marche! Mon co-équipier s'occupe des vérins :slight_smile:

Notez que si vous utilisez des vérins (Actionneur Linéaire) leur position donnera l'angle aussi. Certains ont le circuit de mesure intégré (par exemple celui ci) ou alors juste un Interrupteur de fin de course

Bonjour,

Depuis mon problème a changé, à cause de la pandemie, je vais faire une simulation sur Tinkercad comme ça j'aurais quelque chose à présenter lors de ma soutenance orale.

Pour l'instant je pensais utiliser un Pavé Numérique, un écran LCD (16x2), un Moteur CC et un Pont en H (L293D).

Je voulais faire en sorte qu'on puisse entrer une inclinaison voulue (de -10° à 20°) grâce au Pavé Numérique, cette inclinaison apparaîtrait à la première ligne de l'écran. Sur la deuxième ligne, j'aurais d'affiché, une variable qui imiterait l'inclinaison du banc qui serait à 0° pour commencer. Comme j'ai déjà dit dans mon premier post, en fonction de si l'inclinaison souhaitée est inférieure ou supérieure. Le moteur changerait de sens ou non et après un nombre de secondes (il faut 2s pour aller de -10° à 20°, ce qui fait 15°/s ou 15^-1s/°), le moteur s'arrêterait.

Je sais comment programmer le changement de sens du moteur, je connais les bases du codage de l'écran mais je ne sais pas comment programmer l'entrée de l'inclinaison voulue. Donc je voulais savoir s'il était possible de m'aider avec le code si possible? Toute aide serait énormément appréciée!

Bonne journée à vous

J'ai un petit tuto pour gérer un flux asynchrone genre port Série ou keypad

vous y verrez un bout de code pour attendre une saisie sur le clavier.

ensuite il vous faudra une machine à état --> cf mon autre tuto éventuellement

J'ai sûrement mal compris le tuto mais j'aimerais faire en sorte que la valeur saisie sur le pavé numérique se transforme en variable pour que je puisse faire des tests logiques pour ensuite faire mon changement d'état.

Je vous remercie pour votre patience et votre aide biensûr!

avec ce code qui est dans le tuto (j'ai juste enlevé les lignes qui parlent du mot de passe) vous avez tout ce qu'il faut dans la loop() pour recevoir ce que l'utilisateur a tapé avec un caractère de fin '#'

#include <Keypad.h>

const byte ROWS = 4; //4 rangées
const byte COLS = 4; //4 colonnes

char keys[ROWS][COLS] = {   //les symboles, déclarés par leur code ASCII dans le tableau à 2 dimension
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = { 34, 36, 38, 40 }; // On connecte ROW0, ROW1, ROW2 and ROW3 à ces pins (je suis sur un MEGA)
byte colPins[COLS] = {41, 39, 37, 35}; // On connecte  COL0, COL1, COL2 and COL3 à ces pins (je suis sur un MEGA)

Keypad membraneKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);  //On initialise une instance de la classe Keypad

const byte tailleMessageMax = 50;
char message[tailleMessageMax + 1]; // +1 car on doit avoir un caractère de fin de chaîne en C, le '\0'

const char marqueurDeFin = '#';

boolean ecouter()
{
  static byte indexMessage = 0; // static pour se souvenir de cette variable entre 2 appels consécutifs. initialisée qu'une seule fois.
  boolean messageEnCours = true;

  char c = membraneKeypad.getKey();
  if (c != NO_KEY) {
    if (c == marqueurDeFin) {
      message[indexMessage] = '\0'; // on termine la c-string
      indexMessage = 0; // on se remet au début pour la prochaine fois
      messageEnCours = false;
    } else if (indexMessage <= tailleMessageMax - 1) message[indexMessage++] = (char) c; // on stocke le caractère et on passe à la case suivante
  }
  return messageEnCours;
}

void setup() {
  Serial.begin(115200);
}
void loop() {
  if (! ecouter()) {

    // ICI ON A DANS message CE QUE L'UTILISATEUR A TAPÉ

  }
  // ici on peut faire autre chose
}

-->

if (! ecouter()) {

    // ICI ON A DANS message CE QUE L'UTILISATEUR A TAPÉ

  }

la variable message est une cString (un tableau de char terminé par un caractère nul) et vous pouvez jouer avec en utilisant les fonctions des bibliothèques standard: stdlib.h et string.h.

par exemple si vous savez que ce qui est tapé est un nombre alors

long valeur = atol(message); // http://www.cplusplus.com/reference/cstdlib/atol/

(ça retournera 0 si message ne contient pas un nombre, donc attention vous ne pourrez pas vraiment savoir si l'utilisateur a tapé 0 ou une erreur, pour ça il faut tester les premier caractère à la main).

Ce code n'est pas adapté pour un écran LCD mais je suppose que ça ne serait pas très différent non?

DruideZeus:
Ce code n'est pas adapté pour un écran LCD mais je suppose que ça ne serait pas très différent non?

ben suffit de rajouter du code pour LCD en plus et au lieu d'écrire sur Serial, vous écrivez sur le LCD...

on va pas tout vous faire non plus... :confused: :o

Oui c'est vrai, peut-on entrer des valeurs négatives aussi?

À vous de définir les caractères du clavier pour former un nombre

Pour l'instant mon code ressemble à ceci:

#include <LiquidCrystal.h>   
#include <Keypad.h>

const byte ROWS = 4; //4 rangées
const byte COLS = 4; //4 colonnes
int x = 0;
char keys[ROWS][COLS] = {   //les symboles, déclarés par leur code ASCII dans le tableau à 2 dimension
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = { 7, 6, 5, 4 }; // On connecte ROW0, ROW1, ROW2 and ROW3 à ces pins (je suis sur un MEGA)
byte colPins[COLS] = {3, 2, 1, 0}; // On connecte  COL0, COL1, COL2 and COL3 à ces pins (je suis sur un MEGA)

Keypad membraneKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);  //On initialise une instance de la classe Keypad
LiquidCrystal lcd(8,9,10,11,12,13);
const byte tailleMessageMax = 3;
char message[tailleMessageMax + 1]; // +1 car on doit avoir un caractère de fin de chaîne en C, le '\0'

const char marqueurDeFin = '#';

void test()
{
  if (x > 5) {
  digitalWrite(A1, LOW);
    digitalWrite(A0, HIGH);}
  else { digitalWrite(A1, HIGH);
  digitalWrite(A0, LOW);}
}

boolean ecouter()
{
  static byte indexMessage = 0; // static pour se souvenir de cette variable entre 2 appels consécutifs. initialisée qu'une seule fois.
  boolean messageEnCours = true;
  
int x = (int)message;

  while (Serial.available() && messageEnCours) {
    int c = Serial.read();
    if (c != -1) {
      lcd.clear();  
      lcd.print(F("\t[")); lcd.print((char) c); lcd.println(F("]"));
      switch (c) {
        case marqueurDeFin:
          lcd.println(F("Fin de chaine"));
          message[indexMessage] = '\0'; // on termine la c-string
          indexMessage = 0; // on se remet au début pour la prochaine fois
          messageEnCours = false;
          break;
        default:
          if (indexMessage <= tailleMessageMax - 1) message[indexMessage++] = (char) c; // on stocke le caractère et on passe à la case suivante
          else lcd.println(F("j'ignore!"));
          break;
      }
    }
  }
  return messageEnCours;
}


void setup() {
  Serial.begin(115200);
  lcd.begin(16,2);
  pinMode(A0,OUTPUT); 
  pinMode(A1,OUTPUT);            
  lcd.clear();                             
}
void loop() {
  if (! ecouter()) {
    // on a reçu le marqueur de fin
    lcd.clear();
    lcd.print(F("Inclinaison: ")); lcd.print(message);
    lcd.autoscroll();
  }
  test();
}

Mais je n'arrive pas à faire en sorte que void test() fonctionne...

void test()
{
  if (x > 5) {
  digitalWrite(A1, LOW);
    digitalWrite(A0, HIGH);}
  else { digitalWrite(A1, HIGH);
  digitalWrite(A0, LOW);}
}

J'ai essayé d'utiliser la variable (message) mais visiblement je me trompe dans ma démarche.

byte colPins[COLS] = {3, 2, 1, 0}; // On connecte  COL0, COL1, COL2 and COL3 à ces pins (je suis sur un MEGA)

==> n'utilisez pas les pins 0 et 1, elles correspondent au port Serial - connecté à votre PC par USB (et changez les commentaires si vous n'est pas sur un MEGA)

Notez que rien ne vous empêche de mettre d'autres caractères dans la table

char keys[ROWS][COLS] = {   //les symboles, déclarés par leur code ASCII dans le tableau à 2 dimension
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

que ceux qui sont dessiné sur les touches. Par exemple si vous vouliez que 'A' soit le symbole '-' pour taper un nombre négatif, mettez

char keys[ROWS][COLS] = {   //les symboles, déclarés par leur code ASCII dans le tableau à 2 dimension
  {'1', '2', '3', '-'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

et collez éventuellement une gommette sur votre clavier pour le savoir. Comme cela message contiendra directement un nombre. et vous pouvez modifier la fonction de lecture pour ignorer B,C,D et * par exemple ou leur donner un autre rôle

Demandez vous si votre fonction test doit elle être appelée en permanence ou uniquement quand une nouvelle entrée est réalisée --> ça influe sur là ou vous placez l'appel.

Pour lire dans le if (!ecouter()) {...} un entier vous pourriez avoir une variable globale long derniereValeurLue;et faire   derniereValeurLue = atol(message); // transforme la chaîne de caractère du message en nombre signé

C'est étrange car j'ai changé les pins du pavé numérique mais il ne lit toujours pas les caractères saisis (uniquement en serial) et la fonction test() et ne met pas à jour la variable "x" (elle reste identique à celle que j'ai initialisée).