Automatic Shifting Bicycle

Project Date: 2021-2022

Project Abstract:

To create an automatic gear shifting system for a bicycle that will allow a user to ride a bicycle without any manual shifting inputs required.

Project Description:

I have always toyed with the idea of having an automatic shifting bicycle ever since I got into long distance cycling a couple years ago. For most of the population that rides a bicycle for recreation or for transport, shifting is the thing that “makes going uphill easier” with minimal knowledge on how it works or how to maintain such system. Living in the tri-state area, most bicycles that are used for commuting are either single speed bikes or 2-3 speed bikes (not many hills in New York City). Trying to introduce a new person to biking and explaining this system is often met with confusion or flat out refusal to using the system (for the most part). After all, how many new drivers in the past couple of decades learned on a manual transmission automobile? The concept of how power transfer and gearing works is convoluted to the untrained engineer nor should it be necessary for many people to enjoy biking or use it as transport – after all, automatic transmissions opened the barrier to entry for many people to own and operate a automobile. With the rise of E-bikes and electronics on bicycles, we are starting to see more electronic integration in bicycle, and the future of micro mobility is in the bicycle. We already have electronic shifting (eliminating the steel push-pull cable connecting the shifter and derailleur) why not go the step further and have the bike shift FOR you?

Conceptual Design

The first hurdle I had to overcome during the conceptual design phase was determining the type of bike which I were going to design the device for. I needed to have a bike which would not be too expensive, but would also be a quality bike. I also wanted something that I would be able to install a planetary gear hub onto, as this sort of gear system would not have a delay while changing gears like a standard chain gear system would.  

Thankfully, I was able to procure a bike as a donation from Priority bicycles which was being used as a test model by the company.  The bike was an Onyx Continuum model, and in addition to being a higher end mountain bike it came with a CVT rear hub I wanted to use. I measured all areas of the bike where parts could be mounted and used these measurements in the future design work. 

Figure 3: Donated bike.

Another one of the technical specifications I needed to decide on was that all aspects of the shifting of gears would need to be done with no user input. This meant that I would need to create a mechanical device of some kind that was capable of changing gears on its own.  This device would also need to have some way of knowing what gear it was already in and exactly how far it would have to turn to go up or down a gear.  Finally, this device would need to be able to make the decision to change gears on its own, and thus would have to have some way of collecting data from the bike on things like velocity, cadence, and power output of the rider.  I determined that the device should be able to keep the rider’s cadence within ±5 rpm of a desired cadence (usually around 90 rpm).  As an alternative design goal, I also decided that I would like the possibility of a manual override switch in case the rider would like to shift gears on their own.  This would also mean the device would have to be made in such a way as to not interfere with normal shifting operation.

I also needed to be certain that whatever device created would be able to produce sufficient torque to move the shifting mechanism.  In order to determine exact numbers for this, a simple test was devised once I obtained the bike from the company.  An arm of length 9 cm was attached to the shifting mechanism.  A strain gauge was then attached to the arm in such a way as to measure the force pulling on the arm.  The gauge was then pulled until the static friction inside the gear hub was overcome and the value for the force at which this happened was recorded.  This test was performed multiple times and a value for torque of 0.667 kgf/cm was found to be the minimum value needed to turn the shifting mechanism. 


There were also several technical specifications involving the electronic components of the bike. It was important to ensure that all electronic devices could be powered by whatever battery I ended up using.  This meant that during the design phase of the project I would need to carefully read any spec sheets of the electronics and make sure that everything was compatible with each other.  As an alternative design consideration, I decided that I would like to create some way of recharging the batteries through the motion of the bike.  As luck would have it, the bike already had such a device attached to its front wheel.The electronics were designed in such a way as to be able to draw power from this device, as well as being able to charge the batteries with a standard USB charger if necessary. 

Finally, I had to take into consideration the many ways in which the device could be damaged from normal use.  One such consideration would be protecting sensitive parts in case of a fall.  Casings would need to be designed which would be able to withstand typical forces of an impact into the ground.  These casings would also need to protect the bike from both water and debris, so they would need to be both airtight and waterproof.  

I developed three conceptual designs during the initial phases of the project.  The first was a basic design for the algorithm and electronic parts which would be involved in the process of deciding when to change gears. 

Once an idea of the electronics that would be used was conceptualized, I created a diagram of the control loop algorithm which the device would use to make decisions.  The main use of shifting gears on a bike is to keep the rider’s cadence at a steady rate, and in turn this would be used as the main input for the control loop.  Riders will be able to input a target cadence into the system.  Sensors will be used to find the current cadence the rider is pedalling.  If this value is too low, the gear will shift down, and the gear will shift up if it is too high.  Velocity data will also be collected and used to determine special cases where shifting is not necessary, such as coasting or stopping. A casing to house the control board and the batteries was also designed

Figure 4: Sketch of Control Loop Diagram

The last two conceptual designs focused on the actual mechanics of changing the gears on the bike.  The first of these designs would use a cable based system to pull the shifting mechanism into place.  This design was for a gear system controlled by a motor which would attach to the shifting mechanism directly.  Three gears would pair an electric motor to the planetary gear hub and the motor would rotate the gears when the device needed to shift.  Just as in the previous design, an angular position sensor of some kind could be attached to one of the gears and used to determine the current gear.  A motor controller would need to be included with the control board.  Since the cables would be removed from the shifter, I would also need to design buttons for the handlebars which would allow manual gear shifting. 

Figure 5: Initial Layout of Gears

The final conceptual design  would use cables already used for shifting on the bike to pull the shifting mechanism into place.  A rotary device would be mounted on the frame of the bike and the turning of the device would be used to pull the cables.  Angular position of this device would be used to determine the current gear.  The bike’s gear shifter would also attach to the rotary device and the rider would be able to move it manually by shifting gears normally when the device was shut off.  

