Après avoir démonté mon moteur suite à quelques soucis mécaniques, j’ai voulu en savoir plus sur son fonctionnement. Le système Bosch est propriétaire, peu documenté et du coup, assez mystérieux. Pourtant, il est extrêmement répandu. J’ai donc supposé qu’il était particulièrement verrouillé, c’est pourquoi j’ai attendu si longtemps avant de m’y attarder.
Une autre chose qui m’a toujours parue énigmatique sont les puces de débridages. Toutes interfèrent sur le capteur de vitesse de la roue, en général un aimant fixé sur un rayon et un ILS sur le cadre. En faussant les impulsions envoyées, on peut faire croire que le vélo roule plus lentement qu’en réalité. Jusque là, rien de sorcier. Beaucoup de puces de premières générations se contentaient de renvoyer une impulsion sur 2. L’inconvénient était que le compteur indiquait des vitesses et distances également divisées par 2.
Les puces plus récentes, en revanche, permettent de conserver un affichage des vitesses et distances correctes sur le compteur d’origine. Comment réussissent-elles l’exploit de désactiver le bridage alors que le système connaît (puisqu’il l’affiche) la vraie vitesse du vélo ? Comment l’ajout d’une « puce » peut modifier le comportement d’un firmware particulièrement sophistiqué ?
Un jour, j’ai compris, et c’est tout bête. Pour m’amuser et valider mes hypothèses, j’ai décidé de créer ma propre puce de débridage et de démystifier un peu leur fonctionnement.
Remarque n°1 : débrider un VAE n’est pas un acte anodin et cet article n’a pas pour but de l’encourager mais de transmettre des connaissances techniques.
Remarque n°2 : un VAE débridé devient assimilable à un véhicule à moteur non homologué et par conséquent impossible à assurer. En cas d’accident corporel, les conséquences peuvent être désastreuses.
Remarque n°3 : Bosch lutte activement contre le débridage de ses vélos. On trouve même des rumeurs qui affirment qu’après trop de détections, le moteur pourrait se bricker définitivement. En pratique, il semble que les 3 premières fois, il suffise de pédaler un certain temps avec l’assistance réduite pour désactiver la punition, mais qu’au bout de la 4è, il faille utiliser Bosch Diagnostic Tool (source). Évidemment, cela engendre l’annulation de la garantie.
Pour finir : il existe actuellement 2 grandes générations de systèmes Bosch :
- La génération « historique » (de 2014 à 2022, peut-être même dès 2011 d’après certaines sources). Les équipement suivants en font partie :
- Batteries Powerpack 300, 400, 500 ; Powertube 400, 500, 625
- Ecrans Intuvia, Purion, Kiox et Nyon
- La nouvelle génération appelée « Smart System » ou « Le système intelligent » qui a vu le jour en 2022 :
- Batteries Powerpack 400, 500, 545, 800 ; Powertube 540, 625, 750, 800
- Ordinateur de bord Kiox 300 et Intuvia 100
Les dénominations commerciales des moteurs sont restées identiques (Active Line, Active Line Plus, Performance Line, Performance Line CX) même si les moteurs eux-même ont évolué au fil des années. Par conséquent, on peut trouver des moteurs très différents derrière les mêmes appellations.
Tout ce que je dirai dans la suite ne s’applique qu’à la première génération (non Smart System).
On peut aussi supposer que les techniques de détection se sont améliorées avec les mises à jour logicielles. Dans le doute, je ne les ai jamais réalisées. Pour info, ce qui suit a été testé dans les conditions suivantes :
- Intuvia : matériel V0.0.2.2, logiciel V5.9.2.0
- Moteur Performance Line Speed Gen2 (BDU390) : matériel V0.0.6.0, logiciel V1.8.6.0
Le début : un bus CAN
Un bus CAN relie la batterie, le moteur et le compteur. Sa vitesse est de 500 kbits/s. Compte tenu de son câblage, on devrait trouver une résistance de terminaison de 120Ω dans la batterie et le compteur, qui correspondent physiquement aux extrémités du bus. En réalité, il y a seulement une résistance de 60Ω dans le moteur. Bon, pourquoi pas. Le câblage est court, cela ne pose pas de problème.

