Go Down

Topic: Projet Bar a Cocktail fonctionnel mais .... (Read 1 time) previous topic - next topic

eden99

May 18, 2017, 11:05 pm Last Edit: May 18, 2017, 11:23 pm by eden99
Bonsoir a tous,

Ci apres vous trouverez le code qui me permet de controler un bar a cocktail Via Bluetooth. Shema joint également.

Celui ci fonctionne mais j aurais souhaite, grace a votre aide, en ameliorer le concept.
- Je commande donc un moteur DC qui avance ou recule le chariot -donc le verre- sous les bouteilles
- Ensuite je déclenche (ou non) le servo moteur qui appui sur les bouchons doseurs.
- Et enfin, via les 4 relais, je commande les mini-pompes (pour les boissons gazeuses)

Je voudrais pouvoir ajouter un capteur de distance ultrasons afin que les ordres transmis via Bluetooth ne  s exécute que si et seulement si un verre est positionné sur son emplacement de départ (le chariot).

Et pourquoi ne pas y ajouter 2 interrupteurs de fin de course de chaque coté du chariot.

N ayant jamais eu a intégrer de tels capteurs, j aimerais pouvoir bénéficier de vos lumières. un peu d aide serait bienvenue.


Code: [Select]

#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial Bluetooth(10, 11); // RX | TX

Servo servo;

int pompe1 = 3;    // les 4 pompes déclenchées par les relais
int pompe2 = 4;
int pompe3 = 5;
int pompe4 = 6;
int state = 0;

int servoPin = 7;
int servoAngle = 0;   // Position du servo moteur en degres

int Moteur1_Retour = 8;
int Moteur1_Avance = 9;

void setup() {
  Serial.begin(9600);

  pinMode(pompe1,OUTPUT);
  pinMode(pompe2,OUTPUT);
  pinMode(pompe3,OUTPUT);

  pinMode(Moteur1_Avance, OUTPUT);
  pinMode(Moteur1_Retour, OUTPUT);

  servo.attach(servoPin);
}

void loop() {

  if(Serial.available() > 0)
  {
    char data;
    data = Serial.read();
    Serial.write(Serial.read());

    switch (data)      // Delai et sens a revoir mais fonctionnel
    {
      case '1': // Whisky Coca
        digitalWrite(Moteur1_Avance, HIGH);
        delay(4000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Avance, HIGH);
        delay(5000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Retour, HIGH);
        delay(3000);
        digitalWrite(Moteur1_Retour, LOW);
        digitalWrite(pompe1, HIGH);
        delay(5000);
        digitalWrite(pompe1, LOW);
        break;
      case '2': // Vodka Orange
         digitalWrite(Moteur1_Avance, HIGH);
        delay(3000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Avance, HIGH);
        delay(5000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Retour, HIGH);
        delay(3000);
        digitalWrite(Moteur1_Retour, LOW);
        digitalWrite(pompe1, HIGH);
        delay(5000);
        digitalWrite(pompe1, LOW);
        break;
      case '3': // Rhum Coca
         digitalWrite(Moteur1_Avance, HIGH);
        delay(6000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Avance, HIGH);
        delay(5000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Retour, HIGH);
        delay(7000);
        digitalWrite(Moteur1_Retour, LOW);
        digitalWrite(pompe1, HIGH);
        delay(5000);
        digitalWrite(pompe1, LOW);
        break;
      case '4': //Pastis par temps bleu
        digitalWrite(Moteur1_Avance, HIGH);
        delay(5000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Avance, HIGH);
        delay(5000);
        digitalWrite(Moteur1_Avance, LOW);
        servo.write(45);
        delay(2500);
        servo.write(165);
        delay(500);
        digitalWrite(Moteur1_Retour, HIGH);
        delay(3000);
        digitalWrite(Moteur1_Retour, LOW);
        digitalWrite(pompe1, HIGH);
        delay(5000);
        digitalWrite(pompe1, LOW);
        break;
      case '5': // Coca Cola
        digitalWrite(Moteur1_Avance, HIGH);
        delay(5000);
        digitalWrite(Moteur1_Avance, LOW);
        delay(500);
        digitalWrite(pompe1, HIGH);
        delay(5000);
        digitalWrite(pompe1, LOW);
        break;
      case '6': // Jus d'Orange
        digitalWrite(Moteur1_Avance, HIGH);
        delay(5000);
        digitalWrite(Moteur1_Avance, LOW);
        delay(500);
        digitalWrite(pompe1, HIGH);
        delay(5000);
        digitalWrite(pompe1, LOW);
        break;
      default: //Si Bluetooth ne recoit aucune valeur, mets le moteur en OFF
        digitalWrite(Moteur1_Avance, LOW);
        digitalWrite(Moteur1_Avance, LOW);
        digitalWrite(Moteur1_Retour, LOW);
        digitalWrite(Moteur1_Retour, LOW);
    }
  }
}



