Code...


Voici le code actuel utilisé par le robot, je vous rappelle que se sont mes premières lignes de code, alors merci de votre indulgence. Le code est à améliorer, mais pour le moment c'est celui là!



// prog robot IBT 009   007 + parechoc

#include <Servo.h>
#include "Ultrasonic.h"
#include <Time.h>   

const int RL_EN=6;
const int PWM1D=5;
const int PWM2D=4;
const int PWM1G=3;
const int PWM2G=2;
const int BRUSHLESS=7;
const int APPUI=0;                                // constante état du BP - appui sur niveau bas
const int PAS_APPUI=1;                      // constante état du BP - relâché sur niveau haut
const int BP=1;                                     //declaration constante de broche
int ETAT_BP;                                      // variable d'état du bouton poussoir
int vit_lame=1601;                               //acceleration lames vitesse max à 2200 et mini à 1600
int dist_lateral=35;
int dist_face=25;
int X=0;

long Temp_Reference_avance;  
long Temp_Reference_recul;
long Temp_Reference_droite;
long Temp_Reference_gauche;
long delai_avance=40000;                     //60000=1minute
long delai_recul=15000;
long delai_droite=15000;
long delai_gauche=15000;
Servo cont_brushless;

#define  TRIG_PIN_A  8
#define  ECHO_PIN_B  9
Ultrasonic OurModule_G(TRIG_PIN_A, ECHO_PIN_B);
#define  TRIG_PIN_C  10
#define  ECHO_PIN_D  11
Ultrasonic OurModule_M(TRIG_PIN_C, ECHO_PIN_D);
#define  TRIG_PIN_E  12
#define  ECHO_PIN_F  13
Ultrasonic OurModule_D(TRIG_PIN_E, ECHO_PIN_F);

void setup() 
{
pinMode(BP, INPUT);                                          //met la broche en entree
digitalWrite(BP, HIGH) ;                                     // activation du pullup de la broche en entrée
cont_brushless.attach(BRUSHLESS);
pinMode(BRUSHLESS, OUTPUT);
Temp_Reference_avance=millis();
Temp_Reference_recul=millis();
Temp_Reference_droite=millis();
Temp_Reference_gauche=millis();
//lancement de la coupe
delay (5000);
ROB_CUT_ON();
delay (7000);

pinMode(RL_EN, OUTPUT);
pinMode(PWM1D, OUTPUT);
pinMode(PWM2D, OUTPUT);
pinMode(PWM1G, OUTPUT);
pinMode(PWM2G, OUTPUT);
digitalWrite(RL_EN, HIGH);

AVANCE();
delay (500);

}


void loop()
{
AVANCE();

   while ( (OurModule_D.Ranging(CM)) < dist_lateral & (OurModule_D.Ranging(CM)) < (OurModule_G.Ranging(CM)))
  {
   droite();
  delay(100);
                 while ( (OurModule_M.Ranging(CM)) < dist_face )
                {
                recul();
                delay(100);
                }
              }

 while ( (OurModule_G.Ranging(CM)) < dist_lateral & (OurModule_G.Ranging(CM)) < (OurModule_D.Ranging(CM)))
 
  {
   gauche();
  delay(100);
                while ( (OurModule_M.Ranging(CM)) < dist_face )
                {
                recul();
                delay(100);
                }
              }


 while ( (OurModule_M.Ranging(CM)) < dist_face )
  {
   recul();
                delay(100);
               }



}

void AVANCE()
{
analogWrite(PWM1D,255);
analogWrite(PWM2D,0);
 
analogWrite(PWM1G,0);
analogWrite(PWM2G,255);
ETAT_BP=digitalRead(BP);    // lit l'état du BP et met la valeur 0/1 dans la variable
 
if (ETAT_BP==APPUI)
{       // si l'état du BP est appuyé (càd si variable état BP = 0)

   recul();
     delay(100);
}
else
{       // sinon (càd si variable état bp=1)
 
}

if (millis()>(Temp_Reference_avance+delai_avance))
 {   
                recul();
  delay(100);
                Temp_Reference_avance=Temp_Reference_avance+delai_avance;
 }

}