Le moteur s’alimente en 36V par la batterie et fournit 10,8V au compteur. La couleur des fils sur le schéma ci-dessus correspond à la réalité.
Pour se connecter au bus et faire les premiers essais, le moyen le plus simple est de se repiquer sur le port de charge de la batterie :

Grâce à lui, il est possible de récupérer plein d’informations intéressantes normalement inaccessibles, notamment :
- Tension, courant et puissance délivrés par la batterie,
- Couple appliqué par le cycliste sur les pédales,
- Cadence de pédalage,
- Puissance moteur,
- Températures batterie et moteur,
- SOC batterie précis (la console Intuvia donne seulement l’information avec 5 « barres »)
- etc.
A la base, je voulais simplement connaître la puissance réelle du moteur (et insérer une pince ampèremétrique sur un fil d’alim en roulant n’était pas pratique). J’ai alors eu l’idée de remplacer, via le principe du Man-In-The-Middle, certaines données affichées sur l’écran par d’autres. Par exemple, afficher la puissance instantanée du moteur à la place de la vitesse ou de l’odomètre. Il faut pour cela intercaler un système entre le couple batterie/moteur et l’écran :

En temps normal, le système retransmet toutes les trames sans les modifier. Il est alors transparent et tout fonctionne normalement. Lorsqu’il voit passer une trame contenant la puissance moteur, il la mémorise. Plus tard, lorsqu’il verra passer une trame contenant la distance parcourue, il va l’intercepter et remplacer sa valeur par la puissance mémorisée. Ainsi, le compteur l’affichera à la place de la distance parcourue. Évidemment, les unités ne changeront pas par magie, et la « puissance » restera affichée en kilomètres/heure.
Réalisation matérielle du Man-In-The-Middle
Il faut donc un microcontrôleur avec deux interfaces CAN. Dans la famille STM32, les moins chers sont les STM32F105. Je pensais partir d’une carte Nucleo avec un MCU de cette famille et y ajouter le nécessaire sur du Veroboard, mais je suis tombé par hasard sur ces chinoiseries :

Un STM32F105, deux transceivers CAN, deux régulateurs de tension (probablement 3,3V et 5V)… Bingo, je ne sais pas vraiment à quoi ça sert, mais c’est ce qu’il me faut ! Il y a même un emplacement pour un header au pas de 2,54mm, avec un peu de chance pour l’interface de programmation. Je vais donc partir de cette base matérielle qui me fera gagner beaucoup de temps.
Après quelques recherches, je tombe sur ce site : https://dangerouspayload.com/2020/03/10/hacking-a-mileage-manipulator-can-bus-filter-device. Pas de surprise, il s’agit d’un circuit qui réalise un MITM sur un bus CAN, destiné en l’occurrence à trafiquer l’affichage du compteur kilométrique des voitures.
L’auteur s’est même donné la peine de dessiner le schéma et m’épargne cette étape. Il ne reste donc plus qu’à écrire le soft, mais avant, il faut juste gérer un cas particulier :
Pour allumer le vélo, l’ordinateur de bord (alors alimenté par sa batterie interne pour les Intuvia et Kiox, ou par sa pile CR2032 pour les Purion) écrit sur le bus, ce qui « réveille » la batterie et alimente le système. À noter que si elle est vide, il est toujours possible d’allumer le vélo grâce à un bouton présent sur la batterie elle-même, mais il n’est pas très accessible.
Bref, le MITM n’étant pas sous tension lorsque le vélo est éteint, les demandes d’allumage émanant du compteur ne parviendront plus à la batterie. Pour résoudre le problème, j’ajoute un relais 2RT, avec les contacts normalement fermés câblés de telle sorte à rétablir la continuité du bus lorsque l’alimentation est absente :

En pratique, le câblage ressemble donc à ceci (la bobine du relais n’est pas représentée) :

