Probleme de RTC (DS1307) avec Arduino Micro sans le moniteur serie

Bonjour à tous,

Je commence à tourner en rond, je vous explique :

Je suis en train de fabriquer une “horloge robotique”, sur base de Arduino micro avec un RTC DS1307, un microservo indique les heures et un “mini bras robotique” composé de deux microservos indique les minutes.

Une alimentation de 12v 1.5A alimente la Micro qui elle régule du 5V pour les 3 servos et le RTC, je sais que c’est un peu limite toute cette consommation sur la Micro. Il y a un condensateur 200 uF entre le +5 et la masse

Mon problème, tous fonctionne parfaitement mais uniquement si j ai ouvert le moniteur série de IDE sinon les servos se figent toujours à la même position.

Une fois le moniteur série ouvert je peux le refermer, allumer l’alimentation externe et débrancher l’USB, cela fonctionne.
Par contre juste en allument l 'alim et/ou par cable USB, les servos restent actif mais immobiles!

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
#include <Servo.h>

Servo servomin1;
Servo servomin2;
Servo servoheure;

RTC_DS1307 rtc;


void setup () {

 servomin1.attach(12);
 servomin2.attach(11);
 servoheure.attach(10);
  
  while (!Serial); // for Leonardo/Micro/Zero

  Serial.begin(9600);
  Wire.begin();
  rtc.begin();
  
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
     //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
   servomin1.write(50); 
   delay(600)   
   servomin2.write(100);
   delay(700);
}

void loop () {
    DateTime now = rtc.now();
    
    //Serial.print(now.year(), DEC);
    //Serial.print('/');
    //Serial.print(now.month(), DEC);
    //Serial.print('/');
   // Serial.print(now.day(), DEC);
   // Serial.print(" (");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

   if (now.minute()== 1){
      servomin1.write(26);    
      servomin2.write(111);   
    }
    if (now.minute()== 2){
      servomin1.write(55);   
      servomin2.write(110);  
    }
    if (now.minute()== 3){
      servomin1.write(18);    
      servomin2.write(70);  
    }
    if (now.minute()== 4){
      servomin1.write(60);    
      servomin2.write(82);   
    }
    if (now.minute()== 5){
      servomin1.write(60);    
      servomin2.write(146);   
    }
                                        // ECT ... jusqu'a 60
  
     if (now.hour()== 1){                 
      servoheure.write(1);          
    }
     if (now.hour()== 2){
      servoheure.write(13);          
    }
     if (now.hour()== 3){
      servoheure.write(23);          
    }
     if (now.hour()== 4){
      servoheure.write(40);          
    }
     if (now.hour()== 5){
      servoheure.write(54);          
    }
     if (now.hour()== 6){
      servoheure.write(71);          
    }
     if (now.hour()== 7){
      servoheure.write(84);          
    }
     if (now.hour()== 8){
      servoheure.write(100);          
    }
     if (now.hour()== 9){
      servoheure.write(115);          
    }
     if (now.hour()== 10){
      servoheure.write(138);          
    }
     if (now.hour()== 11){
      servoheure.write(135);          
    }     
    if (now.hour()== 12){
      servoheure.write(8);          
    }

delay (2000);
    
}

Quelqu’un à t’il une idée de mon problème ?

Merci à vous!

Essayez en virant cette ligne du setup()

while (!Serial); // for Leonardo/Micro/Zero et tous les print…et Le Serial.begin(9600)

Pas d’USB = pas de Serial = bloqué dans le while sur unarduino Micro

Autre option tester si Serial s’initialise en attendant quelques secondes dans le setup() et sinon affecter un drapeau (une variable globale boolean portSerieOK;) à faux qui dit que la communication série ne fonctionne pas et dans le code qui suit lier l’exécution de tous les print et le begin à un test sur ce flag

if (portSerieOK) Serial.println(F("Bonjour"));
boolean portSerieOK = false;
...
void setup()
{
   ...
   for (int i = 0;  i < 50; i++) { // essaye pendant 5 secondes
       if (!Serial) {
          delay(100);   
       } else {
          portSerieOK = true;
          Serial.begin(115200);
          Serial.println(F("USB de l'Arduino Micro actif"));
          break;
       }
   }
   ...
}

void loop()
{
   ...
   if (portSerieOK) Serial.println(F("xxx"));
   ...
}

Sinon vous devriez pouvoir trouver une formule mathématique qui vous donne l’angle à utiliser pour vos servos sans écrire 60+12 (ou 24) tests (et les else…!!!)… ou au moins utiliser un tableau avec tous les angles et accéder le bon angle à l’indice correspondant à la minute courante et l’heure.

Une fois le bon angle positionné pas la peine d’appeler en permanence la fonction sur le servo - une fois à chaque nouvelle heure et minute ça suffit.

Merci de ta reponse,

Effectivement sans le "while (!Serial);" cela fonctionne !

Pour la position des servos, un calcule ne permet pas d’accéder à la position suivante car les minutes sont ranger aléatoirement dans une liste.
Je n'est pas mis les ELSE , seulement les IF mais cela revient quasiment au même ?