Figure 6: Basic Initial Sketch of Cable Shifter

I then compared the different design options and began selecting the best one for the final design.  On the electronics end, I first began weighing the options for the different sensors that would be used to determine velocity and cadence.  The first option I looked at was a magnetic Hall effect sensor and neodymium magnets.  These magnets could be placed at regular intervals around the edge of the pedals and rear wheel, and the Hall effect sensor could detect how often they pass and derive an rpm from there.  This method had the advantages of being easy to implement and accurate, however they carry the disadvantage of having a slow response time due to the need for several magnets to pass the sensor before a value can be obtained.  The other option I looked at was using the charging device located at the front wheel to detect velocity as the voltage output would likely be greater at higher speeds. This has the advantage of not only being accurate but also utilizing a part that is already attached to the bike.  However, it’s likely that I would need extensive testing to develop the relationship between output voltage and velocity, and I would need the front and rear wheels to match velocity exactly when testing the shifting mechanism. 

I also weighed the options of Arduino and Raspberry Pi for use as control boards.  The main advantage of the Arduino was the ease of use and previous familiarity with the system.  The Arduino is also simpler since it works by running an iterative loop of code on repeat while the RasPi is running a full kernel and OS leading to significantly higher response time as well as complexity when dealing with power, and sensor inputs.  However, the Raspberry Pi has much greater functionality when compared to the Arduino.  For example, it would be a simple matter to create a phone app which could be used to control the device with Raspberry Pi, while an Arduino would have a much harder time handling such a task.  

I also had to create several concept designs for the casings. I had a number of things to consider during this process.  First, I had to decide where to place the casings. The handlebars were a good option for the controller, as it would allow us to put an LCD screen on the casing that the rider could easily see while using the bike.  However, this would make the casing more exposed in case of a crash.  Putting the casing inside the frame would fix this issue but get rid of that functionality.  I also needed to decide which parts would go in what casing and how many different casings I needed.  Putting everything together in  one casing would mean less design work, but could make the casing excessively bulky.  Making more casings would require more design work, but would reduce the size of each casing and give us greater flexibility on where the electronic components would be mounted.  For materials, I could use either 3D printing or metal fabrication.  Metal would be more durable, but 3D printing would be more accessible since I already had access to a personal printer.  

Figure 7: Initial Design Concepts for the Casings

Next, I had to compare the designs for the cable system and gear system and decide which would be more feasible.  The gear system had a number of advantages over the cable system.  One of the biggest was the fact that it would be easier to implement with the electronic control system.  The motor would be attached directly to the control unit through the use of a motor controller.  Additional gears could be attached to the system and attached to a potentiometer which could be used to easily determine the angular position, and therefore current gear, of the system.  However, this system does carry the disadvantage of requiring much more design work when compared to the cable system.  The gears could also be susceptible to jamming due to particles becoming lodged in the gears  during use.   A separate casing would have to be designed to prevent this.  Dr. Basily also mentioned that the casing’s durability may be an issue, and that I may need to design it out of aluminum.  

The cable design has the major advantage of being much easier to attach to the gear shifter than the motor and gear system.  This is because the cable system would use the same cables which are already being used to change gears on the bike.  Manual override devices would not need to be designed since the gear shifting control on the handlebars would still work.  However, the cable mechanism would likely be more difficult to control with the Arduino.  A motor would still likely need to be used to turn the rotary mechanism, and an angular position sensor would still need to be added, which may be difficult to implement into one rotary device.  The cables could also be susceptible to developing slack, which could cause calibration issues in the control system.  

The sensors I decided to use were the Hall effect sensors.  While response time would be greater, the charging device would require too much work to make it accurately detect velocity.  I also opted to use the Arduino as the control board, due to the ease of use.  Further designs of the device would likely benefit from the Raspberry Pi’s functionality, but for a prototype the simplicity of using an Arduino was the better option.  I also opted for two 3D printed plastic casings.  One would attach to the handlebars and house the Arduino and motor controller, as well as have an LCD screen to display information to the rider.  The other would mount to the central bar of the frame near the front wheel and house the batteries.  This would place it in a central location where it could easily connect to the motor, control unit, and charging device.  

Figure 8: Initial Concept sketch of Final Design Layout

DesignProsCons
Electronic ComponentsHigh Accuracy, lower chance of part failureComplicated programming, possible response time issues
Worm Gear ShiftingHigh Compatibility with ArduinoNeed to design parts to fit bike’s gear hub
Cable ShiftingUses shiting parts already on bikeNot easy to implement with Arduino

Table 1: Pros and Cons of different designs

DETAILED DESIGN AND ANALYSIS

Shifting Mechanism

Figure 9: Cross Section of Gear Shifting Mechanism

The shifting mechanism is directly attached to the bike’s CVT hub and what actuates the CVT hub. The shifting mechanism consists of a 10 turn potentiometer, a N20 worm gearbox motor, internal gears and a housing. The shifting mechanism needs to reliably shift the CVT under normal conditions and give feedback to the controller on the current state of the CVT Hub.

The CVT hub is a N360 Enviolo hub which provides a gear ratio output from 0.5 to 1.8. This is enough range to provide enough torque from a stop and enough overdrive for speeds up to 15 mph for an unskilled cyclist. 

Figure 10: Enviolo CVT Hub.