J’ai dû ajouter une résistance de 120 Ω, sinon aucune résistance de terminaison n’était présente sur le second bus CAN reliant la partie droite du MITM au compteur.
J’ai aussi rajouté des pull-ups entre le µC et le transceiver CAN pour fixer l’état des signaux. Sinon, lorsque le MCU était en reset et son TX par conséquent flottant, le vélo s’allumait occasionnellement sans intervention de ma part. Accessoirement, cela nous montre qu’il n’y a pas besoin d’envoyer une trame CAN valide pour allumer la batterie, une impulsion quelconque suffit.
La bobine du relais est pilotée par un transistor depuis un GPIO pour pouvoir facilement basculer entre le mode « connexion directe » et « MITM » via le soft.


Pour les essais, j’ai voulu garder le circuit accessible et ne pas l’intégrer sous le carter du moteur comme c’est fait habituellement. J’ai donc coupé le câble reliant le moteur au compteur au niveau du guidon. J’ai mis des connecteurs mâle et femelle pour pouvoir facilement rétablir la connexion sans la puce quand je ne m’en sers pas.

C’est fini pour le matériel, on peut commencer le logiciel.
Logiciel du MITM
Les trames transportant les informations essentielles ont déjà été identifiées par la communauté (cf. sources et remerciements à la fin de l’article). Pour commencer, je créé une structure contenant toutes les informations possibles que je visualiserai avec le debugguer.
Il suffit de la remplir lorsqu’un message intéressant arrive :
Pour finir, il ne reste plus qu’à capturer l’information au passage puis la retransmettre de l’autre côté quand un message est reçu :
Le vélo s’allume, fonctionne bien (c’est déjà une petite victoire !) et on récupère comme prévu plein d’infos très intéressantes :

Ci-dessous, quelques constats en vrac :
- Certains messages CAN transitent dans les deux sens, ce qui est assez étrange. Par exemple, on peut s’attendre à ce que la tension de la batterie provienne uniquement du bus CAN de gauche (sur mon schéma). Pourtant, on voit aussi venir cet ID depuis le bus de droite. Comme si l’ordinateur de bord, après l’avoir reçu de la batterie, le renvoyait.
Mais ce n’est pas le cas de tous. Par exemple, ce phénomène n’est pas présent pour la vitesse du vélo ou le SOC.
J’ai mis, dans les commentaires en face de chaque champ de la structure :=>si l’ID vient uniquement de la gauche<=s’il vient de la droite<=>s’il circule dans les deux directions.
- Le moteur transmet seulement la distance totale parcourue par le vélo (odomètre). Le totaliseur journalier (celui que l’on peut remettre à zéro à tout moment) est donc calculé au niveau du compteur via celui-ci : lorsqu’il détecte son incrémentation, il incrémente aussi le journalier.
Du coup, les affichages que l’on peut pirater sur l’Intuvia ne sont pas très nombreux :- L’estimation d’autonomie restante (0-XXX km)
- L’odomètre (mais le totaliseur journalier part dans les choux, et sature rapidement à 99 999 km)
- La vitesse
- L’indicateur suggérant un changement de pignon (une flèche vers le haut, une flèche vers le bas)
- Je n’ai pas réussi à modifier l’affichage du bargraph de puissance, ainsi que le nombre de barres dans le symbole batterie. Modifier la puissance moteur dans le message 0x0D4 ou le SOC dans le message 0x111 ne suffit pas. Ces infos doivent être transmise dans d’autres trames.
- Puisque mon vélo est homologué 45 km/h, je ne peux pas éteindre les phares (décret 2007-271). Sur mon Intuvia, l’icône des phares dessinée sur le bouton permettant normalement de les allumer/éteindre a été masquée par un autocollant 😂. L’appui dessus remonte quand même les trames sur le bus.
En tant que preuve de concept, j’ai remplacé :
- la vitesse par la puissance du moteur divisée par 10
- l’estimation d’autonomie restante par le SOC de la batterie
Je recycle le bouton des phares qui m’est inutile pour activer ou non le MITM. Voici le résultat :
On voit donc un SOC à 100% (qui me permet de parcourir 26km – ma batterie est un peu usée) et que la puissance maximale du moteur se situe autour de 650W. Il s’agit ici de la puissance électrique absorbée par le moteur et non la puissance mécanique.
Cette puissance n’est obtenue que lorsque la batterie est chargée à fond. Par exemple, lorsque le SOC est aux alentours de 40%, alors la puissance max est plutôt de l’ordre de 550W.
Puce de débridage DIY
Théorie
Finalement, pour débrider un vélo, il suffit de mettre deux Man-In-The-Middle :
- un pour modifier les informations du capteur de vitesse et faire croire au moteur que la roue tourne moins vite qu’en réalité,
- un autre pour corriger la vitesse affichée à l’écran et remettre la bonne vitesse.