J-M-L

Rigolo votre projet - envoyez nous une photo du truc fonctionnel ;)

Pour le moment votre code est plein de delay() ce qui est bloquant. si vous voulez utiliser des interrupteurs de fin de course ou des système de détection, il va falloir modéliser différemment votre code de façon à ce que la boucle tourne en permanence et teste des conditions puis prenne les décisions qui conviennent.

c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

eden99

Bonjour,
Oui je suis certain que ca doit etre largement optimisable.
Je mettrais des photos du tout dans "projets finis", quand j aurais finis de le monter, pour le moment j attends encore quelques pièces .
J ai encore quelques interrogations, notamment sur les "delay" dont vous parlez. si ma courroie ne se dérègle pas, par exemple a cause du poids du verre qui se rempli, les délais de traction du chariot sont bons, sinon il va me falloir des capteur de proximité qui auront pour fonction d arrêter le chariot pile sous la bouteille désiré .
On verra a l'usage ... je manquerais pas d y revenir ici.
En tout cas, merci pour le lien, je vais y regarder de près.

J-M-L

le problème de delay() c'est qu'une fois appelé vous ne pouvez pas vérifier autre chose, l'appel est bloquant. vous ne pouvez pas dire

Tant Que (delay(5000) ET PAS "sous la bouteille") alors faire bouger le verre

Pour cela vous pouvez envisager de faire une fonction attente() un peu plus perso (en utilisant millis() ) qui n'est pas bloquante mais qui vous retourne un booléen pour vous dire si le délai est expiré ou pas. Par exemple regardez le code de la réponse 5 de ce post
Code: [Select]
/*
  non blocking delay
  In:
    duration of delay
  Returns:
    false if delay is in progress, else true
*/
bool waitALittle(unsigned long duration)
{
  static unsigned long startTime = 0;

  // if no start time set, 'start' the delay
  if (startTime == 0)
  {
    startTime = millis();
    return false;
  }

  // check if delay has lapsed
  if (millis() - startTime >= duration)
  {
    startTime = 0;
    return true;
  }

  return false;
}
(source de @sterretje)

Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

eden99

Bonsoir,
Oui l idee me semble pas mal mais je ne suis pas sur de maitriser le(s) variable(s).
Une autre idee, peut etre, serait d utiliser un capteur de distance sr-04 , on pourrais ainsi arreter le chariot lorsque celui ci se trouve a tel ou tel distance .... qui correspondrait pile a l emplacement sous la bouteille !
De plus, il n y aurait plus besoin d interrupteur de fin de course . la chariot pourrait s arreter au bon endroit .
J ai conscience qu on ne parlerait plus de délai de course du chariot mais simplement de distance en cms depuis le capteur sr-04.

Qu en dites vous ?


J-M-L

Oui à essayer - il faudra que le SR-04 ait une vue bien dégagée
Comment est le montage physique du charriot ? Vous avez un rail de guidage ? En plaçant des petits contacteurs au niveau de chaque bouteille et un au bout rend switch) ça sera sans doute plus précis
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

eden99

#6
May 24, 2017, 04:15 am Last Edit: May 24, 2017, 04:21 am by eden99
Bonsoir,
Oui, c est bien un rail de guidage.
Je poste un photo promis des que j ai termine de le monter.
A quels types de contacteur pensez vous ?

En attendant, j ai modifier le code pour y joindre le SR04 . Ca me permet d'oter bon nombre de variable "relay",
c est précis également. Mais je ne le saurais qu une fois que le verre se remplira physiquement.

Code: [Select]