On the right side of the hub, is the input side. There are provisions to attach a freehub for a sprocket, and a shifting spline. When this shifting spline is rotated, the internal gearing changes. The shifting mechanism attaches to this shifting spline. In order to shift the mechanism, a motor needed to be selected that provides enough torque. A single motor can not solely provide enough torque to spin the system, so a gearbox needed to be attached. A worm gear box was selected, due to the large force amplification it provides and also the ability to not have the gearbox backdrive the motor. This is a safety feature so that the CVT can not backdrive the system. The calculated torque to overcome the internal stiction was done by attaching a lever to the output and attaching a strain gauge to the output arm. Several readings were taken to average the force needed to spin the output shaft at a constant speed.

Figure 11: Initial ideas to determine necessary motor motor torque.

Equation 1: Torque formula.

=2.9cm*0.23kgf=0.667 kgf*cm

The torque required is 0.667 kg.cm to spin the output shaft. Based on this value, a motor and gearbox was selected. The supplier of the gearbox and motor provides various combinations affecting the final speed and torque. To reliably provide enough shifting power, the torque output should be a minimum of 2 times the required torque to spin an object. Electric motors provide an optimal torque and RPM depending on the input voltage and RPM. The system can output 12v and a maximum amperage of 1.2A from the motor controller.

Figure 12: N20 motor curve chart.

Table 2: N20 motor and gearbox ratings.

The gearbox and motor combination chosen was the 236 reduction ratio model. This provided a constant rated torque of 1274 gf.cm which is 1.91 times the needed torque needed from the system. Stall torque is at 2950 gf.cm, but this would be the motor’s stall limit, meaning the motor would be stalled providing no rotational translation. The gearbox is not the deciding factor of the system’s shifting torque. Due to the packaging constraints of the system, the motor needed to be placed further away from the input. This allowed us to put a gear system inside that can amplify the needed torque even more. The system was designed to be as compact and light as possible, so the proper gear sizes needed to be determined with a custom made calculator. The calculator was able to allow quick iteration of different gear ratios, and see output torques and speeds.

Table 3: Gear calculator

Gear Ratio = Input Ratio/Output Ratio

Speed Ratio = Output Ratio/Input Ratio

Equations 2 & 3: Calculations used for the determining gear and speed ratio.

A gear ratio of 25:55 was chosen. This would amplify the torque to 2802gf.cm which would be 4.2 times the rated torque I need. While increasing the torque would decrease the final drive speed, the range of motion the system would be seeing is less than 180 degrees from one end stop to another. The system will be able to shift from one stop to another in 0.15 seconds.

Since the gears are to be 3d printed, it was critical that the material and gears do not yield under the seen forces. The gears were designed with a factor of safety of 2.0 in mind.  The simulation applied forces at the contact points between the gears and used the same torque values that were obtained from testing.  Gears were assumed to have fixed positions.

Figure 13a: Strain of nylon printed gears.

Figure 13b: Stress of nylon printed gears.

From the simulations, 3D printed gears in Nylon will be more than sufficient in transmitting or torque. When designing gears for 3D printed gears, the size of the teeth is extremely important.

Figure 14: Gear design theory and calculations.

For optimal power transmission and accuracy, a pressure angle of 20 degrees was used, and a tooth modulus of 1.0 relative to the gear diameter was chosen. The 3D printer nozzle being used is limited to 0.2mm, so the gear thickness was sufficient to get material filled in. Any smaller would mean decreased print accuracy and strength. The rest of the housing is to be 3D printed in PLA. The primary concern of the housing is to protect the gears from any foreign objects, as small objects getting trapped between the gears will cause damage. The edges of the model have a lip interlocking system to ensure no objects can pass through. The system is mounted on an existing mounting spline and secured with a nut.

Figure 15: System mounted on the wheel

Electronics and Control System

Figure 16: Electronics Wiring Diagram

Overview

The electronics system is self-powered from a dynamo hub which works as an AC generator with a voltage relative to the wheel speed of the bike. This hub is connected to a voltage regulating AC to DC converter which will output a constant 5V DC. This 5v can then be hooked up to the charge controller that provides both charging for the four 18650 Lithium-Ion batteries hooked up in parallel. This charge controller will then output 12V that can be fed to the Arduino board acting as the main control for the system as well as an H-Bridge motor controller used to power the N20 motor as part of the shifting assembly. The Arduino unit sends a digital output to both an LCD display as well as a PWM output to the motor controller. The inputs of this system are two hardware buttons for user input as well as a hall effect sensor attached to the wheel for wheel speed, a second hall effect sensor for pedal speed/cadence and a rotary encoder equivalent as part of the control loop for the shifter mechanism.

Control Components

The heart of the electronics system will be an Arduino Uno Microcontroller. I chose this board due to being very familiar with it as it is an open-source platform used for a variety of projects and for various applications. It has the necessary capabilities for both digital and analog I/O, which allows us to use one board at the center of all logic and control for the components and sensor inputs. Other boards were also considered for packaging concerns, but from both a cost and capability aspect the Arduino won out over something smaller like a teensy 3.0 or an Arduino micro. In the future I may consider switching to a more feature rich system such as a Raspberry Pi which can run a full kernel, but for the current scope this adds too much complexity to the control system without enough immediate benefit. Also, unlike other boards, the Arduino Uno has a built-in voltage regulator which means the 12 volts coming out of the charge controller can be fed directly into the Arduino’s DC input without being stepped down beforehand. The digital pins and power rail will still output the 5v needed for the rest of the digital components allowing the board itself to work as a 5v source in the system.

Figure 18: Arduino Uno

The parameters required for the motor controller were an output of 12V DC with up to a 700mA output (the stall current of the N20 motor). I settled on a compact off the shelf H-Bridge Motor controller from SparkFun. The specific controller I chose takes in a VCC of 5v unlike other options with 3.5V inputs that would require a voltage divider between the Arduino’s 5V digital outputs. This board can also take a digital PWM signal which allows for greater functionality. Instead of having the binary control of either shifting or not shifting, I can change the shifting speed of the CVT by adjusting the motor rpm. This board is also relatively compact and can be mounted to another board with headers.

