Robot préhenseur télécommandé avancé pour manipulation de précision
Composants et fournitures
| Châssis Runt Rover Half-pint | × | 1 | |
![]() |
Arduino UNO | × | 1 |
| Shield V5 Sensor | × | 1 | |
![]() |
Fils Dupont Femelle/Femelle | × | 1 |
| Contrôleur moteur L9110S | × | 1 | |
| Équerre 90° mono-angle (585424) | × | 1 | |
| Moyeu de servo léger, Futaba | × | 1 | |
| Kit préhenseur standard A (637094) | × | 1 | |
| Servo MG995 | × | 1 | |
| Plaque servo standard | × | 1 | |
| Équerre 90° mono-angle (seconde) | × | 1 | |
| Support 5 piles AA | × | 1 | |
| Piles AA NiMH rechargeables | × | 5 | |
| Entretoises nylon .750" 8-32 | × | 2 | |
| Vis .500" 6-32 avec écrous | × | 8 | |
| Vis .3125" 6-32 | × | 8 |
Applications et services en ligne
![]() |
Arduino IDE |
À propos de ce projet
Il y a quelques mois, mon fils m'a demandé de lui construire un robot télécommandé. Il m'a donné une liste de souhaits qu'on a réduite à quelque chose de gérable. Voici le résultat...
- Assemblez l'UNO et le shield V5, insérez-les dans le support central du châssis.
- Fixez le contrôleur moteur (ruban double face) sur la paroi gauche, le module Bluetooth sur la droite.
Vous pouvez utiliser un autre châssis 4WD fermé selon vos préférences.
Étape 1 : Logiciels nécessaires
- Arduino IDE
- Python 2.7 (installation complète avec tkinter)
- Bibliothèque pySerial
- Bibliothèque L9110S (fichier
L9110Driver.zipjoint) - Code robot (ci-dessous ou
blue_t_slave.zip) - Application de contrôle Python (ci-dessous)
Étape 2 : Nomenclature matérielle
- Châssis Runt Rover Half-pint ou équivalent 4WD fermé
- Arduino Uno + câble USB
- Shield V5 Sensor
- Contrôleur moteur L9110S (en prendre plusieurs, peu coûteux)
- Servo MG995 ×2 (ou équivalent)
- Module Bluetooth HC-05 ou HC-06 ×1
- Plaque servo standard B ×1
- Équerre 90° ×1, équerre simple ×2
- Moyeu servo léger (525125 Futaba) ×1
- Kit préhenseur standard A ×1
- Fils Dupont F/F
- 5 piles AA NiMH + chargeur
- Ruban double face + petits colliers
- Pack 5 piles AA (ou pack 6V NiMH / 7.4V Li-ion + chargeur)
- Vis 1.250" 6-32 ×2, entretoises .750" 8-32 ×2, vis .500" 6-32 avec écrous ×8, vis .3125" 6-32 ×8
Approvisionnement possible : eBay, Sparkfun, Adafruit, ServoCity.
Étape 3 : Assemblage du châssis
Suivez les instructions du châssis. Placez la plaque contrôleur sur les trous centraux (espace avant/arrière). IMPORTANT : retirez les 4 roues avant de continuer pour ne pas endommager les moteurs lors du montage.
Étape 4 : Assemblage du préhenseur
Suivez la vidéo fournie. Résultat attendu : préhenseur assemblé.
Étape 5 : Montage du préhenseur - Partie 1
Utilisez : équerre 90°, moyeu servo léger, 4 vis .3125".
- Fixez le moyeu sur l'équerre avec les 4 vis .3125". Mettez de côté.
- Placez les écrous sur les 2 vis courtes, serrez.
- Prenez : 2 équerres simples, 2 vis 1.250", 2 vis .500" avec écrous, 2 entretoises nylon, plaque servo B.
- Placez une équerre simple à l'intérieur du Half-pint, passez les 2 vis 1.250" à gauche (têtes à l'intérieur) et 2 vis .500" à droite.
- Placez la seconde équerre à l'extérieur sur les vis.
- Mettez les entretoises nylon sur les longues vis (1.250"), puis vissez la plaque servo dessus. Serrez.






Étape 6 : Montage du préhenseur - Partie 2
- Placez le second servo dans son support (arbre vers le haut), fixez avec 4 vis .3125".
- Montez le préhenseur sur l'équerre 90° (avec moyeu) : 4 vis .500" avec 2 écrous 8-32 comme entretoises entre équerre et préhenseur. Écrou de blocage par-dessus.
- Placez l'ensemble préhenseur sur le servo, fixez avec la vis de servo fournie.
- Faites passer les deux fils de servo par le trou de la plaque plate vers l'intérieur du robot.





Étape 7 : Montage de l'électronique
- Emboîtez l'UNO et le shield V5.
- Placez l'ensemble dans le support central.
- Collez (double face) le driver moteur à gauche, le module Bluetooth à droite.



Étape 8 : Câblage - Moteurs
- Driver A-1A → pin 5 shield | A-1B → pin 6
- Driver B-1A → pin 3 shield | B-1B → pin 11
Face avant du robot loin de vous :
- Côté GAUCHE : 2 fils NOIRS → borne sortie 1 Moteur A | 2 fils ROUGES → borne sortie 2 Moteur A
- Côté DROIT : 2 fils NOIRS → borne sortie 1 Moteur B | 2 fils ROUGES → borne sortie 2 Moteur B
Servos :
- Servo Y (vertical) → ligne pin 2 shield (fil blanc/orange = signal)
- Servo X (préhensile) → ligne pin 7 shield (fil blanc/orange = signal)
Étape 9 : Câblage module Bluetooth
- Bluetooth Tx → pin 0 shield
- Bluetooth Rx → pin 1 shield
Étape 10 : Alimentation
- Pack piles (5×AA ou 6V/7.2V) → bornes d'alimentation du shield : Rouge → Vcc, Noir → GND
- Vérifiez le cavalier (jumper) sur les broches d'alimentation du shield V5
- GND driver L9110S → GND shield
- Alimentation moteurs (6V/7.2V) → Vcc sur L9110S
- GND moteurs → GND sur driver
Étape 11 : Configuration module Bluetooth HC-05/HC-06
Allez dans les paramètres Bluetooth de votre OS (Panneau de configuration / Système). Notez le nom/numéro du port série assigné.
- Windows
- Linux (ex. blueman sur Linux Mint)
- Mac
Étape 12 : Chargement du code
Après vérification minutieuse du câblage :
- Installez l'Arduino IDE (site officiel).
- Installez la bibliothèque L9110S : décompressez
L9110Driver.zipdans le dossierlibrariesd'Arduino. - Chargez le code robot depuis
blue_t_slave.zip(ou ci-dessous). - Connectez l'Arduino en USB. Outils → Carte → Uno. Outils → Port → votre port COM. Téléversez.
Étape 13 : Lancement de l'application de contrôle Python
Décompressez le fichier Python de l'étape 1. Ouvrez un terminal dans le dossier extrait et lancez :
python rover.py
Une fenêtre "Rover Control Center" doit s'ouvrir. Allumez le robot. Entrez le port COM du module Bluetooth et cliquez Connect. Après quelques secondes, les contrôles s'activent.
Commandes clavier :
- Flèches : avant, arrière, gauche 90°, droite 90°
- a : gauche 45° | s : droite 45°
- h : arrêt (halt)
- y : axe Y préhenseur | u : ouvrir/fermer préhenseur
- c : position home préhenseur
Avant/Arrière = continus (jusqu'à nouvelle commande ou Halt).
Virages 90°/45° = temporaires (arrêt après délai).
Curseurs préhenseur : valeurs 0-180. Y : 0 = haut, 180 = bas. X : 0 = fermé, 180 = ouvert. Il faut cliquer "Set" ou touche correspondante pour exécuter.
Bouton Disconnect : arrête le robot et replace le préhenseur en position home.

Code
Interface de contrôle Python (GUI Tkinter)
#!/usr/bin/env python
# Pour Linux/BSD/Mac : chmod +x pour rendre exécutable
# Rover control app - Scott Beasley 2015 - Libre d'utilisation/modification
import sys, serial, time
from Tkinter import *
import tkFont, tkMessageBox
class App(Frame):
def createWidgets(self):
self.connected = False
self.message = StringVar()
helv6 = tkFont.Font(family='Helvetica', size=6, weight='normal')
self.frame = Frame(self.master); self.frame.pack()
self.f1 = Frame(self.frame)
Label(self.f1, text="Port COM: ").pack(side=LEFT)
self.comm_entry = Entry(self.f1, bd=5, name="comm_entry"); self.comm_entry.pack(side=LEFT)
self.connectButton = Button(self.f1, text="Connect", command=self.SerialConnect, name="b_connect"); self.connectButton.pack(side=LEFT)
self.disconnectButton = Button(self.f1, text="Disconnect", command=self.SerialDisconnect, name="b_disconnect"); self.disconnectButton.pack(side=RIGHT)
self.f1.grid(row=0, column=0)
self.f2 = LabelFrame(self.frame, bd=3, relief="groove", text="Contrôle au sol")
self.g_vert_fm = Frame(self.f2)
self.grip_vert = Scale(self.g_vert_fm, from_=0, to=180)
self.grip_vert.grid(row=0, column=0, rowspan=4, sticky=W)
self.grip_vert_set = Button(self.g_vert_fm, text="Set", command=self.GripperY, name="b_grip_vert_set", width=1, height=2, font=helv6)
self.grip_vert_set.grid(row=5, column=0, sticky=W)
self.master.bind("y", self.GripperY)
self.g_vert_fm.grid(row=0, column=0, rowspan=4, sticky=W)
self.leftforwardButton = Button(self.f2, text="\\", command=self.TurnLeft45, name="b_left_forward"); self.leftforwardButton.grid(row=0, column=1)
self.master.bind("a", self.TurnLeft45)
self.leftButton = Button(self.f2, text="<", command=self.TurnLeft, name="b_left"); self.leftButton.grid(row=1, column=1)
self.master.bind("", self.TurnLeft)
self.rightforwardButton = Button(self.f2, text="/", command=self.TurnRight45, name="b_right_forward"); self.rightforwardButton.grid(row=0, column=3)
self.master.bind("s", self.TurnRight45)
self.haltButton = Button(self.f2, text="Halt!", command=self.Halt, name="b_halt"); self.haltButton.grid(row=1, column=2)
self.master.bind("h", self.Halt)
self.rightButton = Button(self.f2, text=">", command=self.TurnRight, name="b_right"); self.rightButton.grid(row=1, column=3)
self.master.bind("", self.TurnRight)
self.upButton = Button(self.f2, text="^", command=self.Forward, name="b_forward"); self.upButton.grid(row=0, column=2)
self.master.bind("", self.Forward)
self.leftdownButton = Button(self.f2, text="/", command=self.TurnRight45, name="b_left_down"); self.leftdownButton.grid(row=2, column=1)
self.downButton = Button(self.f2, text="V", command=self.Reverse, name="b_reverse"); self.downButton.grid(row=2, column=2)
self.master.bind("", self.Reverse)
self.f2.grid(row=1, column=0, pady=25)
self.rightdownButton = Button(self.f2, text="\\", command=self.TurnLeft45, name="b_right_down"); self.rightdownButton.grid(row=2, column=3)
self.g_horz_fm = Frame(self.f2)
self.grip_horz = Scale(self.g_horz_fm, from_=0, to=180, orient=HORIZONTAL)
self.grip_horz.grid(row=0, column=0, columnspan=7, sticky=E)
self.grip_horz_set = Button(self.g_horz_fm, text="Set", command=self.GripperX, name="b_grip_horz_set", width=1, height=2, font=helv6)
self.grip_horz_set.grid(row=0, column=8)
self.master.bind("u", self.GripperX)
self.g_horz_fm.grid(row=4, column=0, columnspan=7, sticky=E)
self.master.bind("c", self.GripperHome)
self.f3 = Frame(self.frame)
Label(self.f3, text="Dernière action: ").pack(side=LEFT)
Label(self.f3, text=" ", textvariable=self.message).pack(side=RIGHT)
self.f3.grid(row=3, column=0, pady=8)
def CtrlButtonsState(self, bstate):
for btn in [self.leftforwardButton, self.leftButton, self.rightforwardButton, self.rightButton,
self.upButton, self.leftdownButton, self.downButton, self.rightdownButton,
self.haltButton, self.disconnectButton]:
btn.config(state=bstate)
for w in [self.grip_horz, self.grip_vert, self.grip_horz_set, self.grip_vert_set]:
w.config(state=bstate)
def ConnCtrlsState(self, bstate):
self.connectButton.config(state=bstate)
self.comm_entry.config(state=bstate)
def SerialConnect(self):
try:
self.ser = serial.Serial(self.comm_entry.get(), 9600)
except IOError:
tkMessageBox.showerror("Port COM invalide", "Port non trouvé.")
return
self.ConnCtrlsState(DISABLED)
self.CtrlButtonsState(NORMAL)
self.message.set("SerialConnect")
self.connected = True
time.sleep(3)
def SerialDisconnect(self):
try:
self.send_cmd('h', "Halt!")
time.sleep(1)
self.ser.close()
except IOError:
print("Impossible de fermer le port...")
self.message.set("SerialDisconnect")
self.ConnCtrlsState(NORMAL)
self.CtrlButtonsState(DISABLED)
self.connected = False
time.sleep(2)
def send_cmd(self, action, msg):
if self.connected:
for val in action:
self.ser.write(val)
self.ser.flush()
self.message.set(msg)
def TurnLeft(self, event=None): self.send_cmd('a', "Gauche")
def TurnLeft45(self, event=None): self.send_cmd('q', "Gauche45")
def TurnRight(self, event=None): self.send_cmd('s', "Droite")
def TurnRight45(self, event=None): self.send_cmd('e', "Droite45")
def Forward(self, event=None): self.send_cmd('w', "Avant")
def Reverse(self, event=None): self.send_cmd('z', "Arrière")
def Halt(self, event=None): self.send_cmd('h', "Halt!")
def GripperX(self, event=None):
grp_change = ('>', chr(self.grip_horz.get()), chr(255))
self.send_cmd(grp_change, "Préhenseur X")
def GripperY(self, event=None):
grp_change = ('^', chr(self.grip_vert.get()), chr(255))
self.send_cmd(grp_change, "Préhenseur Y")
def GripperHome(self, event=None):
self.send_cmd(('c', chr(255)), "Préhenseur Home")
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.CtrlButtonsState(DISABLED)
def main():
root = Tk()
root.geometry("450x350")
root.wm_title("Rover Control Center (RCC)")
app = App(master=root)
app.mainloop()
if __name__ == '__main__':
main()
Code Arduino (Robot)
/* Bluetooth Rover - Scott Beasley 2015 - Libre d'utilisation/modification
Utilise la bibliothèque L9110S pour pont en H L9110S
Source: https://github.com/jscottb/L9110Driver */
#include <L9110Driver.h>
#include <Servo.h>
#define SERVO_Y 2 // Pin servo Y (vertical)
#define SERVO_CLAW 7 // Pin servo préhenseur
#define pinAIN1 5 // I1
#define pinAIN2 6 // I2
#define pinBIN1 3 // I3
#define pinBIN2 11 // I4
#define MAXFORWARDSPEED 225
#define MAXBACKWARDSPEED 225
#define TOPSPEED 255
#define TURNDELAY 475
#define TURNDELAY45 235
#define BACKUPDELAY 400
#define SERVOMOVEDELAY 200
#define SERVOSEARCHDELAY 85
L9110_Motor motor_left(pinAIN1, pinAIN2);
L9110_Motor motor_right(pinBIN1, pinBIN2);
Servo grip_y_servo;
Servo grip_servo;
void setup() {
Serial.begin(9600);
grip_y_servo.attach(SERVO_Y); grip_y_servo.write(90);
grip_servo.attach(SERVO_CLAW); grip_servo.write(90);
delay(500);
}
void loop() {
byte command = 0, val = 0;
if (Serial.available() > 0) command = Serial.read();
switch (command) {
case 'w': go_forward(); break;
case 'z': go_backward(); break;
case 'a': go_left(); delay(TURNDELAY); halt(); break;
case 's': go_right(); delay(TURNDELAY); halt(); break;
case 'q': go_left(); delay(TURNDELAY45); halt(); break;
case 'e': go_right(); delay(TURNDELAY45); halt(); break;
case 'h': halt(); break;
case '>':
val = Serial.read();
grip_servo.write(constrain(val, 64, 179));
break;
case '^':
val = Serial.read();
grip_y_servo.write(constrain(val, 53, 179));
break;
case 'c':
grip_y_servo.write(90);
grip_servo.write(90);
break;
case 255:
Serial.flush();
break;
}
Serial.flush();
delay(125);
}
void go_forward() {
ramp_it(MAXFORWARDSPEED, FORWARD, FORWARD);
motor_left.setSpeed(MAXFORWARDSPEED); motor_right.setSpeed(MAXFORWARDSPEED);
motor_left.run(FORWARD|RELEASE); motor_right.run(FORWARD|RELEASE);
}
void go_backward() {
ramp_it(MAXBACKWARDSPEED, BACKWARD, BACKWARD);
motor_left.setSpeed(MAXBACKWARDSPEED); motor_right.setSpeed(MAXBACKWARDSPEED);
motor_left.run(BACKWARD|RELEASE); motor_right.run(BACKWARD|RELEASE);
}
void go_left() {
ramp_it(TOPSPEED, BACKWARD, FORWARD);
motor_left.setSpeed(TOPSPEED); motor_right.setSpeed(TOPSPEED);
motor_left.run(BACKWARD|RELEASE); motor_right.run(FORWARD|RELEASE);
}
void go_right() {
ramp_it(TOPSPEED, FORWARD, BACKWARD);
motor_left.setSpeed(TOPSPEED); motor_right.setSpeed(TOPSPEED);
motor_left.run(FORWARD|RELEASE); motor_right.run(BACKWARD|RELEASE);
}
void halt() {
motor_left.setSpeed(0); motor_right.setSpeed(0);
motor_left.run(BRAKE); motor_right.run(BRAKE);
}
void ramp_it(uint8_t speed, uint8_t lf_dir, uint8_t rt_dir) {
uint8_t ramp_val = 0, step_val = 0;
step_val = abs(speed / 4);
if (!speed) step_val = -step_val;
for (uint8_t i = 0; i < 4; i++) {
ramp_val += step_val;
motor_left.setSpeed(ramp_val); motor_right.setSpeed(ramp_val);
motor_left.run(lf_dir|RELEASE); motor_right.run(rt_dir|RELEASE);
delay(25);
}
}
Bibliothèque L9110 Driver
Driver moteur L9110 pour Arduino : GitHub
Pièces personnalisées et boîtiers
4wdgripperbt2.fzz
Schémas
4wdgripperbt2.fzz (Fritzing)
Processus de fabrication
- Système de Capteur de Température Multi-Position pour Intégration Domotique
- Contrôleur DIY pour fer à souder 862D+ — Précision et fiabilité
- MotionSense : Détection d'intrusion intelligente avec Arduino et ESP8266
- Prévention incendie imprimante 3D : Système de sécurité à capteur intelligent
- Lévitation magnétique répulsive avec Arduino : circuit simple et guide DIY
- Enregistreur de données Arduino haute performance pour ballon météo
- CoroFence : Détecteur Thermique Avancé PIR + Capteur Grid-EYE & IoT
- Surveillance Cloud : système de contrôle à distance pour la gestion d'actifs en temps réel
- 5 avantages clés du contrôle de production à distance pour l'industrie moderne


