Sourino (от французского — «мышь») — маленький Arduino-робот, изготовленный при помощи 3D-печати, который поможет играть детям и котятам.
В основе робота — контроллер Arduino Nano, и три ультразвуковых датчика расстояния (HC-SR04), необходимых для для автономной навигации робота. В верхней части робота располагается инфракрасный приёмник, предназначенный для дистанционного управления роботом. В движение робот приводится с помощью двух небольших мотор-редукторов, управляемых через драйвер двигателей на L298N.
Код прошивки робота — Sourino_software.ino
#include <IRremote.h>
const char DIN_RECEPTEUR_INFRAROUGE = 2;
IRrecv MonRecepteurInfraRouge(DIN_RECEPTEUR_INFRAROUGE);
decode_results MessageRecu;
// Définition des variables :
String mode = "Stop";
const int vitmax = 100;
const int vitref = 75;
const int vitmin = 55;
int vitesse = vitmin; //La vitesse est réglable de 0 à 1023
int vitesse_int = 0; //La vitesse du moteur intérieur du virage
float ValUSG = 0;
float ValUSM = 0;
float ValUSD = 0;
const int K = 1; // Coefficient pour faire varier la vitesse en fonction de la distance
unsigned long t0 = 0; // temps de début de compteur
unsigned long t = 0; // temps écoulé dans la boucle (chien de garde)
int retour = 0; // return value 0 = Bien passé, 1 = Appui OK, 2 = timeout, 3 = appui #
int vitesse_plus_mt_droit = 0;
int vitesse_moins_mt_droit = 0;
int vitesse_plus_mt_gauche = 0;
int vitesse_moins_mt_gauche = 0;
String action;
const int plus_mt_droit = 9;
const int moins_mt_droit = 10;
const int plus_mt_gauche = 6;
const int moins_mt_gauche = 5;
const float D1 = 75.00;
const float D2 = 50.00;
const float D3 = 20.00;
// Définition des fonctions
float MesureDistUS (String Capteur) {
int PinTrig;
int PinEcho;
long Temps;
float Distance;
if(Capteur == "G") {
PinTrig = 3;
PinEcho = 4;
}
else if(Capteur == "M") {
PinTrig = 7;
PinEcho = 8;
}
else if(Capteur == "D") {
PinTrig = 11;
PinEcho = 12;
}
do{
digitalWrite (PinTrig,HIGH);
delayMicroseconds (10);
digitalWrite (PinTrig,LOW);
Temps = pulseIn (PinEcho,HIGH);
}while(Temps == 0);
Temps = Temps/2;
Distance = (Temps*340)/10000.0;
return Distance;
};
int Cas1 () { // Tout droit à fond
vitesse_plus_mt_droit = vitmax;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = vitmax;
vitesse_moins_mt_gauche = 0;
return 0;
};
int Cas2 (float USM) { // Tout droit en ralentissant proportionnellement à la distance avec l'obstacle
float V = K * USM;
if (V > vitmax) {V = vitmax;}
if (V < vitmin) {V = vitmin;}
vitesse_plus_mt_droit = V;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = V;
vitesse_moins_mt_gauche = 0;
return 0;
};
int Cas3 () { // Tourne légèrement à gauche
vitesse_plus_mt_droit = vitmax;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = vitref;
vitesse_moins_mt_gauche = 0;
return 0;
};
int Cas4 () { // Tourne légèrement à droite
vitesse_plus_mt_droit = vitref;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = vitmax;
vitesse_moins_mt_gauche = 0;
return 0;
};
int Cas5 (float USG, float USD) { // Tourne de façon à passer entre les obstacles
// Vitesse droite proportionelle à distance obstacle gauche et inversement
float vG = K * USD;
if (vG > vitmax) {vG = vitmax;}
if (vG < vitmin) {vG = vitmin;}
float vD = K * USG;
if (vD > vitmax) {vD = vitmax;}
if (vD < vitmin) {vD = vitmin;}
vitesse_plus_mt_droit = vD;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = vG;
vitesse_moins_mt_gauche = 0;
return 0;
};
int Cas6 (float USG, float USM, float USD) { // Avance et tourne en s'éloignant de l'obstacle le plus proche
vitesse_moins_mt_droit = 0;
vitesse_moins_mt_gauche = 0;
float V = K * USM;
if (V > vitmax) {V = vitmax;}
if (V < vitmin) {V = vitmin;}
if (USG < USD) {
if (V * 0.8 < vitmin) {
vitesse_plus_mt_droit = 0;
}
else {
vitesse_plus_mt_droit = V * 0.8;
}
vitesse_plus_mt_gauche = V;
}
else {
if (V * 0.8 < vitmin) {
vitesse_plus_mt_gauche = 0;
}
else {
vitesse_plus_mt_gauche = V * 0.8;
}
vitesse_plus_mt_droit = V;
}
return 0;
};
int Cas7 () { // Tourne sur place vers la droite jusqu'a ce que l'obstacle est disparut ou qu'un obstacle apparaissent à droite
vitesse_plus_mt_droit = 0;
vitesse_moins_mt_droit = vitmin;
vitesse_plus_mt_gauche = vitmin;
vitesse_moins_mt_gauche = 0;
return 0;
};
int Cas8 () { // Tourne sur place vers la gauche jusqu'a ce que l'obstacle est disparut ou qu'un obstacle apparaissent à gauche
vitesse_plus_mt_droit = vitmin;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = 0;
vitesse_moins_mt_gauche = vitmin;
return 0;
};
int Cas9 (float USG, float USD) { // Tourne vers là ou l'obstacle est le plus loin
if(USG > USD) {
vitesse_plus_mt_droit = vitmin;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = 0;
vitesse_moins_mt_gauche = vitmin;
}
else {
vitesse_plus_mt_droit = 0;
vitesse_moins_mt_droit = vitmin;
vitesse_plus_mt_gauche = vitmin;
vitesse_moins_mt_gauche = 0;
}
return 0;
};
int Cas10 () { // Souris coincée dans un cul de sac ou dans un angle
t0 = millis();
do{
ValUSG = MesureDistUS("G");
ValUSD = MesureDistUS("D");
if(ValUSG > ValUSD) {
vitesse_plus_mt_droit = vitmin;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = 0;
vitesse_moins_mt_gauche = vitmin;
}
else {
vitesse_plus_mt_droit = 0;
vitesse_moins_mt_droit = vitmin;
vitesse_plus_mt_gauche = vitmin;
vitesse_moins_mt_gauche = 0;
}
analogWrite(plus_mt_droit, vitesse_plus_mt_droit);
analogWrite(moins_mt_droit, vitesse_moins_mt_droit);
analogWrite(plus_mt_gauche, vitesse_plus_mt_gauche);
analogWrite(moins_mt_gauche, vitesse_moins_mt_gauche);
t = millis() - t0;
if(t >= 10000) {
return 2;
break;
}
if (MonRecepteurInfraRouge.decode(&MessageRecu)) {
if (MessageRecu.value == 0xFF38C7) {
break;
}
}
}while(true == true);
if(t <= 10000) {
return 1;
}
}
String prog_US () {
String toto = "Auto";
Serial.println ("En mode Auto");
do {
t0 = millis();
retour = 0;
ValUSG = MesureDistUS("G");
ValUSM = MesureDistUS("M");
ValUSD = MesureDistUS("D");
if(ValUSG > D2 && ValUSM > D1 && ValUSD > D2)
{
retour = Cas1();
}
else if(ValUSG > D2 && (ValUSM < D1 && ValUSM > D3) && ValUSD > D2)
{
retour = Cas2(ValUSM);
}
else if(ValUSG > D2 && ValUSM > D3 && (ValUSD > D3 && ValUSD < D2))
{
retour = Cas3();
}
else if((ValUSG < D2 && ValUSG > D3) && ValUSM > D3 && ValUSD > D2)
{
retour = Cas4();
}
else if((ValUSG < D2 && ValUSG > D3) && ValUSM > D1 && (ValUSD > D3 && ValUSD < D2))
{
retour = Cas5(ValUSG, ValUSD);
}
else if((ValUSG < D2 && ValUSG > D3) && (ValUSM < D1 && ValUSM > D3) && (ValUSD < D2 && ValUSD > D3))
{
retour = Cas6(ValUSG, ValUSM, ValUSD);
}
else if(ValUSG < D3 && ValUSM > D3 && ValUSD > D3)
{
retour = Cas7();
}
else if(ValUSG > D3 && ValUSM > D3 && ValUSD < D3)
{
retour = Cas8();
}
else if(ValUSG > D3 && ValUSM < D3 && ValUSD > D3)
{
retour = Cas9(ValUSG, ValUSD);
}
else if(ValUSG < D3 && ValUSM < D3 && ValUSD < D3)
{
retour = Cas10();
}
/*else //Cas non prévu arret immédiat + msg d'erreur
{
analogWrite(plus_mt_droit, 0);
analogWrite(moins_mt_droit, 0);
analogWrite(plus_mt_gauche, 0);
analogWrite(moins_mt_gauche, 0);
Serial.println ("Cas non prévu");
break;
}*/
analogWrite(plus_mt_droit, vitesse_plus_mt_droit);
analogWrite(moins_mt_droit, vitesse_moins_mt_droit);
analogWrite(plus_mt_gauche, vitesse_plus_mt_gauche);
analogWrite(moins_mt_gauche, vitesse_moins_mt_gauche);
if (retour == 2) { // time-out du cas 10
toto = "Stop";
}
if (MonRecepteurInfraRouge.decode(&MessageRecu)) {
if (MessageRecu.value == 0xFF38C7) { //OK
toto ="Stop";
}
if (MessageRecu.value == 0xFFB04F) { //#
toto ="Tele";
}
MonRecepteurInfraRouge.resume();
}
}while(toto == "Auto");
analogWrite(plus_mt_droit, 0);
analogWrite(moins_mt_droit, 0);
analogWrite(plus_mt_gauche, 0);
analogWrite(moins_mt_gauche, 0);
return toto;
}
String prog_IR () {
String toto = "Tele";
Serial.println ("En mode Tele");
do {
if (MonRecepteurInfraRouge.decode(&MessageRecu)) {
if (MessageRecu.value == 0xFF18E7) // Si la flèche du haut à été pressée //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
delay(500); //
action = "avance"; //
} //
//
if (MessageRecu.value == 0xFF10EF) // Si la flèche de gauche à été pressée //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse_int; //
vitesse_moins_mt_gauche = 0; //
delay(500); // Controle de la direction en fonction du bouton préssé
action = "gauche"; //
} //
//
if (MessageRecu.value == 0xFF5AA5) // Si la flèche de droite à été pressée //
{ //
vitesse_plus_mt_droit = vitesse_int; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
delay(500); //
action = "droite"; //
} //
//
if (MessageRecu.value == 0xFF4AB5) // Si la flèche du bas à été pressée //
{ //
vitesse_plus_mt_droit = 0; //
vitesse_moins_mt_droit = vitesse; //
vitesse_plus_mt_gauche = 0; //
vitesse_moins_mt_gauche = vitesse; //
delay(500); //
action = "arriere"; //
} //
//
if (MessageRecu.value == 0xFF38C7) // Si OK à été pressé //
{ //
vitesse_plus_mt_droit = 0; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = 0; //
vitesse_moins_mt_gauche = 0; //
action = "stop"; //
} //
if (MessageRecu.value == 0xFFA25D) // Si le bouton 1 à été préssé //
{ //
vitesse = vitmin; //
vitesse_int = 0; //
//
if (action == "avance") //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "droite") //
{ //
vitesse_plus_mt_droit = vitesse_int; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "gauche") //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse_int; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "arriere") //
{ //
vitesse_plus_mt_droit = 0; //
vitesse_moins_mt_droit = vitesse; //
vitesse_plus_mt_gauche = 0; //
vitesse_moins_mt_gauche = vitesse; //
} //
} //
//
if (MessageRecu.value == 0xFF629D) // Si le bouton 2 à été préssé //
{ //
vitesse = vitref; // Réglage des vitesses en fonction du bouton préssé (1,2 ou 3)
vitesse_int = 0; //
//
if (action == "avance") //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "droite") //
{ //
vitesse_plus_mt_droit = vitesse_int; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "gauche") //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse_int; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "arriere") //
{ //
vitesse_plus_mt_droit = 0; //
vitesse_moins_mt_droit = vitesse; //
vitesse_plus_mt_gauche = 0; //
vitesse_moins_mt_gauche = vitesse; //
} //
} //
//
if (MessageRecu.value == 0xFFE21D) // Si le bouton 3 à été préssé //
{ //
vitesse = vitmax; //
vitesse_int = 50; //
//
if (action == "avance") //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "droite") //
{ //
vitesse_plus_mt_droit = vitesse_int; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "gauche") //
{ //
vitesse_plus_mt_droit = vitesse; //
vitesse_moins_mt_droit = 0; //
vitesse_plus_mt_gauche = vitesse_int; //
vitesse_moins_mt_gauche = 0; //
} //
//
else if (action == "arriere") //
{ //
vitesse_plus_mt_droit = 0; //
vitesse_moins_mt_droit = vitesse; //
vitesse_plus_mt_gauche = 0; //
vitesse_moins_mt_gauche = vitesse; //
} //
}
if (MessageRecu.value == 0xFF6897) { //*
toto ="Auto";
}
MonRecepteurInfraRouge.resume();
}
analogWrite(plus_mt_droit, vitesse_plus_mt_droit);
analogWrite(moins_mt_droit, vitesse_moins_mt_droit);
analogWrite(plus_mt_gauche, vitesse_plus_mt_gauche);
analogWrite(moins_mt_gauche, vitesse_moins_mt_gauche);
}while(toto == "Tele");
analogWrite(plus_mt_droit, 0);
analogWrite(moins_mt_droit, 0);
analogWrite(plus_mt_gauche, 0);
analogWrite(moins_mt_gauche, 0);
return toto;
}
// Définition des fonctions :
void setup() {
// Début du setup...
// ...pour tout...
MonRecepteurInfraRouge.enableIRIn();
pinMode (plus_mt_droit, OUTPUT);
pinMode (moins_mt_droit, OUTPUT);
pinMode (plus_mt_gauche, OUTPUT);
pinMode (moins_mt_gauche, OUTPUT);
// ...et pour l'automatisation
pinMode (3, OUTPUT);
pinMode (4, INPUT);
pinMode (7, OUTPUT);
pinMode (8, INPUT);
pinMode (11, OUTPUT);
pinMode (12, INPUT);
Serial.begin (9600);
}
void loop() {
if (mode == "Tele") { // Si il faut passer en mode télécommandé
vitesse_plus_mt_droit = 0;
vitesse_moins_mt_droit = 0;
vitesse_plus_mt_gauche = 0;
vitesse_moins_mt_gauche = 0;
mode = prog_IR();
}
else if (mode == "Auto") { // Si il faut passer en autonome
mode = prog_US();
}
else if (mode == "Stop") { // Si il faut passer en stop
Serial.println ("STOP !!!");
analogWrite(plus_mt_droit, 0);
analogWrite(moins_mt_droit, 0);
analogWrite(plus_mt_gauche, 0);
analogWrite(moins_mt_gauche, 0);
}
if (MonRecepteurInfraRouge.decode(&MessageRecu)) {
if (MessageRecu.value == 0xFFB04F) { // #
mode ="Tele"; }
if (MessageRecu.value == 0xFF6897) { // *
mode = "Auto";
}
MonRecepteurInfraRouge.resume();
}
}
Ссылки
Sourino – the Best Toy for Cats and Kids
По теме
GoodBoy - робот-собака на Arduino
Свой spotmini для 3D-печати
Доступный Arduino-совместимый робот для рисования
LogoBot - простой робот для изготовления при помощи 3D-печати
Изготовление виброботов при помощи 3D-печати
PANDA - самодельный робот-чистильщик на базе Arduino и 3D-печати
Простой Arduino-робот на одном моторе и сервомашинке