Et c’est tout… La puce ne retire pas le bridage du moteur à proprement parler !
J’ai quand même voulu vérifier mes hypothèses en fabriquant un prototype.
Mise en oeuvre matérielle
Le capteur de vitesse sur la roue est probablement un simple ILS. Quand on le débranche, l’erreur remontée par Bosch Diagnostic Tool va dans ce sens :

Un coup de multimètre permet de lever tout doute : le contact est polarisé en 3,3V et le courant qui le traverse, lorsqu’il est fermé, est 1mA.
Je vais donc ajouter au circuit précédent une entrée pour brancher l’ILS et un optocoupleur pour le simuler auprès du moteur. Je me connecte sur des ponts de soudure qui permettaient de choisir le comportement du firmware d’origine. J’ajoute aussi deux LEDs, c’est toujours pratique pour le debug :

Physiquement, j’ai tiré un câble 4 conducteurs pour amener les signaux jusqu’au guidon. Sur ces 4 conducteurs, deux sont connectés au capteur, les deux autres à l’entrée idoine du moteur. J’ai monté un connecteur différent de ceux du bus CAN afin qu’il n’y ait pas d’erreur de câblage possible. Lorsque je n’utilise pas la puce, j’installe un pont qui rétablit la continuité du capteur au moteur :

Avec la puce installée :

Pour mettre au point confortablement le soft, il faut pouvoir pédaler en gardant le vélo immobile. Voilà le mieux que j’ai trouvé pour soulever la roue arrière :

Côté logiciel (strict minimum)
Le minimum pour outrepasser la vitesse limite est l’algorithme suivant (les vitesses indiquées ne sont que des exemples, adaptées à bridage initial à 45 km/h) :

En gros, à partir d’une certaine vitesse (lue via l’ILS, dans mon cas 38 km/h), le débridage entre en action et la puce envoie au moteur des impulsions simulées correspondant à une vitesse inférieure (ici 30km/h). En parallèle, le contenu des trames envoyant la vitesse à l’écran est corrigé pour afficher la bonne vitesse.
Pour limiter les risques de détection du débridage, il peut être judicieux de :
- Ne pas envoyer une vitesse constante pendant trop de temps (cela n’arriverait jamais en pratique). Il faudrait la faire fluctuer un peu.
- Idéalement, il faudrait même qu’elle soit proportionnelle à la cadence de pédalage (le coefficient peut toutefois changer de temps en temps, cela correspondrait à un changement de pignon sur la cassette).
- Dans Bosch Diagnostic Tool, le rapport de réduction mini et maxi de la transmission est renseigné et impossible à modifier. C’est le nombre de dents de la cassette divisé par le nombre de dents du pignon moteur. Il faudrait aussi rester dans cette plage.
- La durée de l’impulsion (correspondant au moment où l’aimant est devant l’ILS) est censée être également proportionnelle à la vitesse à laquelle s’attend le moteur.
- Un coup d’oscilloscope montre même que le passage de l’aimant devant le capteur génère 2 impulsions successives (et ce n’est pas un rebond). Peut-être faudrait-il également reproduire ce comportement.
En pratique, je n’ai pas pris ces précautions et mon moteur n’est jamais passé en mode dégradé.
Attention, j’ai un moteur de génération 2, qui date de 2019, sur lequel je n’ai jamais fait de mise à jour. Les nouveaux modèles sont peut-être mieux protégés !
Ajout du correctif de l’odomètre
Cet algorithme simpliste permet d’outrepasser la vitesse limite tout en affichant la bonne à l’écran, mais l’odomètre (total et journalier) stocké dans le moteur est sous-estimé puisque le vélo croit qu’il roule plus lentement.
On pourrait stocker dans la mémoire interne de la puce le vrai kilométrage et l’envoyer au compteur, comme c’est fait pour la vitesse. L’inconvénient est que si elle est un jour retirée ou tombe en panne, la correction disparaîtrait et le kilométrage affiché n’aurait plus aucune signification. C’est dommage, il faudrait trouver quelque chose de plus élégant.
Et si, lorsque le vélo est à l’arrêt, on lui faisait croire qu’il roule hyper vite pour récupérer rapidement les kilomètres manquants ? On dépasserait largement la vitesse de bridage, donc l’assistance serait désactivée, mais ce n’est pas gênant puisqu’on est immobile. Pour le vélo, ce serait semblable au cas où on serait dans une grande descente sans pédaler.
L’algorithme devient alors :