Figure 19: H-Bridge Motor Driver

Charging Components

The power system of the design is a subsystem that will both charge itself and power the rest of the electronics in the system. This will consist of 4 main components, all depicted along the top of the wiring diagram. These will be the dynamo wheel hub, AC to DC converter, charge controller and 4 cell battery pack.

The hub and AC to DC converter are manufactured by Shimano to be retrofitted to traditional road bikes. They came preinstalled on the bike when I received it and after originally considering removing them and charging the system externally, I decided to look into integrating them as part of the design. The original system was meant to output 5v DC from a USB output to charge phones and other low power electronics like an LED headlights.

Figure 20: Shimano Dynamo Hub

This led us to choosing a charge controller that could both output up to the 12v needed to power the motor controller as well as take in a variable voltage so I could directly draw power from the pre installed components. The controller I chose is called the “DIY LiPi Supercharger” and ships as a PCB with all the necessary components needing to be soldered on. This board has multiple auxiliary functions that benefit the project such as over current protection for the charge circuit as well as an eFuse to prevent the rest of the electronics from drawing too much power and overloading the boost converter IC. Also the max current draw of both the Arduino (200mA) and motor (85mA load) will not exceed the 750mA output of this board.

Figure 21: Charge Controller Board

The power storage will be provided by a pack made up of 4 18650 Lithium Ion batteries wired in parallel. These batteries charge at 3.7 volts which is standard for most LiPo batteries and the charging voltage output by the charge circuit. The parallel pack output the same voltage while the storage increases. Each individual battery can hold 2500mAh of energy for a combined 10000mAh of storage. Assuming the normal power draw is about 250mA, at full charge the system could run for almost two days, giving us a lot of leeway in terms of charging efficiency.

Figure 22: 18650 Cell

Electronic Component Housings

Seeing as I have multiple components that work directly with each other, the electronics described above will have to be split amongst enclosures suited to their purpose. The final layout was to start with the components that are fixed in place; in this case the dynamo hub, DC converter, and the shifting assembly, and build two housings between them.

Figure 23: Location of the Casings on the Frame

Control Box

The Control Box is the first of two casings designed to hold the electronic components for the device.  This casing is designed to hold the main control boards; an Arduino Uno and the motor controller. This allows us to create one PCB, in this case a shield for the Arduino, that can also serve as the base of the motor controller and share a common 12V line coming from the battery box as these are the only components that require power directly from the charge controller. I can also attach the LCD screen at the front of this case as it requires multiple pins connected. This housing will have the most I/O as basically all other components are connected either directly or indirectly to the control unit. These will consist of the battery box power, individual connections from the various sensors described above, a connection to the handlebar buttons, and a line going towards the back of the bike to the shifting assembly for both the motor controller output and the encoder input. This whole casing will be mounted to the handlebars to allow the rider to easily view the screen.

Figure 24: Full Assembly of Control Casing

The entire casing will be 3D printed using nylon filament.  It will consist of four separate parts; the main body of the casing, the top cover of the casing, and two clamping arms.  There will be 3 holes on the main body to allow wires to be placed through.  The top of the casing will be fastened using four M3 screws along with brass heated inserts.  The electronics will be attached with M3 screws and nuts.  M3 screws and nuts will also be used to hold the clamp shut.  

Stress testing was done using Ansys Live to optimize the amount of material being used.  Stresses were placed in areas likely to experience stresses (mostly on the clamping area).  The casing was assumed fixed and a force of 10 N was applied along the inner radius of the clamp.  Areas of low principle stresses could be made thinner.

Figure 25: Stress Testing Done on Original Design

Battery Box

The second of the two casings is designed to hold the batteries and charge controller.  It will be mounted on the central part of the frame near the handlebars.  This position was chosen in order to provide protection to the unit in case of a crash. The battery box will contain the 4 cell battery pack wired directly to the board for the charge controller, the I/O for this module will be the USB input from the DC converter and a single output of 12v.

Figure 26: Full Assembly of Battery Box

This casing will also be 3D printed from nylon filament.  It will consist of six parts; a main body, a top casing, two legs, and two clamps.  The legs were added to the design due to the fact that the structure would have poor support during the 3D print if the legs were made part of the main body.  There will also be three holes in the main body to allow wiring.  The top will be held in place by M3 screws along with heated brass inserts, and the clamps and electronic components will be held in place with M3 screws and nuts.  The results of the stress testing described for the main casing were used to determine thicknesses.  

Shifter Override Controller

Figure 27: Manual Gear Shifting Control

For the gear selection controller, I design a one piece clamp which has a box attached to it. The buttons need to be designed properly so they don’t go into the box or fall out of it when I press them. So I extend the edge of the button like the picture shown below so that it doesn’t fall out of the box.

                                                                Figure 28: Control Button

Since I am using electric buttons from Amazon to control the gear selection system, I would need to affix the electric buttons on the lid of the box and also make sure that the buttons designed can trigger them. In the picture, the designed buttons are extended so that they are able to touch the electric buttons and trigger them.

                                                        Figure 29: Cross-section of control box

The clamps are designed to hold on to the bicycle handle bar so that the rider can select gear manually with his or her numb. The clamp is designed with holes which can fit M2 screws on it. Once I put the clamp on the handle bar, I can use M2 screws to tighten up the clamp. For the design of the box, I need to consider the size of buttons and also the height of the box. And I also need to make sure that the part is compatible with screws.

                                                              Figure 30: Lid

 In addition, buttons needed to be as close to the handle bar as possible so that the rider can easily reach out to them. The distance between the box and the handlebar needs to be taken into consideration. And the arm that connects the box and the clamp needs to be strong enough to hold the pressure without breaking. For the gear controller, the parts selection is crucial since there are several parts involved including the part from Amazon, I need to put them together and make them work for the gear selection system. with the gear controller, the rider can manually change whatever gear he or she wants. It provides an additional way for gear changing  to the rider.  

