> création d'une tondeuse robot autonome, piloté par un arduino, avec détection par sonar...
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 !
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
{
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 à fondanalogWrite(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...
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);
}
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é "...
Inscription à :
Articles (Atom)