case '1':                                                         //                         Whisky Coca
     if ( distance = 100)                         // Enclenche le chariot si celui ci est sur son emplacement de depart
       digitalWrite(Motor_A_Forward, HIGH);                
       if ( distance = 50)                                 // Arrete le chariot a 50 cm du capteur
       digitalWrite(Motor_A_Forward, LOW);                    
       servo.write(45);                                  
       delay(2500);
       servo.write(165);                                    // Declenche le bouchon doseur grace au servo moteur  
       digitalWrite(Motor_A_Forward, HIGH);                    
       if ( distance = 20)                                // Arrete le chariot a 20 cm du capteur
       digitalWrite(Pompe1, HIGH);
       delay(5000);
       digitalWrite(Pompe1, LOW);                     // Declenche la pompe N1  
       digitalWrite(Motor_A_Forward, LOW);
       delay(500);
       digitalWrite(Motor_A_Reverse, HIGH);      // Retour du chariot a son emplacement de depart
       if ( distance = 100)
       digitalWrite(Motor_A_Reverse, LOW);
       break;





J-M-L

#7
May 24, 2017, 05:30 am Last Edit: May 24, 2017, 08:52 am by J-M-L
Attention il y a de multiple soucis avec ce code

- il faut '==' au lieu de '=' pour tester une égalité, sinon vous faites une affectation et là vous verrez que plus rien ne va fonctionner...

- il faut des accolades {} autour des instructions à  exécuter si le 'if' est vrai
- vous ne pouvez pas utiliser de delay() et ensuite tester la position une seule fois, il faut enlever le delay() et mettre une boucle qui lit la position et tant qu'elle n'est pas bonne le moteur continue
- pour tester la position vaut mieux un intervalle if (d >= 49 && d <= 51) {...} par exemple car vous n'êtes pas sûr d'arriver pile au bon endroit (50 tout rond) et si vous le dépassez le moteur va alors continuer sans fin

Côté testeur jetez un œil à des "Interrupteurs Fin de Course a Roulette" ou alors "Interrupteur Fin de Course a Levier long" (que vous courberez un peu pour qu'il n'accroche pas le charriot et le laisse passer dans les 2 sens) sur eBay ou votre vendeur favori

Autre option sans contact un détecteur infrarouge soit sous forme de U (genre LM393) et vous faites passer un morceau de votre charriot entre les branches de U ou alors un Module de capteur infrarouge d'évitement d'obstacles qui par reflection sur le charriot sera capable de dire s'il est devant le module

Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

eden99

#8
May 24, 2017, 11:35 pm Last Edit: May 24, 2017, 11:43 pm by eden99
Ok merci des ces précieux conseils.

Pour les rupteurs fin de course, j avais un peu anticipé et commander des 'OOTDTY' , mais je crois bien, en effet, que ceux a roulettes seraient plus judicieux.
Je verrais pour les intégrer au code quand je les aurais recu.

Tant que je n ai pas recu le chariot definitif pour test, je suis un peu dans l expectative. Mais j en apprends un peu plus chaque jour, donc merci encore pour l aide précieuse.

En attendant je tentes de modifier le codes en fonction des vos dernières indications.

A suivre ...

J-M-L

Il faudra restructurer le code sous forme de machine à état si vous mettez plein de capteurs et actionneurs - cf mon tuto éventuellement la dessus
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

eden99

Bon, en essayant d'intégrer vos remarques ;

   
Code: [Select]

case '1': //                         Whisky Coca
     if ( distance >= 99 && distance <= 101)  {                      
       digitalWrite(Motor_A_Forward, HIGH);   }              
       if ( distance >= 49 && distance <= 51)  {                            
       digitalWrite(Motor_A_Forward, LOW);                    
       servo.write(45);                                  
       delay(2500);
       servo.write(165);                              
       digitalWrite(Motor_A_Forward, HIGH);   }                  
       if ( distance >= 19 && distance <= 21) {                        
       digitalWrite(Pompe1, HIGH);
       delay(5000);
       digitalWrite(Pompe1, LOW);                        
       digitalWrite(Motor_A_Forward, LOW);
       delay(500);
       digitalWrite(Motor_A_Reverse, HIGH);}
       if ( distance <= 100)  {
       digitalWrite(Motor_A_Reverse, LOW);}
       break;  

  

Quant a ceci :

"- vous ne pouvez pas utiliser de delay() et ensuite tester la position une seule fois, il faut enlever le delay() et mettre une boucle qui lit la position et tant qu'elle n'est pas bonne le moteur continue "

je ne comprends pas quoi ni comment faire.

ensuite, concernant le code sous forme de machine a etat, j y travailles. meme si je ne suis pas sur de bien suivre.

J-M-L

Avec un bout de code isolé impossible de commenter vraiment ? Est-ce dans la loop() et va être appelé automatiquement plein de fois ?

Sinon ou distance est-elle calculée et mise à jour pendant que le moteur bouge ?
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

eden99