Module Wiring/Layout

The wiring for this system will be made up of 22 Gauge multi strand wire. Seeing as this system is relatively low power, anything thicker would be unnecessary. A thinner wire could be chosen but estimating the longest run would be from the control unit to the shifting assembly and measure 5 feet, a thinner wire would potentially add enough resistance to alter the analog reading from the encoder.

The connections at the modules will be standard JST connectors. Male ends will be connected to the wire runs, with female ends mounted to the insides of the cases. This system eliminates the need to hardwire any connections between components which would lead to problems when troubleshooting components in the future as well as making any adjustments to positioning or layout.

Figure 31: JST Connectors

Sensors

The control loop for the system requires three inputs to function properly. These inputs are the bicycle’s velocity, the cadence of the rider, and what position the CVT hub is in its travel. Each of these inputs will be satisfied by a different sensor mounted on the bike.

Cadence will be measured via a specialized hall effect sensor that mounts directly to the pedal shaft. This device is marketed as a pedal assist sensor and is commonly used in electric bike builds to deliver data on pedal speed so the electric bike motor can kick in with the appropriate power. The use case is similar except it will be used to determine when to shift in the control loop. The sensor will work similarly to the digital input from a switch but will need to be powered via 5V from the Arduino.

Figure 32: Cadence Sensor

The bike’s velocity will be measured via a standard hall effect sensor mounted to the rear frame of the bike. The input will function like other high/low signal inputs and be triggered by small magnets along the spokes of the wheel. Compared to other methods such as a GPS module or a simple reed switch, this method is less complex to integrate and has a significantly lower latency.

Figure 33: Wheel Speed Sensor

Lastly, the position of the hub, hence the current ratio of the wheel speed or “gear”, will be detected by a multi turn potentiometer. Though referred to as an encoder multiple times earlier, I settled on using a potentiometer instead as it will be fixed in reference to its position, eliminating the need to zero the whole system every time the control board power cycles.

Figure 34: Hub Position Sensor

Final Components

The final components were assembled and shown. The parts were all 3d printed and took a total time of 57 hours to complete. The heated inserts were pressed with a soldering iron with special attachment tips, and components were all fastened together to create the final product. Wire harnesses were cut to length and connected all the electronic components togethers. 

Figure 36,37,38,39: Printed parts for shifter and button.

Figure 40,41,42: Pictures of control box, finished shifter mechanism, and fully assembled bike.

Control Loop and Programming

The system was coded using the arduino C language (Reference code can be found in the Appendix Section) and the final PID (proportional, integral, and derivative) control loop is shown here. In actually, the control loop is a PI loop primarily because adding a derivative function did not reduce the error rate on the controller. I suspect that is because the system has to much of a delay as it is currently.

PID Control Loop

You may be asking why I have the cadance be our control point – if you have ever looked at an engine horsepower and torque graph, you will notice it peaks and drops off after a certain point. An automatic transmission (either geared or a CVT) uses the engine’s RPM and torque to determine when or what gear ratio to be in.

A transmission in a car optimizes the engine speed to be in the power band. Below this range, the engine may struggle to produce enough power, while above it, the engine may become inefficient or even damage itself. Automatic transmissions enable the engine to stay within its optimal range by providing multiple gear ratios. Transmissions are what allow the torque output of the engine to be transformed into different levels of rotational speed at the wheels. Lower gears provide more torque, which is useful for starting from a stop or climbing hills. Higher gears allow for higher speeds with less torque, ideal for cruising on the highway. Also, by keeping the engine operating in its most efficient range, transmissions can contribute to better fuel efficiency. When the engine doesn’t have to work as hard to maintain speed, it uses less fuel.

Humans are essentially a biomechanical engine, and also have an optimal “power band” when cycling, and is why we shift gears on a bicycle in the similar scenarios, such as accelerating, going up a hill, or maintaining speed on a flat road. Thus, we want to maintain our cadance in the optimal power band and we can change that cadence by changing the ratio between the pedal and the rotational speed of the wheel propelling the cyclist.

Testing and Analysis

Figure 43: The testing rig in use.

Testing was divided into two main stages: one in which the basic functionality of the system mechanically was tested, and one in which the control loop was tested.  The first round of testing was done while the bike was disassembled. A testing rig which could rotate the rear wheel of the bike was used to test the shifting mechanism with internal forces inside the CVT Hub.. A voltage generator with current monitoring was used to power the shifting mechanism during this stage

The shifting mechanism was tested just buy connecting it to a testing arduino and simple code to shift was flashed on it. The other electronic components were tested individually. A simple Arduino code which would only affect the component being tested was written for each test.  The following is a rough outline of the order in which the electronics were tested:

  • Tested the LCD display.
  • Tested the basic functionality of the motor controller and motor.
  • Tested the functionality and accuracy of the potentiometer.
  • Tested the batteries and charge controller.
  • Tested the functionality and accuracy of the hall effect sensors.
  • Tested the manual control buttons.
  • Tested the motor and gear system while attached to the rear wheel.

This first round of testing went smoothly, and most electronics ran as expected without issues.  When a component didn’t work, it was always due to an easy to fix wiring or soldering mistake.  However, the motor controller originally used was found to have insufficient power to turn the gears and a different make of motor controller was used instead. When these tests were finished, all parts were assembled in their respective casings and fixed to the bike to prepare for the second round of testing.  

