Distributeur de nourritture et gestion de l'eau pour chat-licorne

Bonjour à toutes et à tous !

OUi, je suis nouveaux sur le forum ! et je me plonge tel le grand bleu dans l'univers Arduino.

Mon équipement :
un Uno rev 3
un motorshield 2.3
un lcd adafruit 772.
un 1307

mon projet :

réaliser un distributeur de nourriture ibspiré de [DIY] Réalisation d'un cat feeder contrôlé par Arduino

avec un menu permettant :
augmenter ou réduire la quantité de croquettes distribuées par jour (la RATION)
déterminer le nombre de Repas (8, 10 et 12 repas, soit ration /8 10 ou 12) et déduire le moment des repas (intervalle régulier).

avec un détecteur de présence enclencher la pompe à eau ( ça c'est assez simple, je crois...)

je pensais faire dans le simple en prenant tout le matériel en I2C (ahahaha...)

je découvre que plus c'est simple en électro, plus c'est complexe en progra, et réciproquement...

Voici le code (inspiré et tripatouillé, donc à mon avis, c'est sale...)

il n'y a pas encore la pompe à eau mais les principe sont là.
faire varier la vitesse des moteurs pour la quantité de croquette..
et pour le timer, je cherche avec millis mais j’ai des doutes ( et encore plus d'ignorance...)

bonsoir
pour un chat, chien ou … , c’est un problème assez trivial.
Par contre pour les licornes , il faut bien prendre en compte l’influence de leur longue corne, ces connes de licornes :grin: ayant une fâcheuse tendance a ne pas avoir une grande aptitude à une excellente proprioception…
8)

trivial, tu es rude avec mes soucis ^^
j’ai pas eu le temps de poster le code, ne riez pas trop !
et en fait il st trop long… mauvais augure ! donc pj!

menuwork.ino (13.7 KB)

Hum... arrete moi si je me tompe mais ta licorne ton chat n'aura pas à manger,
il ne me semble pas avoir vu de déclenchement de la ration suivant le temps/heure/jour,
tu est obligé de le faire manuellement c'est bien ça ?

Vaarai:
Hum... arrete moi si je me tompe mais ta licorne ton chat n'aura pas à manger,
il ne me semble pas avoir vu de déclenchement de la ration suivant le temps/heure/jour,
tu est obligé de le faire manuellement c'est bien ça ?

En effet!
le menu est réalisé, et semble fonctionnel ( avec du bug!)
les déclencheur moteur sont en cours et en même temps je réfléchi et potasse la fonction millis.

si je déclare un timer dans le void repas1, va-t-ils se déclencher régulièrement ou juste à la sélection du void..
et je crains donc de devoir modifier la structure de tout le menu pour intégrer millis.

Je sens que la taille du prog est excessive vu ce qu'il réalise, et je crains qu'avec les autre fonctions ça fasse ramer le uno?

Bonjour , tu as ce système qui fonctionne :

ARTNOW:
Bonjour , tu as ce système qui fonctionne :

http://forum.arduino.cc/index.php?topic=354328.0

Bonjour Artnow, ravi de ta présence !
ton post et ta vidéo m'ont pas mal inspiré lors de ma recherche, belle compétences !
j'ai préféré le système avec vis d’Archimède et moteur continu, j'ai trouvé qu'il y avait moins de contraintes mécanique, et surtout moins complexe à réalisé surtout pour la partie tringlerie pour laquelle je n'ai pas le niveau !
pour la partie alarme, vu que le menu propose 3 setup différent je pense plutôt axé sur des intervalles millis, qui seront moins long à encoder et je pense plus performant, qu'en dis tu ?

Petits conseils pratiques:

  • évite les “goto”, ici cela passe car tu redirige juste en dessous (d’ailleurs pk ne pas y intégrer dans le
    case ?) mais ça a tendance à rendre les programmes illisible et à générer des bug ^^

  • Cette partie du code est récurrente:

 DateTime now = RTC.now();
  Wire.beginTransmission(0x68);   // Accède au RTC I2C d'adresse 0x68.
  Wire.write(0x03);               // Pointe le registre du dayOfWeek (0x03).
  Wire.requestFrom(0x68, 1);      // Demande de reception d'un octet depuis registre (0x03).
  byte dayOfWeek = Wire.read();   // Stocke la valeur reçue.
  Wire.endTransmission();

  lcd.clear();
  lcd.print(tableauDesJours[dayOfWeek ]);
  lcd.print(" ");
  lcd.print (now.day() / 10, DEC);
  lcd.print (now.day() % 10, DEC);
  lcd.print("/");
  lcd.print (now.month() / 10, DEC);
  lcd.print (now.month() % 10, DEC);
  lcd.print(' ');
  lcd.print (now.hour() / 10, DEC);
  lcd.print (now.hour() % 10, DEC);
  lcd.print(':');
  lcd.print(now.minute() / 10, DEC);
  lcd.print(now.minute() % 10, DEC); // print a simple message

Tu pourrait la mettre dans une fonction et l’appeler au lieu du copy/paste fait ici.

  • Cela relève de l’optimisation mais toujours dans cette partie du code, autant d’accès au bus juste
    pour deux ou trois caractère à la fois cela ralentie le bus et l’arduino.
    Essaie si tu veux de créer un “objet” String (Objet sur arduino ? :o), d’y mettre une ligne complète de
    l’écran et de l’envoyer en une seule fois.
    (présentation de l’objet String)

menuwork_1.ino (7.07 KB)

menuwork_1.ino (7.07 KB)

elyo33:
Bonjour Artnow, ravi de ta présence !
ton post et ta vidéo m'ont pas mal inspiré lors de ma recherche, belle compétences !
j'ai préféré le système avec vis d’Archimède et moteur continu, j'ai trouvé qu'il y avait moins de contraintes mécanique, et surtout moins complexe à réalisé surtout pour la partie tringlerie pour laquelle je n'ai pas le niveau !
pour la partie alarme, vu que le menu propose 3 setup différent je pense plutôt axé sur des intervalles millis, qui seront moins long à encoder et je pense plus performant, qu'en dis tu ?

Bonjour , elyo33 pas de soucis , la vis sans fin à fait ses preuves , personnellement je préfère la précision concernant les horaires de distribution , quand ton projet fonctionnera , publie le en projet fini ,c'est toujours sympas pour les arduinistes d'apprendre en consultant les autres projets . bon courage

Vaarai:
Petits conseils pratiques:

  • évite les “goto”, ici cela passe car tu redirige juste en dessous (d’ailleurs pk ne pas y intégrer dans le
    case ?) mais ça a tendance à rendre les programmes illisible et à générer des bug ^^

  • Cette partie du code est récurrente:

 DateTime now = RTC.now();

Wire.beginTransmission(0x68);   // Accède au RTC I2C d’adresse 0x68.
 Wire.write(0x03);               // Pointe le registre du dayOfWeek (0x03).
 Wire.requestFrom(0x68, 1);      // Demande de reception d’un octet depuis registre (0x03).
 byte dayOfWeek = Wire.read();   // Stocke la valeur reçue.
 Wire.endTransmission();

lcd.clear();
 lcd.print(tableauDesJours[dayOfWeek ]);
 lcd.print(" “);
 lcd.print (now.day() / 10, DEC);
 lcd.print (now.day() % 10, DEC);
 lcd.print(”/");
 lcd.print (now.month() / 10, DEC);
 lcd.print (now.month() % 10, DEC);
 lcd.print(’ ‘);
 lcd.print (now.hour() / 10, DEC);
 lcd.print (now.hour() % 10, DEC);
 lcd.print(’:’);
 lcd.print(now.minute() / 10, DEC);
 lcd.print(now.minute() % 10, DEC); // print a simple message



Tu pourrait la mettre dans une fonction et l'appeler au lieu du copy/paste fait ici.


- Cela relève de l'optimisation mais toujours dans cette partie du code, autant d'accès au bus juste
pour deux ou trois caractère à la fois cela ralentie le bus et l'arduino.
Essaie si tu veux de créer un "objet" String (Objet sur arduino ? :o), d'y mettre une ligne complète de
l'écran et de l'envoyer en une seule fois.
([présentation de l'objet String](https://www.arduino.cc/en/Reference/StringConstructor))

en effet j’étais en train de faire un void times, mais print date c’est classe aussi, ça aère !
puis j’ai vu la suie de ton message (toujours prendre sont temps !!)

Pour l’optimisation des moteurs tu as intégrer les rations + et - 5 gr dans une seule fonction et 2 variables vitesse moteur? c’est bien ça ?

pour le string,je ne connaissais pas "msg_to_print += ", ça permet concrètement de prendre plusieurs données de les assembler et d’en faire ce que l’on veut ?

mise a jour avec la variable spd

C’est 100 fois plus propre, mais je crois que l’affichage aime pas du tout le spd,
il y aun bug d’affichage , le lcd.clear ne fonctionne, et/ou je ne sais pas!

menuwork_10.ino.ino (6.87 KB)

Bonjour à tous, j’avance ! un peu mais bon, l’affichage est pas mal débuggé,

il manquait un lcd.cursors donc mémoire saturée…

mais il restes des réponses que je comprends pas dans mon code,
je n’arrive pas à afficher les sous menu, ni a faire de retour…

help ?

menuwork_10.ino.ino (7.41 KB)

up ?

bonjour, j’en profite pour vous montrer l’évolution de mon code, j’ai eu des coup de mains, nnoteùent sur le logigramme mais toujours des décalage d’affichage??

#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
#include <Adafruit_MotorShield.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;

// initialisation des moteurs
Adafruit_MotorShield monShield = Adafruit_MotorShield();      // création de l'objet shield motor V3
Adafruit_DCMotor *moteurCroq = monShield.getMotor(1);         // création de l'objet moteurGauche par pointeur et repérage du numéro
Adafruit_DCMotor *moteurPompe = monShield.getMotor(4);        // création de l'objet moteurDroite par pointeur et repérage du numéro

// les différents états du menu
enum {
  date,
  miam,
  niagara,
  reprep,
  repas1,
  repas2,
  ratrat,
  ration1,
  ration2,
}
varmen = date; //
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();      // création de l'objet LCD shield adafruit 772
int     x = 8;                                            // nombre moyen de repas par jour

const char *tableauDesJours[] = {
  "Sam",
  "Dim",
  "Lun",
  "Mar",
  "Merc",
  "Jeu",
  "Vend"
};

int nour = 5000;                                     // temps en millis pour  5Gr
unsigned long rep = 86400000;                         // pour calcul de la distri auto
unsigned long Depart;

//--------------------------------------------------------------------------------
// INITIALISATION
//--------------------------------------------------------------------------------

void setup() {
  Wire.begin();                                       // On lance la communication i2c
  Serial.begin(9600);                                 // On lance la communication série

  lcd.begin(0x20, 16, 2);                             // On lance la communication avec l'écran
  lcd.setCursor(0, 0);                                // régle le curseur sur la première ligne première colonne

  RTC.begin();                                        //On lance la communication avec l'horloge
  monShield.begin();                                  //On lance la communication avec le shield

  Depart = millis();                                  // Enregistrement de mon point de départ

  uint8_t i = 0;
}
void print_date()
{
  DateTime now = RTC.now();
  RTC.adjust(DateTime(__DATE__, __TIME__));
  Wire.beginTransmission(0x68); // Accède au RTC I2C d'adresse 0x68.
  Wire.write(0x03); // Pointe le registre du dayOfWeek (0x03).
  Wire.requestFrom(0x68, 1); // Demande de reception d'un octet depuis registre (0x03).
  byte dayOfWeek = Wire.read(); // Stocke la valeur reçue.
  Wire.endTransmission();
  lcd.home();
  lcd.setCursor(0, 0);

  String msg_to_print = String(tableauDesJours[dayOfWeek]);
  msg_to_print += " ";
  msg_to_print += String(now.day() / 10, DEC) + String(now.day() % 10, DEC);
  msg_to_print += "/";
  msg_to_print += String(now.month() / 10, DEC) + String(now.month() % 10, DEC);
  msg_to_print += " ";
  msg_to_print += String(now.hour() / 10, DEC) + String(now.hour() % 10, DEC);
  msg_to_print += ":";
  msg_to_print += String(now.minute() / 10, DEC) + String(now.minute() % 10, DEC);

  lcd.print(msg_to_print);
}

void loop()
{ print_date();
  uint8_t lcd_key = lcd.readButtons();

  //   if ((millis() - Depart) >= rep) {                   // si rep ms se sont écoulées
  //   Depart = millis();                                // nouvelle enregistrement du point de départ modification en cours pour la nutrition programmée
  //}

  switch (varmen) {                                   // détermination de menu dans lequel on se trouve
    case (date) :
      print_date();


      switch (lcd_key) {
        case (BUTTON_UP):                          // dans le cas du bouton haut
          varmen = miam;                           // passer au menu repas
          break;

        case (BUTTON_DOWN):                           // dans le cas du bouton bas
          varmen = reprep;                   // passer au menu ration
          // fin du switch/case lcd_key pour varmen == date
          break;
      }
      // fin du switch/case lcd_key pour varmen == ratrat
      break;
    case (miam) :
      if (lcd_key)  {
        lcd.clear() ;
        lcd.setCursor(0, 1);
        lcd.print ("miam miam select");
      }
      switch (lcd_key) {
        case (BUTTON_UP):
          varmen = niagara;
          break;

        case (BUTTON_DOWN):
          varmen =  date;
          break;

        case (BUTTON_SELECT):
          lcd.setCursor(0, 1);
          lcd.print("     MIAM !!!! !");

          moteurCroq->setSpeed(200); //On définit la vitesse de rotation
          moteurCroq->run(FORWARD); //On fait tourner les moteurs
          delay(1000); // pendant 1 seconde
          moteurCroq->run(RELEASE); //Puis on les arrête
          delay(500);
          moteurCroq->run(FORWARD); //On fait tourner les moteurs
          delay(1000); // pendant 1 seconde
          moteurCroq->run(RELEASE); //Puis on les arrête
          break;    // fin du switch/case lcd_key pour varmen == ratrat
      }

      break;
    case (niagara) :
      if (lcd_key)  {
        lcd.setCursor(0, 1);
        lcd.print ("  Niagara select  ");
      }
      switch (lcd_key) {
        case (BUTTON_UP):
          varmen = ratrat;
          break;

        case (BUTTON_DOWN):
          varmen = miam;
          break;

        case (BUTTON_SELECT):
          lcd.clear() ;
          lcd.setCursor(0, 1);
          lcd.print("NIAGARA !!!");
          
          moteurPompe->setSpeed(200); //On définit la vitesse de rotation
          moteurPompe->run(FORWARD); //On fait tourner les moteurs
          delay(5000);
          moteurPompe->run(RELEASE); //Puis on les arrête
          break;
      } // fin du switch/case lcd_key pour varmen == niagara

      break;
    case (reprep) :
      if (lcd_key)  {
        lcd.setCursor(0, 1);
        lcd.print ("+1rep   -1rep");
      }
      switch (lcd_key) {
        case (BUTTON_UP):
          varmen = date;
          break;

        case (BUTTON_DOWN):
          varmen = ratrat;
          break;

        case (BUTTON_RIGHT):
          x = x - 1;
          lcd.clear() ;
          lcd.setCursor(0, 1);
          lcd.print (x);
          lcd.print ("repas / J");
          break;

        case (BUTTON_LEFT):
          x = x + 1;
          lcd.clear() ;
          lcd.setCursor(0, 1);
          lcd.print (x);
          lcd.print ("repas / J");
          break;
      }   // fin du switch/case lcd_key pour varmen == reprep

      break;
    case (ratrat) :
      if (lcd_key)  {
        lcd.setCursor(0, 1);
        lcd.print ("+5 Gr    -5 Gr");
      }
      switch (lcd_key) {
        case (BUTTON_UP):
          varmen = reprep;
          break;

        case (BUTTON_DOWN):
          varmen = niagara;
          break;

        case (BUTTON_RIGHT):
          lcd.clear() ;
          lcd.setCursor(0, 1);
          lcd.print("FAIT - 5Gr !");
          nour = nour - 1000;
          break;

        case (BUTTON_LEFT):
          lcd.clear() ;
          lcd.setCursor(0, 1);
          lcd.print("FAIT + 5Gr !");
          nour = nour + 1000;
          break;
      }      // fin du switch/case lcd_key pour varmen == ratrat

      break;
  } // fin du switch/case varmen
} // fin de loop()