
1. 项目概述从千元梦想到底层实现作为一名玩了十几年自行车改装的老玩家我始终对高端公路车上那套丝滑的电子变速系统念念不忘。手指轻点按钮变速器“咔哒”一声精准到位没有线缆的滞涩感尤其在全力摇车爬坡时那种稳定可靠的换挡体验是任何机械变速都难以比拟的。然而看一眼Shimano Di2或SRAM eTap那动辄五位数的售价又只能默默把口水咽回去。难道这项“黑科技”真的与普通爱好者无缘吗当然不是。技术的乐趣就在于拆解与重建。这个项目就是一次彻底的“祛魅”之旅用一颗售价不到10块钱的ATtiny85微控制器一个常见的RC遥控车舵机辅以巧妙的3D打印结构和极致的低功耗设计亲手打造一套属于自己的电子变速系统总成本可以轻松控制在百元以内。它可能没有原厂件那般极致轻量和完美集成但其核心逻辑——将你的换挡意图转化为精准的机械动作——是完全相通的。更重要的是通过这个过程你将彻底理解电子变速是如何“思考”和“执行”的这种掌控感是花钱买成品永远无法获得的。这套DIY系统的核心目标非常明确可靠、低功耗、可定制。它不是为了在环法赛场上与职业车手竞技而是为了给通勤车、老式旅行车甚至是一辆你舍不得扔的“老爷车”注入新的智能灵魂。想象一下在车把上安装两个小巧的防水按钮拇指轻轻一推就能完成变速无需担心线管老化、变速不准系统绝大部分时间处于深度睡眠一次充电可以续航数月之久。这就是本项目的终极愿景让智能骑行的门槛降低到每一个有动手意愿的爱好者触手可及的程度。2. 核心设计思路与方案选型2.1 为什么是ATtiny85与RC伺服在构思这套系统时元器件选型是第一个需要攻克的难题。市面上微控制器种类繁多从功能强大的ESP32到经典的Arduino Uno为何偏偏选中了这颗仅有8个引脚的ATtiny85首要原因是“恰到好处的性能与极致的低功耗”。电子变速器不是一个需要复杂计算或网络连接的设备它的核心任务非常简单检测按钮信号根据预设位置表驱动舵机转动特定角度然后继续睡觉。ATtiny85运行在8MHz下足以流畅处理这些任务而其真正的杀手锏是深度睡眠模式。在睡眠状态下其电流消耗可以低至0.1微安级别这意味着即使使用一颗普通的CR2032纽扣电池也能轻松待机数年。这对于一个需要长期挂在车上、又不能频繁充电的设备来说是至关重要的。其次极小的体积与成本。ATtiny85的DIP封装加上一个8脚插座体积比一枚硬币还小成本仅几元钱。这让我们可以将整个控制电路做得非常紧凑方便塞进车把末端的把堵或一个小型防水盒里。那么执行机构为什么选择RC舵机而不是步进电机或直线电机答案在于“开环控制下的位置保持与足够扭矩”。高品质的RC舵机内部集成了电机、减速齿轮组和电位器反馈电路形成了一个完整的闭环位置控制系统。我们只需要发送一个PWM信号指定目标角度舵机就会自己驱动到那个位置并保持住只要持续供电。这对于变速这种需要精确角度定位的应用来说几乎是“傻瓜式”的解决方案大大简化了我们的驱动电路和代码逻辑。MG996R这类金属齿轮舵机能提供超过10kg·cm的扭矩足以拉动拆除回位弹簧后的后拨链器。2.2 系统架构与能量管理哲学整个系统的架构围绕低功耗展开可以看作一个“沉睡的哨兵”。其工作流如下常态系统处于深度睡眠状态。ATtiny85休眠控制舵机电源的MOSFET电路关闭舵机不通电。此时仅由CR2032电池为ATtiny85的睡眠电路和中断唤醒引脚提供微安级电流。USB充电宝完全断开。唤醒当车把上的升档或降档按钮被按下时会触发ATtiny85的引脚变化中断。这个中断信号能将微控制器从最深度的睡眠中瞬间唤醒。执行ATtiny85唤醒后首先会打开一个P-MOSFET这个MOSFET作为“总开关”接通USB充电宝为整个系统主要是舵机供电。接着根据被按下的按钮查询内置的“换挡位置表”生成对应的PWM信号驱动舵机旋转到目标档位。再休眠舵机到位并短暂保持后代码会先关闭舵机电源的MOSFET然后将ATtiny85自身再次配置为深度睡眠模式等待下一次中断。整个活动周期可能只有1-2秒。注意这里有一个关键设计细节——“双电源系统”。舵机工作电流瞬间可达1-2ACR2032电池根本无法承受。因此采用USB充电宝容量大可充电作为舵机的动力源。而ATtiny85的待机则由CR2032负责因为它的睡眠电流极小一颗电池就能用很久。两个电源通过MOSFET电路隔离避免了充电宝在休眠时的静态电流损耗。这种设计确保了无论是动力系统还是控制系统都能在能效上做到最优。2.3 机械改造拆除弹簧与3D打印连接件原项目的机械部分是一个亮点也是一个需要深刻理解其妥协与权衡的地方。作者移除了后拨链器以下简称“后拨”内部的两根核心弹簧一是负责将链条拉向小飞轮的张力弹簧二是负责在变速时引导链条横向移动的回位弹簧。为什么这么做因为舵机的扭矩虽然可观但要同时对抗这两根为人力操作设计的、弹力十足的弹簧依然会非常吃力导致反应迟钝、耗电剧增甚至烧毁舵机。拆除弹簧后后拨就变成了一个“无阻力”的摆臂舵机可以轻松地将其推到任意位置。带来的问题与解决方案拆除弹簧后后拨失去了自动回位或保持张力的能力。这导致两个问题1. 遇到颠簸时后拨可能因震动而错位导致掉链2. 链条张力完全由变速器本身的结构限位和链条刚性维持在某些档位可能张力不足。对于问题1作者的解决方案是设计一个3D打印的舵机支架将舵机机身牢固地固定在自行车后下叉或尾钩上舵机摇臂则通过一个连杆与后拨的固定臂原装线管拉线处硬连接。这样舵机摇臂的转角就直接对应后拨的横向位置。对于问题2以及更理想的“自锁”方案作者提到了蜗轮蜗杆机构。这是工程上一个非常巧妙的思路。如果能在舵机输出轴后级加入一套蜗轮蜗杆利用其反向自锁的特性蜗杆可以驱动蜗轮但蜗轮很难反向驱动蜗杆那么即使在舵机断电后后拨的位置也能被机械锁死抗震性极大提升同时也不再需要舵机持续通电来维持位置省电。这对于DIY来说是一个高阶的改进方向。3. 硬件电路详解与制作要点3.1 核心电路原理图分析整个电路可以划分为三个功能模块微控制器最小系统、电源切换模块和用户输入模块。ATtiny85最小系统这是大脑。包括ATtiny85芯片、其电源滤波电容通常为0.1uF贴片电容、以及连接编程接口的6个引脚RESET, MOSI, MISO, SCK, VCC, GND。VCC直接连接至CR2032电池的正极。这里特别注意为了让深度睡眠更彻底我们将ATtiny85的电源电压检测BOD功能在编程时禁用。电源切换模块关键这是项目的节能核心由两个MOSFET和一个肖特基二极管构成。P-MOSFET (如AO3401)其源极S接USB充电宝的5V输出漏极D输出给舵机和ATtiny85的VCC当需要时。栅极G通过一个10k电阻上拉到源极即5V。初始状态栅极为高电平P-MOSFET关闭5V无法输出。控制逻辑当需要换挡时ATtiny85的一个I/O引脚例如PB3输出低电平0V。这个低电平会拉低P-MOSFET的栅极电压使其导通5V主电源被接通。N-MOSFET (如AO3400)与肖特基二极管为什么需要它们因为舵机是感性负载断电时会产生反向电动势。在P-MOSFET的漏极和地之间我们反向并联一个肖特基二极管阴极接5V阳极接地可以快速泄放这个反向电流保护MOSFET。N-MOSFET在这里可能用于更精确地控制舵机信号地的通断形成一个“双开关”确保彻底断电但更简化的设计可以省略N-MOSFET仅用P-MOSFET控制正极电源。用户输入模块两个轻触开关分别接在ATtiny85的两个支持中断的引脚如PCINT0和PCINT1与地之间。引脚内部通过代码启用上拉电阻。平时引脚被上拉到高电平按下按钮时接地变为低电平触发中断。3.2 焊接与组装实操指南电路搭建推荐使用万用板洞洞板因为元件数量不多布局灵活。步骤与心得规划布局在纸上或脑海里先规划好元件位置。将ATtiny85的8脚插座放在板子中央。电源输入USB口、CR2032电池座放在一侧输出舵机接口、按钮引线放在另一侧。MOSFET和贴片电阻、二极管可以集中在ATtiny85旁边。先贴片后直插优先焊接贴片元件MOSFET、电阻、LED、二极管。使用尖头烙铁和细焊锡丝。焊接MOSFET时动作要快防止过热损坏。可以在焊盘上先上一点锡然后用镊子夹住元件对准烙铁头点一下即可。焊接直插元件与连线接着焊接IC插座、按钮、USB母座、舵机接口可用一个3针排母代替。然后用细导线如AWG30的硅胶线或者利用万用板背面的铜箔走线连接各个部分。务必注意电源正负极VCC/GND不要短路。可以在关键节点如5V输入、ATtiny85的VCC引脚并联一个100uF的电解电容和一个0.1uF的瓷片电容以稳定电源防止舵机动作时电压骤降导致单片机复位。外接接口通过三芯线信号、电源、地连接舵机。通过两芯线连接两个按钮。所有外部引线接头建议使用热缩管保护并考虑一定的应变 relief例如在出线口打结或用扎带固定。绝缘与封装焊接完成后用万用表通断档仔细检查有无短路、虚焊。确认无误后可以用绝缘胶带或热熔胶将裸露的焊点和导线固定绝缘。最后将整个电路板装入尺寸合适的防水塑料盒如作者用的补胎盒在对应按钮和出线口开孔。避坑提示舵机的电源线红、黑务必足够粗建议AWG22以上且从电路板到舵机的距离不宜过长以减少压降。舵机信号线黄或白可以细一些。如果通电后舵机抖动或不动作首先检查电源电压是否稳定应在4.8V-6V之间其次检查信号线连接是否可靠。4. 软件编程低功耗逻辑与换挡算法4.1 开发环境搭建与芯片编程ATtiny85不是Arduino官方板需要安装第三方支持包。最常用的是Spence Konde的ATTinyCore。设置步骤打开Arduino IDE进入“文件 - 首选项”在“附加开发板管理器网址”中添加https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json打开“工具 - 开发板 - 开发板管理器”搜索“attiny”安装“ATTinyCore”。安装完成后在“工具”菜单下依次选择开发板ATtiny25/45/85处理器ATtiny85时钟8 MHz (internal)编程器USBtinyISP (如果你使用的是这种编程器)其他选项建议关闭BODB.O.D. Level - B.O.D. Disabled以达成最低功耗。编程硬件连接你需要一个USBtinyISP之类的编程器或者按照网上教程将一个Arduino Uno配置成“Arduino as ISP”来给ATtiny85烧录程序。连接时注意对应引脚MOSI, MISO, SCK, RESET, VCC, GND。将编写好的代码点击“通过编程器上传”即可烧录。4.2 核心代码逻辑剖析代码的核心围绕着中断唤醒和换挡位置表展开。#include avr/sleep.h #include avr/power.h #include Servo.h // 引脚定义 const int buttonUp 0; // PCINT0升档按钮 const int buttonDown 1; // PCINT1降档按钮 const int powerGate 3; // PB3控制P-MOSFET的引脚 const int servoPin 4; // PB4舵机信号引脚 Servo derailleurServo; volatile bool shiftRequested false; volatile int requestedDirection 0; // 0无1升档-1降档 int currentGear 1; // 假设初始在最小飞轮1档 const int totalGears 6; // 6速飞轮 // 核心换挡位置查找表。数值代表舵机角度0-180。 // 通常升档和降档到同一档位所需的角度略有不同以确保变速干脆利落。 int upShiftPositions[6] {30, 50, 70, 90, 110, 130}; // 从1档升到2、3...6档的目标角度 int downShiftPositions[6] {25, 45, 65, 85, 105, 125}; // 从2、3...6档降到1档的目标角度 void setup() { pinMode(buttonUp, INPUT_PULLUP); pinMode(buttonDown, INPUT_PULLUP); pinMode(powerGate, OUTPUT); digitalWrite(powerGate, HIGH); // 初始关闭电源开关P-MOSFET栅极高电平 // 配置引脚变化中断 PCMSK | (1 PCINT0) | (1 PCINT1); // 允许PCINT0和PCINT1产生中断 GIMSK | (1 PCIE); // 使能引脚变化中断 derailleurServo.attach(servoPin); derailleurServo.write(getServoPosForGear(currentGear)); // 上电后先归位到当前档位需外部供电 delay(1000); goToSleep(); // 进入深度睡眠 } void loop() { // 主循环大部分时间不会运行因为MCU在睡眠 if (shiftRequested) { executeShift(); shiftRequested false; requestedDirection 0; goToSleep(); // 换挡完成后继续睡觉 } } // 中断服务程序仅设置标志位不做耗时操作 ISR(PCINT0_vect) { // 简单的防抖逻辑如果上次中断刚发生则忽略 static unsigned long lastInterruptTime 0; unsigned long interruptTime millis(); if (interruptTime - lastInterruptTime 250) { // 防抖延时250ms if (!digitalRead(buttonUp)) { requestedDirection 1; shiftRequested true; } else if (!digitalRead(buttonDown)) { requestedDirection -1; shiftRequested true; } } lastInterruptTime interruptTime; } void executeShift() { // 1. 打开主电源给舵机供电 digitalWrite(powerGate, LOW); delay(50); // 等待电源稳定 // 2. 根据请求的方向和当前档位计算目标档位和目标角度 int targetGear constrain(currentGear requestedDirection, 1, totalGears); int targetAngle; if (requestedDirection 1) { // 升档从当前档位升到目标档位使用升档表 targetAngle upShiftPositions[targetGear - 1]; } else { // 降档从当前档位降到目标档位使用降档表 targetAngle downShiftPositions[targetGear - 1]; } // 3. 驱动舵机 derailleurServo.write(targetAngle); delay(300); // 等待舵机运动到位时间根据舵机速度调整 // 4. 更新当前档位 currentGear targetGear; // 5. 关闭主电源 digitalWrite(powerGate, HIGH); delay(10); // 确保电源完全关闭 derailleurServo.detach(); // 断开舵机信号进一步省电 } void goToSleep() { set_sleep_mode(SLEEP_MODE_PWR_DOWN); // 最省电的睡眠模式 sleep_enable(); sleep_mode(); // 进入睡眠 // 程序在此暂停直到被中断唤醒 sleep_disable(); }代码关键点解读中断防抖机械按钮在按下时会产生物理抖动可能导致多次触发中断。代码中通过记录上次中断时间并设置一个静默期如250ms来过滤掉抖动信号。换挡位置表upShiftPositions和downShiftPositions这两个数组是调校的核心。由于后拨和传动系统存在机械间隙和弹性从低档位升到高档位链条向大飞轮移动和从高档位降到低档位即使目标飞轮相同所需的后拨位置也可能有细微差别。升档时可能需要稍微“过推”一点降档时则需要“欠拉”一点以确保链条能准确卡入齿片。这个表的具体数值需要在实际装车后通过反复测试、微调获得。电源时序控制executeShift()函数中先打开电源再操作舵机完成后立即关闭电源并detach()舵机对象。detach()操作会释放舵机信号引脚并将其设为输入模式减少不必要的功耗。4.3 低功耗配置的奥秘要达到uA级的睡眠电流软件配置和硬件设计必须双管齐下软件配置使用SLEEP_MODE_PWR_DOWN这会关闭几乎所有内部模块包括时钟。只有外部中断和看门狗如果使能能唤醒它。在sleep_mode()前确保所有未使用的I/O引脚设置为输入模式并启用内部上拉或外部拉到固定电平防止引脚悬空产生漏电流。硬件配合这就是MOSFET电源开关的意义。即使ATtiny85睡了如果USB充电宝一直连着舵机充电宝自身的静态放电和舵机电路的微小漏电可能仍有几百uA到几个mA的消耗。用MOSFET彻底断开能将这部分功耗降为0。CR2032电池只给处于睡眠状态的ATtiny85供电自然非常耐用。5. 机械安装与系统调校5.1 3D打印支架设计与安装支架的设计需要根据你的具体车型后下叉形状、后拨型号特别是固定螺栓孔位和舵机尺寸来定制。使用Fusion 360或FreeCAD等软件进行建模是关键。设计要点稳固性支架必须紧密贴合车架和后拨的安装点避免使用中晃动。设计时考虑增加三角加强筋。舵机定位舵机安装孔位要标准。舵机输出轴的中心线需要与后拨的转动中心线即尾钩安装螺栓的轴线平行。这是保证舵机旋转角度能线性转换为后拨横向移动的前提。如果两者不平行换挡会变得非线性难以校准。连杆连接舵机摇臂与后拨拉线臂之间建议使用一个可调节长度的连杆如M2/M3螺纹杆搭配球头关节轴承。这允许你微调换挡的“中位”和行程范围比固定长度的连接方式灵活得多。安装步骤将后拨从车上拆下小心移除所有弹簧。注意记录弹簧的安装位置和方式以备复原之需。将3D打印的支架用后拨原有的固定螺栓安装在尾钩上。将舵机塞入支架并用螺丝固定。将舵机摇臂建议使用金属摇臂安装到输出轴上暂时置于中间位置如90度。连接连杆到舵机摇臂和后拨拉线臂。此时不要拧紧所有关节的锁紧螺母。将组装体装回自行车。手动将后拨推到最小飞轮位置调整连杆长度和舵机摇臂角度使得链条对准最小飞轮且舵机摇臂处于一个机械上舒适的位置避免在极限角度工作。然后拧紧所有锁紧螺母。同理手动推到最大飞轮位置观察舵机摇臂是否还有转动余量确保行程覆盖所有档位。5.2 换挡位置表的精细调校这是整个项目中最需要耐心和经验的“手艺活”。你需要将自行车架起或用维修架让后轮悬空。调校流程烧录一个简单的测试程序让舵机能通过串口指令或按钮控制每次转动一个固定的角度例如1度或5度。从最小飞轮开始。手动转动曲柄发送指令微调舵机角度直到链条安静、顺畅地啮合在最小飞轮上。记录这个角度值这就是downShiftPositions[0]降到1档的初始值。升档测试向升档方向通常舵机角度增大微调一个角度如5度然后转动曲柄观察链条是否能“爬”上第二个飞轮。如果不能再增加角度如果跳过了或者摩擦噪音很大则减小角度。找到能稳定、快速上到二档的最小角度记录为upShiftPositions[1]从1档升到2档的目标角度。降档测试现在链条在二档微调舵机角度向降档方向角度减小找到能稳定、快速降回一档的角度记录为downShiftPositions[1]从2档降到1档的目标角度。你会发现这个值很可能不等于upShiftPositions[0]。重复步骤3和4为所有6个档位建立升档和降档的角度表。动态测试编写一个简单的循环换挡程序让系统自动从1档升到6档再降回1档。观察每个档位是否准确、干脆。在换挡时适当用力踩踏踏板模拟真实骑行负载进一步微调角度确保负载下也能顺利变速。调校心得调校时在关键角度值附近如升档点可以设置一个微小的“预压”和“释放”动作。例如升档时先快速转动到一个稍大的角度确保链条上档然后立即回退1-2度以减少链条和飞轮的侧向压力降低噪音和磨损。这个逻辑可以编码到executeShift()函数中使换挡手感更接近高端电子变速。6. 系统优化、问题排查与进阶思路6.1 常见问题与解决方案速查表问题现象可能原因排查与解决步骤按下按钮无反应1. 系统未唤醒2. 电源问题3. 程序未运行1. 检查CR2032电池电压应2.8V。2. 用万用表测量ATtiny85的VCC引脚是否有约3V电压。3. 检查按钮焊接是否良好按下时中断引脚是否对地短路。4. 给系统主电源USB充电宝上电看舵机是否归位如果有上电初始化动作以判断程序是否运行。舵机抖动或不动作1. 电源功率不足2. 信号干扰3. 机械卡死1. 确保USB充电宝能输出至少1A电流且连接线够粗。测量舵机供电电压动作时不应低于4.5V。2. 检查舵机信号线连接尽量远离电机、电源线。在舵机电源正负极并接一个100-470uF的电解电容。3. 断开舵机与后拨的连接空载测试舵机是否正常转动排除机械阻力过大的问题。换挡不准跳档或不到位1. 位置表参数不准2. 机械连接松动3. 后拨限位螺丝未调好1. 重新执行精细调校流程。2. 检查所有连杆、关节轴承的锁紧螺母是否紧固。3.至关重要在安装电子系统前必须先用传统方法手变或指拨调好后拨的L限位最大飞轮和H限位最小飞轮螺丝。电子系统的工作范围必须在这两个机械限位之内。待机耗电过大1. 睡眠模式未正确配置2. MOSFET未完全关断3. 电路存在漏电1. 确认代码中使用了SLEEP_MODE_PWR_DOWN且所有未用引脚设置为带上拉的输入。2. 测量睡眠时P-MOSFET的栅源电压应为接近5V高电平。测量USB充电宝输出端电流应为0。3. 检查电路板有无焊锡渣短路特别是贴片元件下方。剧烈颠簸后掉链或错档1. 后拨无弹簧缺乏保持力2. 连接件有框量1. 这是本方案固有缺点。可尝试增加舵机保持扭矩选用更高扭矩舵机或采用前述的蜗轮蜗杆自锁方案。2. 检查并消除所有连接处的间隙使用带锁紧功能的关节轴承。6.2 进阶优化思路当基础系统稳定工作后你可以考虑以下升级让它更接近“专业产品”无线控制将按钮换成蓝牙或2.4G无线模块如HM-10或NRF24L01实现真正的无线变速。需要注意无线模块的功耗管理可能需要在变速完成后彻底断电。多档位指示与同步增加一个微型OLED显示屏或LED灯环实时显示当前档位。更进一步可以设计前拨控制器实现前后拨的联动变速如半自动同步模式。电池一体化与充电管理抛弃外挂的USB充电宝和CR2032设计一块内置的锂电池如14500或18650搭配微型充电管理模块如TP4056和低压升压模块将3.7V升到5V给舵机用。这样外观更整洁。引入传感器反馈在舵机输出轴或后拨上安装一个微型电位器或编码器实时反馈实际位置实现真正的闭环控制。这样即使机械连接稍有松动系统也能自动补偿提高精度和可靠性。蜗轮蜗杆自锁机构这是对机械部分最根本的改进。可以设计一个包含蜗轮蜗杆的减速箱将舵机的输出扭矩放大数倍并实现自锁。这样后拨的位置将极其稳固且舵机只需在换挡瞬间工作平时完全断电系统整体功耗和可靠性得到质的提升。这个项目最吸引我的地方在于它完美地诠释了DIY的精神用有限的预算和通用的元器件去解构并复现一项昂贵的技术。整个过程充满了工程上的权衡与妥协比如为了低功耗和简化控制我们牺牲了机械自恢复的便利性换来了对能量管理的深刻理解。每一次成功的换挡背后都是硬件、软件、机械三者精密协作的结果。它可能不像商店里买来的那样完美无瑕但车上每一个由自己亲手调试、安装的零件都会在每一次骑行中带来无与伦比的满足感。