Il faut que je me renseigne un peu plus sur les listes et leurs utilisations

Pour ne pas appeler tous le temps la fonction Servo, je mets du Delay? ou je créer une variable afin de vérifier si les minutes ont changées et n’appeler la fonction Servo que dans ce cas?

En tous cas merci de tes conseils!

tout à fait d'accord avec pepe

Merci pepe pour ton aide, tes explications et cerise sur le cadeau des propositions écrites d’amélioration du code !

J’ai donc modifié mon code avec ton exemple pour utiliser les tableaux (Code beaucoup plus court et facile a lire) et aussi une variable pour attendre un changement de minute avant d’appeler la fonction Servo.

Je n’ai pas eu le temps de l’uploader pour le vérifier mais je me permets de le poster si quelqu’un découvre une erreur ou un axe d’amélioration :slight_smile:

#include <Wire.h>
#include "RTClib.h"
#include <Servo.h>

Servo servomin1;
Servo servomin2;
Servo servoheure;

RTC_DS1307 rtc;

const byte positions_servomin1[24] = {8, 1, 13, 23, 40, 54, 71, 84, 100, 115, 138, 135, 8, 1, 13, 23, 40, 54, 71, 84, 100, 115, 138, 135}; 
const byte positions_servomin1[60] = {26, 55, 18, 60, 60, 85 ,63, 123, 105, 51, 24, 24, 35, 37, 59, 67, 83, 119, 39, 57, 77, 116, 96, 25, 46, 61, 21, 125, 42, 54, 77, 22, 71, 104, 38, 108, 79, 57, 99, 13, 47, 108, 66, 42, 26, 114, 76, 60, 60, 26, 31, 93, 53, 60, 79, 79, 62, 85, 66, 97};
const byte positions_servomin2[60] = {111, 110, 70, 82, 146, 146, 50, 102, 145, , 102, 126, 129, 88, 71, 68, 113, 120, 138, 134, 118, 82, 110, 106, 90, 73, 33, 123, 115, 113, 72, 110, 80, 102, 114, 96, 93, 63, 93, 123, 58, 92, 104, 93, 82, 98, 121, 130, 143, 143, 105, 77, 78, 84, 134, 99, 73, 61, 107, 78, 137};

int ancien_temps = 61  // 61 valeur initiale differente des 60 posibilitées de minute


void setup () {

 servomin1.attach(12);
 servomin2.attach(11);
 servoheure.attach(10);
  
  Serial.begin(57600);
  
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
     //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}

void loop () {
  
    DateTime now = rtc.now();
    
    byte index_heure = now.hour();
    byte index_min = now.minute();

    Serial.print(now.hour(), DEC);      // pour debug
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    if (index_min != ancien_temps) {
    
         if ( index_heure<24 && index_min<60 )                          { // test en cas d'erreur de lecture de la RTC
          
               servomin1.write( positions_servomin1[index_min] );
               delay(500);
               servomin2.write( positions_servomin2[index_min] );
               delay(500);

               index_heure %= 12;
               servoheure.write( positions_servoheure[index_heure] );
               delay(500);
               
               ancien_temps = index_min;
                                                                        }
                                   }  
    
}

Quelle est la signification exact de %= (dans mon cas: index_heure %= 12; ) ?

Pour mes servos, mème si tous fonctionnais bien 99% du temps, j’ai modifié pour les alimenter à travers un régulateur linéaire 6v dédié.
Je pensais ainsi réduire ou supprimer les vibrations de mon bras des minutes, composé de deux servos 9g, qui peux dans certaines positions faire des vibration frénétique.
Mais cela n’a rien changé !
Une simple pression de quelques grammes sur le bras permet d’annuler cette vibration.
La cause peut elle etre du à une bras trop léger (quelques grammes de PLA)?

Si le problème persiste je vais mettre un transistor pour activer l’alim des servos uniquement quand besoin. La force de maintient des servos non alimenté est suffisante.

Arnaud

Quelle est la signification exact de %= (dans mon cas: index_heure %= 12; ) ?

% c’est la fonction mathématique “modulo”, c’est à dire le reste de la division entière

23 % 12 c’est 11 parce que 23 / 12 = 1 et reste 11 → pratique pour ramener l’heure qui peut être de 0 à 23 dans la game 0 à 11.

Je pensais ainsi réduire ou supprimer les vibrations de mon bras des minutes, composé de deux servos 9g, qui peux dans certaines positions faire des vibration frénétique.
Mais cela n’a rien changé !

Sans doute ce sont des servos de moyenne qualité… et donc certains angles ne sont pas atteignables souvent dans le petites et grandes valeurs… il faut les tester un par un, en essayant l’angle 0 voir si ça vibre, passer à 1, 2, 3, etc jusqu’à ce que ça ne vibre plus (il se peut aussi que ça vibre en fin de course) ==> malheureusement ça fait que vous n’aurez pas l’ensemble de la palette des angles dispos