The second round of testing was done both on a bike trainer and on the streets around the Rutgers Busch campus.  The trainer was used to quickly iterate changes with the control loop and code. Once satisfactory operation was being observed, testing moved to the streets and routes were chosen with changes in gradient. As stated before, these tests checked the optimization of the control loop. The effectiveness of the system was judged based on how closely the cadence matched the reference cadence. Ideally, the error should be minimal and be responsive enough to react to changes in the terrain. When cadence overtime is graphed, the average cadence should not deviate from the set cadence more than 20%.

I that found our system to be very successful from the test results. When riding with similar force applied to the pedals, the system shifts gears very quickly.  As can be seen from the data, cadence values stayed even closer to the reference value than expected. To test the effectiveness of the system, both an experienced cyclist (~1000 miles of cycling a year) vs a beginner cyclist (less than 50 miles a year) rode the same loop several times, with the experienced cyclists shifting the bike in manual mode. The beginner cyclists noticed that the system shifted responsively and reacted to the changes of the gradients, quickly lowering gears on uphills and raising gears on downhills. 

Figure 44: Test loop around Rutgers Campus, 1.1 miles.

Figure 45: Elevation of ride to show uphills and downhills.

The system was set to keep a cadence of 70 RPM for the beginner rider, which is a good cruising pace. The experienced rider was able to keep an average cadence of 68.1433RPM and on average, deviated from the system 16.73% of the time. 

Figure 46: Experience cyclist cadence over time.

Figure 47: Beginner cyclist cadence over time.

The beginner rider was able to ride with an average cadence of 68.447 with a deviation of only 11.89% of the time. Typically new cyclists would be in the incorrect gears for uphill and downhill and not shift quickly enough. However, the beginner cyclist was able to keep his cadence at an optimal pace and not deviate from it very closely to that of the experienced cyclist. As a benefit, the beginner cyclist was able to keep an average speed of 8 mph compared to the experienced cyclist’s 10 mph. Without thinking about when to shift gears, the system helped a beginner rider have similar performance to what would be expected from an experienced rider.  This shows that the system would be useful for casual or beginner riders since it would optimize their gear shifting without the need for them to have the knowledge of the experienced rider. 

Further testing can include heart rate monitors and power meters to measure the energy expended and to compare a traditional manually shifted bike with the system to compare if there is increased efficiency between a traditional system and the system. If the system could be optimized to outperform the experienced rider, it could even be used by experienced riders to train and further improve their riding.

Conclusion

In conclusion, I was able to successfully achieve the design parameters with a working prototype that can both shift automatically under its own power with no user input. There are a number of avenues I could take to further improve this design in the future. Firstly, there is vast room for improvement within the software I created to run the bicycle, specifically in the optimization of the control loop. By simply implementing more testing and tweaking of the control parameters, I could increase the efficiency of the bike. Beyond this, I could add more inputs for the control loop to implement such as a gradient sensor to tell if the rider is on an incline or a torque sensor to tell how much force the rider is applying. I could also replace the current hall effect sensors with something that has a shorter response time to improve latency.  

In terms of physical design, I could also make changes to improve the manufacturability and durability of the system, essentially creating a design more appropriate for a mass producible product/kit.  For example, while 3D printing worked well for rapid prototyping and quickly making alterations, I could instead design injection molded casings which would allow mass production. For durability, the gears should be made from a tougher material, such as being machined out of aluminum, to avoid wear and eventual shearing over extended use.  Finally, I could ruggedize out design with features such as gaskets along the mating surfaces and sealed connectors to prevent ingress of  water and debris and allow use of the system in suboptimal weather and terrain conditions. 