Bonsoir a Tous.
Et pardon de ne pas être revenu plus tot.
Donc comme promis, voici une photo du bar quasiment fini, en tous cas fonctionnel même si sur cette photo, il manque les valves pour les pompes fixées a l arriere ainsi que le servo moteur fixé sur le chariot, demontés pour le moment, pour fignoler un peu le look, passer un coup de vernis etc ...

Donc oui, ca fonctionne comme initialement prevu, mais avec le temps et le nombres d ordres lancés, mon chariot finit toujours par se décaler au fur et a mesure de la soiree, d abord de quelques mm puis de quelques cm.

J ai donc teste le capteur a Ultra son SR04, mais celui ci s avere trop peu efficace lorsque l on dépasse les 20/30 cm, mon chariot va plus vite que la vitesse du "ping".

La deuxieme tentative, pour pouvoir arreter le chariot a son emplacement de depart (lors du retour) , est donc de monter 2 rupteurs fin de course( un de chaque coté). J ai donc tenté de les integrer au code.... mais je dois faire une erreur quelques part car ca ne fonctionne pas.

Ci apres,voici le code 'version light', si quelqu un pouvait me dire ou je me trompes, ca serait top.


Code: [Select]
// J ajoutes 2 capteurs fin de course

#include <SoftwareSerial.h>
#include <Servo.h>

Servo servo;

int Pompe1 = 8;
int Pompe2 = 9;
int Pompe3 = 10;
int Pompe4 = 11;
int state = 0;

const int button1 = 5;             
const int button2 = 6;
int buttonState1 = 0;              // variable for reading the pushbutton1 status
int buttonState2 = 0;              // variable for reading the pushbutton2 status             

int servoPin = 7;
int servoAngle = 0;   // Position du servo moteur en degres

int Motor_A_Forward = 3;
int Motor_A_Reverse = 4;

void setup() {

  Serial.begin(9600);
 
  servo.attach(servoPin);
 
  pinMode(Motor_A_Reverse, OUTPUT);
  pinMode(Motor_A_Forward, OUTPUT);

  pinMode(Pompe1,OUTPUT);
  pinMode(Pompe2,OUTPUT);
  pinMode(Pompe3,OUTPUT);
  pinMode(Pompe4,OUTPUT);

  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);

}

void loop() {

  if(Serial.available() > 0)
  {
    char data;
    data = Serial.read();
    Serial.write(Serial.read());

    switch (data)
    {
      case '1': //                             5Whisky 20Coca
        digitalWrite(Motor_A_Forward, HIGH);
        delay(1000);
        digitalWrite(Motor_A_Forward, LOW);                // Avance le chariot vers bouteille de Whisky
       
        servo.write(45);
        delay(2500);
        servo.write(165);                                // Declenche le bouchon doseur grace au servo moteur
       
        digitalWrite(Motor_A_Forward, HIGH);
        delay(1000);
        digitalWrite(Motor_A_Forward, LOW);                // Avance le chariot vers  la bouteille de Coca
       
        digitalWrite(Pompe1, HIGH);
        delay(2000);
        digitalWrite(Pompe1, LOW);                       // Declenche la pompe N1 pendant 5 secondes


        if (buttonState1 == LOW) {                           // Revient a la position de depart
        digitalWrite(Motor_A_Reverse, LOW);             // C EST ICI QUE CA NE FONCTIONNE PAS
        delay (500);                                                 // RUPTEUR INOPERANT
        digitalWrite(Motor_A_Reverse, HIGH);
        }
        break;
       
       
      default: //Si le module bluetooth ne recoit aucune valeur, tout mettre en OFF
     
        digitalWrite(Motor_A_Reverse, LOW);
        digitalWrite(Motor_A_Forward, LOW);
         pinMode(Pompe1,OUTPUT);
         pinMode(Pompe2,OUTPUT);
         pinMode(Pompe3,OUTPUT);
         pinMode(Pompe4,OUTPUT);
    }
  }
}



J-M-L

Bonsoir

Le post 9 est toujours d'actualité... joli montage sinon !
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

eden99

Bsr, JML l insomniaque, j avais promis donc ....
je ferais une petite video pour monter le tout, y compris l appli que j ai fait sous android (capture ecran ci apres).
et pour sur ca ira dans projet fini des que ce sera peaufiner.
D ailleurs si ca interesse quelqu un, je laisserai l appli en telechargement libre également.

Et crois moi, j essai de m inspirer de ton propre montage mais y a des trucs que je comprends pas.
et pourtant je fais des efforts !

Go Up