void droite()
{
analogWrite(PWM1D,200);
analogWrite(PWM2D,0);
 
analogWrite(PWM1G,0);
analogWrite(PWM2G,0);
ETAT_BP=digitalRead(BP);    // lit l'état du BP et met la valeur 0/1 dans la variable
 
if (ETAT_BP==APPUI)
{       // si l'état du BP est appuyé (càd si variable état BP = 0)

   recul();
     delay(100);
}
else
{       // sinon (càd si variable état bp=1)
 
}

}

void gauche()
{
analogWrite(PWM1D,0);
analogWrite(PWM2D,0);
 
analogWrite(PWM1G,0);
analogWrite(PWM2G,200);
ETAT_BP=digitalRead(BP);    // lit l'état du BP et met la valeur 0/1 dans la variable
 
if (ETAT_BP==APPUI)
{       // si l'état du BP est appuyé (càd si variable état BP = 0)

   recul();
     delay(100);
}
else
{       // sinon (càd si variable état bp=1)
 
}
               
}

void recul()
{
 
if (X==0)
{
 
analogWrite(PWM1D,0);
analogWrite(PWM2D,0);
 
analogWrite(PWM1G,0);
analogWrite(PWM2G,0);
delay(200);

analogWrite(PWM1D,70);
analogWrite(PWM2D,140);
 
analogWrite(PWM1G,140);
analogWrite(PWM2G,0);
delay(700);

analogWrite(PWM1D,70);
analogWrite(PWM2D,140);
 
analogWrite(PWM1G,0);
analogWrite(PWM2G,0);
delay(550);
X=1;
}
else
{
analogWrite(PWM1D,0);
analogWrite(PWM2D,0);
 
analogWrite(PWM1G,0);
analogWrite(PWM2G,0);
delay(200);

analogWrite(PWM1D,70);
analogWrite(PWM2D,140);
 
analogWrite(PWM1G,140);
analogWrite(PWM2G,0);
delay(700);

analogWrite(PWM1D,0);
analogWrite(PWM2D,0);
 
analogWrite(PWM1G,140);
analogWrite(PWM2G,0);
delay(550);
X=0;
}

analogWrite(PWM1D,0);
analogWrite(PWM2D,0);
 
analogWrite(PWM1G,0);
analogWrite(PWM2G,0);
delay(150);
if (millis()>(Temp_Reference_recul+delai_recul))
  {   
                analogWrite(PWM1D,0);
                analogWrite(PWM2D,0);
 
                analogWrite(PWM1G,0);
                analogWrite(PWM2G,0);
                delay(200);           
   
                analogWrite(PWM1D,175);
                analogWrite(PWM2D,0);
 
                analogWrite(PWM1G,0);
                analogWrite(PWM2G,175);
                delay(1050);
                analogWrite(PWM1D,0);
                analogWrite(PWM2D,0);
 
                analogWrite(PWM1G,0);
                analogWrite(PWM2G,0);
                delay(50);
                Temp_Reference_recul=Temp_Reference_recul+delai_recul;
 }
}



void ROB_CUT_ON()    //demarrage de la coupe
{
  cont_brushless.writeMicroseconds(1470); // génère initialisation du controleur
  delay (2000);     //attente de 2 secondes pour initialisation du controleur
 int robcuton;
   for(robcuton = 1470 ; robcuton <= vit_lame; robcuton+=1)  //acceleration vitesse max à 2200 et mini à 1600
   {
    
     cont_brushless.writeMicroseconds(robcuton);
 
   }
  delay(3000);
  cont_brushless.writeMicroseconds((robcuton-19));   //-15 pas de changement ** -21 bien  **-24 arret moteur  


}



enfin un projet avec le code !!!! ;-)

Modification...