Il y a 2 subtilités ici :
- Quand le vélo est immobile et qu’on envoie rapidement les impulsions manquantes, le moteur croit qu’il roule vite. En mettant du couple sur les pédales pour démarrer, l’assistance ne s’activera donc pas. Il est donc judicieux d’envoyer les impulsions manquantes seulement lorsque le vélo est immobile ET qu’on ne force pas sur les pédales (facile, le moteur renvoie cette info).
- Comme précédemment, il serait approprié d’envoyer une vitesse qui fluctue légèrement pendant le rattrapage d’impulsions, pour éviter une détection du débridage.
- Plutôt que d’afficher une vitesse nulle, on pourrait afficher une sorte de décompte a l’avantage d’indiquer la fin de l’opération. C’est ce qui est réalisé sur certaines puces commerciales.
Analyse d’une puce commerciale (Speedbox)
Nous avons donc trouvé une solution permettant de débrider notre vélo, tout en gardant toutes les informations affichées correctes. Il serait intéressant d’analyser le fonctionnement des puces existantes sur le marché, pour savoir si elles fonctionnent exactement de la même manière ou pas.
Évidemment, je n’en possède pas et ne souhaite pas en acheter. On va donc extrapoler quelques informations à partir de la fiche technique d’une puce répandue, la Speedbox :

Cette puce affiche bien la vitesse et l’odomètre réels. Dans le descriptif, il est bien indiqué qu’après un trajet, il faut attendre un certain temps avant d’éteindre le vélo :

Cela laisse supposer que le rattrapage de l’odomètre se fait comme sur la nôtre. Pour inciter leurs clients à bien attendre la fin du décompte (et éviter qu’ils se plaignent sinon que l’odomètre est faussé), rien de tel que de brandir la menace d’une détection par Bosch :

Dans sa gamme Smart System, Bosch a comblé les failles précédentes. A l’heure actuelle (novembre 2025), aucune puce, à ma connaissance, ne permet de débrider ces vélos en conservant l’affichage de la vitesse correcte sur le compteur d’origine :

Speedbox contourne le problème en fournissant une application smartphone qui l’affiche à la place. La distance parcourue est elle correcte, mais seulement une fois le vélo arrêté et les impulsions rattrapées.
Un mot sur le passage en mode dégradé (« limp mode »)
Si un débridage a été détecté dans la durée de vie du produit, cette information est enregistrée irrémédiablement par le moteur et visible depuis Bosch Diagnostic Tool.
Durant certains essais (je l’ai un peu cherché : j’ai simulé des impulsions à vitesse constante pendant l’équivalent de 15 km…), le code d’erreur 503 s’est déclenché :