Appendix

  1. /*PINS
  2. A0: Minus button right handlebar
  3. A1: Plus Button right handlebar
  4. A2: Encoder Pos
  5. A3: LCD Enable
  6. A4: LCD Voltage
  7. 1:
  8. 2: Cadence Interrupt Sensor
  9. 3: Wheel Speed Interrupt Sensor
  10. 4: Digital LCD Pin
  11. 5: Digital LCD Pin
  12. 6: Digital LCD Pin
  13. 7: Digital LCD Pin
  14. 8: Motor Controller A12
  15. 9: Motor Controller A11
  16. 10: Motor Controller PWM A
  17. 11:
  18. 12: Button
  19. 13: Button
  20.  
  21. */
  22.  
  23. //PIN SETUP MOTOR
  24. #define motorPWM  10
  25. #define motorPinA  9
  26. #define motorPinB  8
  27.  
  28.  
  29.  
  30. //LCD SETUP
  31. #include <LiquidCrystal.h>  //Library LiquidCrystal
  32. #include <LcdProgressBar.h> //Library LCD Progress Bar
  33. const int rs = A4, en = A3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
  34. LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
  35. LcdProgressBar lpg(&lcd, 1, 16);
  36. int buttonPushCounter = 1;    // counter for the number of button presses
  37. int buttonState = 0;       // current state of the up button
  38. int lastButtonState = 0;   // previous state of the up button
  39. bool bPress = false;
  40.  
  41. int buttonState2 = 0;       // current state of the up button
  42. int lastButtonState2 = 0;   // previous state of the up button
  43. bool bPress2 = false;
  44.  
  45.  
  46.  
  47. //PIN SETUP BUTTONS
  48. #define buttonA  A0
  49. #define buttonB  A1
  50.  
  51. //PIN SETUP ENCODER
  52. #define encoderPin  A2
  53.  
  54. //Button VALS
  55. int boolButtonA;
  56. int boolButtonB;
  57.  
  58. //ENCODER VALUES
  59. int encValue;
  60. int minValueCVT = 422;   //Reminder, it is “reversed”
  61. int maxValueCVT = 348;
  62. int setPointCad;
  63. int manConInc =5;
  64.  
  65.  
  66. //CONTROL LOOP AUTO
  67. float cadanceCurrent, cadanceDesired; //cadanceDesired is ourSP, cadance current is our cadance val
  68. int dt;
  69. unsigned long t;
  70. unsigned long tPrev = 0;
  71. int val_prev = 0, val = 0;
  72. float e, e_prev = 0, inte, inte_prev = 0;
  73. float kp = .8;
  74. float ki = 0;
  75. float V;
  76. int motorVal;
  77.  
  78. //CONTROL LOOP ESTIMATE MODE
  79. float mthetaCurrent, mthetaDesired; //cadanceDesired is ourSP, cadance current is our cadance val
  80. int mdt;
  81. unsigned long mt;
  82. unsigned long mtPrev = 0;
  83. int mval_prev = 0, mval = 0;
  84. float me, me_prev = 0, minte, minte_prev = 0;
  85. float mkp = .5;
  86. float mki = 0;
  87. float mV;
  88.  
  89.  
  90. //AUTOMATIC CONTROL PARAMATERS
  91. float startSP = 70;
  92.  
  93.  
  94. //PARAMETRS FOR SENSORS
  95.  
  96. const byte interruptPinCadance = 2; //pin for cadance sensor
  97. const byte interruptPinRPM = 3; //pin for rpm sensor
  98.  
  99. int pulseCountCadance = 6; //pulse per rotation for cadance sensor  
  100. int pulsecountRPM = 12; //pulse per rotation for wheel speed sensor
  101. unsigned long timeOldCadance;      //—
  102. unsigned long timeBetweenCadance;  // pulse count stuff for wheel speed and cadnace
  103. unsigned long timeOldRPM;          //
  104. unsigned long timeBetweenRPM;      //
  105.  
  106. float cadanceVal; //CADANCE VALUE
  107. float wheelSpeedVal;  //WHEEL SPEED VAL
  108. float rotationCadance = .1667;    
  109. float rotationWheel = .08333;
  110. float minutesCadance;
  111. float hoursWheel;
  112. float milesWheel;
  113. float theoreticalRatio;
  114.  
  115. //DEBUG
  116. char input;
  117.  
  118.  
  119. void setup() {
  120.    
  121.      
  122.   //LCD SETUP
  123.   lcd.begin(2, 16);
  124.   lcd.clear();
  125.   //lpg.setMinValue(long(0));
  126.   //lpg.setMaxValue(long(minValueCVT-maxValueCVT));
  127.   //lpg.draw(long(abs(encValue – minValueCVT)));
  128.   // put your setup code here, to run once:
  129.   Serial.begin(9600);
  130.  
  131.   //Motor pin setup
  132.   pinMode(motorPWM, OUTPUT);
  133.   pinMode(motorPinA, OUTPUT);
  134.   pinMode(motorPinB, OUTPUT);
  135.  
  136.   //Button Pin Setup;
  137.   pinMode(buttonA, INPUT_PULLUP);
  138.   pinMode(buttonB, INPUT_PULLUP);
  139.  
  140.   //Sensor Pin Setup
  141.   pinMode(interruptPinCadance,INPUT_PULLUP);
  142.   pinMode(interruptPinRPM,INPUT_PULLUP);
  143.    
  144.   attachInterrupt(digitalPinToInterrupt(interruptPinCadance), PulseCountCadance, RISING);
  145.   attachInterrupt(digitalPinToInterrupt(interruptPinRPM), PulseCountRPM, RISING);
  146.  
  147.   //On start, get the base level SP for cadance
  148.   setPointCad = startSP;  
  149.  
  150. }
  151.  
  152. void loop() {
  153.   // put your main code here, to run repeatedly:
  154.  
  155.  
  156.  
  157.   //Swtiches between continously running a contorl loop or esitmate mode when coasting and I know I have alot of errrors typing commoments because i do not care and there is no spell check
  158.   if(cadanceVal <=5 && wheelSpeedVal >=1){
  159.     EstimateRatio();
  160.     ProportionalControlEstimateMode();
  161.   }else{
  162.     ProportionalControlAutomaticShifting();
  163.   }
  164.   //display code and sensors
  165.   Display();
  166.   Sensors();
  167.   SerialData();
  168. }
  169.  
  170.  
  171.  
  172.  
  173.  
  174. void EstimateRatio(){
  175.  theoreticalRatio = (wheelSpeedVal/.000217)/(2.08*setPointCad);
  176.  mthetaDesired = minValueCVT – (theoreticalRatio*52.8);
  177.  
  178. }
  179. void ManualControlPropV2()
  180. {
  181.     //Read Button INPUTS
  182.   boolButtonA = digitalRead(buttonA);
  183.   boolButtonB = digitalRead(buttonB);
  184.  
  185.  
  186.   //A is minus B is plus
  187.   if(boolButtonA == LOW && boolButtonB == HIGH)
  188.   {
  189.     if(encValue <= maxValueCVT){
  190.       MotorControl(0);
  191.     }else{
  192.       MotorControl(12);
  193.     }
  194.   }
  195.   else if (boolButtonA == HIGH && boolButtonB == LOW)
  196.   {
  197.     if(encValue >= minValueCVT){
  198.       MotorControl(0);
  199.     }else{
  200.       MotorControl(-12);
  201.     }
  202.   }
  203. }
  204.  
  205.  
  206. void ProportionalControlAutomaticShifting(){
  207.   t = millis();
  208.   dt = t – tPrev;
  209.   cadanceCurrent = cadanceVal;
  210.   cadanceDesired = setPointCad;
  211.  
  212.   e= cadanceCurrent – cadanceDesired;
  213.   inte = inte_prev + (dt * (e + e_prev) / 2);
  214.  
  215.   V = kp * e + ki * inte;
  216.  
  217.    if (V > 12) {
  218.       V = 12;
  219.       inte = inte_prev;
  220.     }
  221.     if (V < -12) {
  222.       V = -12;
  223.       inte = inte_prev;
  224.       val_prev= val;
  225.     }
  226.  MotorControl(V);
  227.  tPrev = t;
  228.  inte_prev = inte;
  229.  e_prev = e;
  230.  
  231. }
  232.  
  233. void ProportionalControlEstimateMode(){
  234.  
  235.   mt = millis();
  236.   mdt = mt – mtPrev;
  237.   mthetaCurrent= encValue;
  238.  
  239.   me= mthetaCurrent – mthetaDesired;
  240.   minte = minte_prev + (mdt * (me + me_prev) / 2);
  241.  
  242.   mV = mkp * me + mki * minte;
  243.  
  244.    if (mV > 12) {
  245.       mV = 12;
  246.       minte = minte_prev;
  247.     }
  248.     if (mV < -12) {
  249.       mV = -12;
  250.       minte = minte_prev;
  251.       mval_prev= mval;
  252.     }
  253.  MotorControl(mV);
  254.  mtPrev = mt;
  255.  minte_prev = minte;
  256.  me_prev = me;
  257.  
  258. }
  259.  
  260. void MotorControl(float V){
  261.  
  262.   motorVal = int (255 * abs(V) / 12);
  263.   constrain(motorVal, 0,255);
  264.  
  265.  
  266.  
  267.   if(wheelSpeedVal >= 1)
  268.   {  
  269.     if(V > 0) //Go Forward
  270.     {
  271.       if(encValue <= maxValueCVT){
  272.         digitalWrite(motorPinA, LOW);
  273.         digitalWrite(motorPinB, LOW);
  274.       }
  275.       else
  276.       {
  277.         digitalWrite(motorPinA, HIGH);
  278.         digitalWrite(motorPinB, LOW);
  279.         analogWrite(motorPWM, motorVal);
  280.       }
  281.     }
  282.     else if(V < 0) //Go Backward
  283.     {
  284.       if(encValue >= minValueCVT){
  285.         digitalWrite(motorPinA, LOW);
  286.         digitalWrite(motorPinB, LOW);
  287.       }
  288.       else
  289.       {
  290.         digitalWrite(motorPinA, LOW);
  291.         digitalWrite(motorPinB, HIGH);
  292.         analogWrite(motorPWM, motorVal);
  293.       }
  294.     }else{
  295.       digitalWrite(motorPinA, LOW);
  296.       digitalWrite(motorPinB, LOW);
  297.     }
  298.   }
  299.   else
  300.   {
  301.     digitalWrite(motorPinA, LOW);
  302.     digitalWrite(motorPinB, LOW);
  303.   }
  304. }
  305.  
  306. void Display(){
  307.  
  308.  lcd.clear();
  309.  lcd.setCursor(0,0);
  310.  lcd.print(“Enc: “);
  311.  lcd.print(encValue);
  312.  lcd.print(“WS:”);
  313.  lcd.print(wheelSpeedVal);
  314.  lcd.setCursor(0,1);
  315.  lcd.print(“RPM:”);
  316.  lcd.print(cadanceVal);
  317.  lcd.setCursor(8,1);
  318.  lcd.print(“SP:”);
  319.  lcd.print(cadanceDesired);
  320.  //lpg.draw(long(abs(encValue – minValueCVT)));
  321.  delay(500);
  322.  
  323. }
  324.  
  325. //INTERUPTS FOR PULSE COUNT CADANCE
  326. void PulseCountCadance(){
  327.   timeBetweenCadance = millis()-timeOldCadance;
  328.   timeOldCadance = millis();
  329. }
  330.  
  331. //INTERUPTS FOR PULSE COUNT RPM
  332. void PulseCountRPM(){
  333.   timeBetweenRPM = millis()-timeOldRPM;
  334.   timeOldRPM = millis();
  335. }
  336.  
  337.  
  338.  
  339. void Sensors(){
  340.   //Encoder Value—-
  341.   encValue = analogRead(encoderPin);
  342.   //ENOCDER END—-
  343.  
  344.   //Cadance——
  345.    cadanceVal = (5000/timeBetweenCadance); // degree/ms  rot/degree ms/min
  346.   if (millis()-timeOldCadance>1000){ //If cadance is not counted for 1 second, set at zero
  347.     timeBetweenCadance = 0;
  348.   }
  349.   if (timeBetweenCadance == 0){
  350.     cadanceVal = 0;
  351.   }
  352.   //END CADANCE —-
  353.  
  354.   //RPM——-
  355.   wheelSpeedVal = ((30.0/timeBetweenRPM))*11.36; // degree/time *factor to get mph
  356.   if (millis()-timeOldRPM>1000){
  357.     timeBetweenRPM = 0;
  358.   }
  359.   if (timeBetweenRPM == 0){
  360.     wheelSpeedVal = 0;
  361.   }
  362. //delay(100);
  363. }
  364.  
  365.  
  366.  
  367.  
  368.  
  369. void SerialData(){
  370. Serial.print(encValue);
  371. /*Serial.print(‘x’);
  372. Serial.print(cadanceVal);
  373. Serial.print(‘x’);
  374. Serial.print(wheelSpeedVal);
  375. Serial.print(‘x’);
  376. Serial.println(millis());
  377. */
  378. }
  379.  
  380.  
  381.  
  382. /*
  383.   // E-STOP CODE TO PROTECT THE CVT!!!!
  384.   if(encValue >= 427 || encValue <= 343)
  385.   {
  386.     digitalWrite(motorPinA, LOW);
  387.     digitalWrite(motorPinB, LOW);
  388.   }
  389.  
  390.   */

Arduino Code Reference

Wiring Diagram