Si le robot devrait être modifié, j'opterais pour une caisse ronde ( moins d'accrochage aux obstacles),
des moteurs de tractions en 24v, 3 disques et 3 moteurs de coupe (augmentation de son diamètre de coupe et peu de consommation des batteries en plus), sur 4 roues au lieu de 3 ( meilleur stabilité dans les terrains accidenté), gestion du terrain par le programme (optimiser les passages au même endroit et faire une grille de tonte). Toutes ces modifs dans une prochaine version!

Autonomie et poids...

Vu le dimensionnement des moteurs de traction, j'ai ajouté une batterie supplémentaire
afin d'augmenter l'autonomie du robot. Les moteurs étant suffisamment puissant pour
pouvoir transporter 2 batteries au plomb! La première batterie étant une batterie de récupération,
je ne connais pas sa performance, la seconde est neuve. Autonomie plus de 40 minutes. 



Batterie scotché sur son dos pour les essais...

Pare-choc !!!

Installation de 2 pare-choc contact à l'avant, pour les obstacles trop bas pour les capteurs US.




Les pare-chocs sont montés sur charnières pour pouvoir se relever lors
d'une marche arrière sans tout arracher !

Il a maintenant un nom...!


Il s'appelle robot CutFlowers !

Essai terrain...


Essai avec les 2 cartes de gestion des MEGs, bon conportement et plus facile à
programmer que l'ancienne. Modif du prog pour essayer de gérer les réactions du robot
en cas d'enlisement de la caisse et augmentation de la vitesse de coupe, la fonction recul alterne maintenant le coté de dégagement pour mieux se sortir des impasses.

 
J'ai fait des test avec un pack d'accus maison (SUB ni-mh en 12V 6A), les réactions sont
beaucoup plus fluide qu'avec la batterie au plomb à l'avant qui fait piquer du nez le robot
lors des marches AR, mais au niveau autonomie rien à voir avec la grosse batterie au plomb...

Carte de puissance et H-bridges


après avoir grillé la moitié de ma carte driver moteur, je m'en suis procuré une autre sur ebay,
qui doit tenir jusque 43A ! (une par moteur)

Double BTS7960B 43A Motor Driver High-power module/smart car driver Arduino


voici un bout de code pour tester 2 cartes pour 2 moteurs :
câbler VCC (5v) et GND.


const int RL_EN=6;   // relier tous les R_EN et L_EN ensemble
const int PWM1D=5;  //moteur D
const int PWM2D=4;  //moteur D
const int PWM1G=3;  //moteur G
const int PWM2G=2;  //moteur G

void setup()  
{
pinMode(RL_EN, OUTPUT);
pinMode(PWM1D, OUTPUT);
pinMode(PWM2D, OUTPUT);
pinMode(PWM1G, OUTPUT);
pinMode(PWM2G, OUTPUT);

digitalWrite(RL_EN, HIGH); // mets tous les R_EN et L_EN à un niveau HAUT
}

void loop()
{
analogWrite(PWM1D,255);  // moteur D avant à fond
analogWrite(PWM2D,0);      // moteur G avant à fond
 
analogWrite(PWM1G,0);       // moteur G avant à fond
analogWrite(PWM2G,255);   // moteur G avant à fond
} 

pour la marche arrière, inverser les valeurs 0 et 255.


Correctifs...

     Démontage et renforcement du support de moteur de coupe et réglage du
disque à lames afin qu'il soit bien à plat. Vérification de l'équilibrage du disque.

Modification du programme pour:

-- la mise en marche du brushless à haute vitesse pour être sûr qu'il s'initialise correctement 
( le frottement de l'herbe ralenti le démarrage et il risque de ne pas se lancer ), puis réduction
de la vitesse pour limiter la consommation et le bruit...
-- modification du comportement lors d'un obstacle de face...
-- marche arrière progressive, pour que le robot ne lève pas la roue AR...

Touchdown !!!


Essai !!! sur la pelouse de l'hiver, dur dur !!! et, encore des petits réglages...


Problème : à la fin de l'essai, le robot a reculé contre un mur et la carte de driver
des moteurs a griller à moitier...
Avec l'utilisation de transistor Darlington du type TIP120 et TIP 125 on ne recupère pas
en sortie 100% de la puissance contrerement à l'utilisation de Mosfet où le rendement est meilleur.
Ce qui explique pourquoi le robot se déplace plus vite quand les moteurs sont branchés en
directe sur la batterie, plutot que quand ils sont gérés par la carte de puissance...

Serrage des vis !!!


Premier essai avec le système de coupe ! Toutes les vis se sont dévissés et
le moteur est tombé !



Support du brushless...


Le remède: la Loctite !



Remontage du moteur sur le chassis...



Tests ...


Premier test avec les MEG, et une batterie au plomb de 7A, détection calibrée à 40cm...





Montage...



Montage et cablage...

Now, rectification du programme afin de régler les news moteurs et tests...

Démontage ...

Démontage de toute la partie électronique de l'ancien chassis...


Découpage de la nouvelle caisse plus haute pour recevoir les MEG...




... suite ...

... suite du test au sol, la ligne droite et bien gérée par les codeurs, mais un new problème !
Les moteurs tournent à 500 tr/mn et je dois donc les ralentir pour tourner aux environs de 100tr/mn
( no prob avec la prog sur l'arduino!), mais vu le ralentissement, les moteurs perdent beaucoup de
couple et deviennent trop faible pour promener correctement le robot !!! GRRRR!!!!!
Mise en place de new moteurs: des MEG ! Moteur d'essuie-glace de Kangoo
( et chui pas trop voiture française !!! lol )
J'ai donc bricolé avec mon filleul Hugo (un futur grand bricoleur)
une caisse bidon avec 2 MEG plus la batterie et un peu de poids,
le tout à l'arrache pour voir si les moteurs se comportent bien !!!
et surprise, jusque-là ça marche plutôt bien et pas besoin de réguler la vitesse,
 c'est pas beau ça !!!


Premier test au sol...



Premier test au sol avec les moteurs codés, et la batterie de 284Kg!
Merci mon pote Nico pour le code de dingo des codeurs !!

Codage des moteurs...

Après un premier test au sol, il faut absolument créer un asservissement
pour gérer les vitesses des 2 motoréducteurs et la trajectoire...


Découpage de rondelle en plastique...


Impression de roue de codage...




Découpe à la meuleuse des encoches...




Montage sur l'axe de la roue...


Test d'un optocoupleur récupéré dans une imprimante...


Installation sur le chassis du robot...





Mise en place des composants...


Conception du sonar monté sur tourelle...


Réalisation de la carte de puissance...


Insertion des 2 motoréducteurs et du moteur brushless pour la coupe...

 
exemple de code pour tester le moteur brusless:
 
// lignes de code pour demarrer un moteur brushless...

#include <Servo.h>                                       // librairie pour servomoteur
const int BRUSHLESS=3;                           //declaration constante de broche
Servo cont_brushless;                                  // crée un objet servo pour contrôler le servomoteur
 
void setup()  
{
cont_brushless.attach(BRUSHLESS);        // attache l'objet servo à la broche de cmd du servo
pinMode(BRUSHLESS, OUTPUT);          //met la broche en sortie

 cont_brushless.writeMicroseconds(1470);        // génère milieu servo
 delay (2000);                                                     //attente de 2 secondes pour initialisation du controleur
 
int robcuton;
  for(robcuton = 1470 ; robcuton <= 2200; robcuton+=1)  //acceleration vitesse max à 2200
  {
        cont_brushless.writeMicroseconds(robcuton);
  }
}
 
void loop()
{ // debut de la fonction loop()
}



Fabrication d'une boite autour de la carte de puissance pour faire un système " air forcé "...



Création de la caisse...


Découpe des roues dans de l'alu...


Corps en PVC et Plexi...