Contrairement à d’habitude, celui-ci ne pouvait pas être effacé en cliquant sur la croix rouge. Je m’attendais à ce que la ligne « Manipulation » passe définitivement à « Oui », mais ça n’a pas été le cas (bizarre, mais tant mieux pour moi).
Je m’attendais donc à subir le fameux « limp mode » (assistance fortement réduite et nécessité de rouler 90 minutes dans ces conditions pour en sortir). Mais surprise : le comportement est très différent de celui lu sur les forums :
- À faible cadence de pédalage, la puissance de l’assistance ne semble pas réduite, quoique très « brusque », bien loin de la souplesse et de la fluidité habituelle.
- Par contre, l’assistance se coupe à partir d’une cadence de pédalage moyenne. La conséquence est que sur le grand pignon, l’assistance se désactive à très faible vitesse (je n’ai plus la valeur en tête) mais en contrepartie… je peux dépasser allégrement les 50 km/h sur le plus petit pignon, car ma cassette offre un développement très long 😂.
Vraiment très étrange. Et je n’ai pas eu le temps de bien investiguer, car tout est revenu à la normale après quelques minutes seulement.
Conclusion
Je suis très étonné par la discordance entre la sophistication apparente du système Bosch et la simplicité que j’ai eue pour le débrider.
Les ingénieurs ont développé le système vraiment élaboré et pointu sur certains aspects (Bosch Diagnostic Tool, mode Dual Battery, authentification de la batterie inviolé jusqu’à très récemment, compatibilité entre TOUS les équipements (batteries, moteurs et compteurs) de leurs VAE pendant plus de 10 ans, etc.) alors que certaines protections élémentaires ont été omises.
En particulier : il y a énormément de trafic sur le bus CAN, et finalement peu de trames ont été décodées. Il serait très simple de détecter la présence d’un MITM : lorsqu’une information circule dans un sens (par exemple, le moteur envoie la vitesse au compteur), le destinataire pourrait renvoyer, noyé dans la masse d’information, un checksum de cette valeur, calculé avec un algorithme secret. Ainsi, l’émetteur pourrait très simplement vérifier si la valeur reçue par le destinataire est bien celle qu’il a envoyé.
J’ai au début cru que cette méthode était employée, car certains messages CAN transitent dans les deux sens. Mais puisque les données sont en clair à l’intérieur, cela n’a aucun intérêt. De plus, on trouve ce phénomène sur certains messages relativement « inutiles », comme les flèches suggérant un changement de rapport de cassette, alors que certains messages « sensibles », comme la vitesse, n’y sont pas soumis.
Remerciements – sources
La majorité du décodage du bus CAN n’est pas de moi. Beaucoup de choses semblent venir initialement de ce thread : https://www.pedelecforum.de/forum/index.php?threads/bosch-active-can-daten-sammlung.40358/page-5 et on été reprises ailleurs.
En vrac, voici certains liens complémentaires :
- https://git.cccfr.de/bosch-nerds/ebike (d’autres liens en allemand sont intéressants à la fin)
- https://apollo.open-resource.org/lab:wip:bosch
- https://en.ebiketuningshop.com/blogs/motoren/bosch-smart-system-mit-felgenmagnet-fachwissen-and-tuning-optionen
- https://ebiketuning.com/collections/ebt/products/ebt-unlock-key-1 ce site Web propose de débrider un vélo Bosch de manière purement logicielle. C’est très intéressant, mais évidemment, les vitesses et distances restent fausses. Je pense que les concepteurs ont trouvé comment modifier le diamètre de la roue programmé en usine (en temps normal, même Bosch Diagnostic Tool ne permet pas de le faire)
- https://en.ebiketuningshop.com/pages/bosch-tuning
- https://en.ebiketuningshop.com/bosch-gen4-motoren
- https://www.vtt12v.ovh/vttae-bosch/erreurs-display-bosch
- Famille de connecteurs utilisés sur le moteur Bosch : https://www.te.com/en/product-2141467-2.html
- https://ebiketuner.com/blogs/news/how-to-derestrict-a-bosch-ebike
- https://www.youtube.com/watch?v=hbOgFicC70k