top of page


Master’s Thesis Project by Chris Arntzen



This thesis entails the design and fabrication of a smartphone charger that is powered by a bicycle dynamo hub.  In addition to the design and validation of the charger prototype, this thesis involves the testing and characterization of the dynamo hub power source, the design and construction of specialized test equipment, and the design and prototyping of a handlebar-mounted case for the smartphone and charging electronics.  With the intention of making the device a commercial product, price, aesthetics, and marketability are of importance to the design.  An appropriate description of the charger circuit is a microcontroller-based energy management system, tailored to meet strict power demands of current smartphones.  The system incorporates a switched-mode power supply, lithium polymer battery, microcontroller, and specialized protection circuitry.  Prototype testing confirms that the circuit meets the charging requirements of the smartphone at bicycle speeds ranging from 7 miles per hour to as high as 55 miles per hour.




The microcontroller chosen for this project is the Atmel ATMega328P; it is also the microcontroller used on the Arduino Uno.  For the DC-DC converter, the Single-Ended Primary Inductor Converter (SEPIC) topology was selected since it can buck and boost, and does not invert the output voltage.  The Linear Technology LT3759 controller works with the SEPIC topology at an input range of 1.6 – 42V, which was necessary for the scope of this project.  The iPhone 5 serves as the load for design and testing purposes, as it was a fairly common and popular phone at the time of this project.

Block Diagram

System design had to accommodate varying input voltage, frequency, and power as the rider’s speed varies.  The power management scheme is to charge the phone directly when the rider is going fast enough to provide the minimum output power to charge the phone, and charge the integrated battery at speeds where the output power is not sufficient to charge the phone.  The battery can be cycled back to the input of the DC-DC converter when phone charging is necessary at low speeds.  The microcontroller makes all of the power management decisions, varies the output voltage depending on the load profile, and toggles load switches at the output to select battery versus phone.

DC-DC Converter Section Schematic

Specialized circuitry was necessary to protect the circuit from high input voltages produced by the hub at high speeds.  Since the input capacitors are rated at 35V, a high-side MOSFET disconnects the input from the circuit at a pre-determined threshold.  A comparator circuit feeds a high-side gate driver powered by charge pumps, which were necessary to drive the gate of the MOSFET.

Input Stage Schematic

The microcontroller utilizes input and output current and voltage sensing to make power management decisions.  It programs the DC-DC converter output voltage via serial peripheral interfacing (SPI) to a digital potentiometer in the feedback node of the converter.  Temperature sensing is also implemented as a safety feature for charging the lithium polymer battery.

Microcontroller Section Schematic

Eagle PCB Design software was used to draw the schematics and design the PCB.  The PCB design was limited to two layers due to cost.  Design considerations such as routing of digital lines, analog lines, and switching nodes were taken into account.

PCB Top Layer

PCB Bottom Layer

DC-DC Converter Section

Input Stage

Microcontroller Section

The DC-DC converter circuit was modeled in LT Spice to verify proper operation over the applicable range of input voltages.  The amount of input voltage ripple was of concern in sizing the input capacitor. 

Circuit Simulation in LT Spice

2,200μF was chosen for the input capacitor since 22 100μF SMD capacitors fit nicely on the PCB, and it provides allowable input voltage ripple at speeds down to 7.5 miles per hour.

Input Capacitor Selection in MATLAB


A custom-built test fixture enabled easy bench-top testing of the hub without having to ride on a bicycle.  National Instruments LabView was used in conjunction with a data acquisition unit to control the speed of the dynamo hub.  A software-based control loop varied a pulse width modulated (PWM) signal to a motor controller board, which drove a DC motor.

Test Fixture

LabView Control Panel

The test code that follows was used to verify basic system functionality.  More complex code would be later developed to run the power management schemes.

//Smartphone Charger Testing Code

//Chris Arntzen

//Master Thesis


#include <avr/io.h>

#include <util/delay.h>     // software delay functions


int main(void){


// set Data Direction for GPIO

DDRD |= (1<<PD0);       //  PORTD0 = output (input_enable)

DDRD |= (0<<PD1);       //  PORTD1 = input (switch1)

DDRD |= (0<<PD2);       //  PORTD2 = input (switch2)

DDRD |= (1<<PD3);       //  PORTD3 = output (greenLED)

DDRD |= (1<<PD4);       //  PORTD4 = output (redLED)

DDRD |= (1<<PD5);       //  PORTD5 = output (battery_enable)

DDRD |= (1<<PD6);       //  PORTD6 = output (phone_enable)

DDRD |= (1<<PD7);       //  PORTD7 = output (converter_disable)


// set Data Direction for ADC Analog Inputs

DDRC |= (0<<PC0);       //  analog pin0/PORTC0 = input (Batt_VSense)

DDRC |= (0<<PC1);       //  analog pin1/PORTC1 = input (Out_ISense)

DDRC |= (0<<PC2);       //  analog pin2/PORTC2 = input (VOut_VSense)

DDRC |= (0<<PC3);       //  analog pin3/PORTC3 = input (In_Isense)

DDRC |= (0<<PC4);       //  analog pin4/PORTC4 = input (VIn_VSense)

DDRC |= (0<<PC5);       //  analog pin5/PORTC5 = input (Temp_Sense)


// set Data Direction for SPI

DDRB |= (1<<PB2);       //  PORTB2 = output (/cs)

DDRB |= (1<<PB3);       //  PORTB3 = output (MOSI)

DDRB |= (1<<PB5);       //  PORTB4 = output (SCK)


// set ADC registers

ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));   

ADMUX |= (1<<MUX0);

ADMUX |= (1<<MUX1);

ADMUX |= (0<<MUX2);

ADMUX &= ~(1<<REFS0);

ADMUX &= ~(1<<REFS1);       //Vref as voltage reference

ADCSRB &= ~((1<<ADTS2)|(1<<ADTS1)|(1<<ADTS0));    //Free-running mode

ADCSRA |= (1<<ADATE);       //Enable auto-triggering

ADCSRA |= (1<<ADEN);        //Enable the ADC

ADCSRA |= (1<<ADSC);        //Start conversion


// initialize variables

int adc_value;

int twohundred_mA = 193;

int onehundred_mA = 96;

int n = 0;

char cData = 0;


//************* MAIN LOOP *************





if(n == 0){


PORTD |= (1<<PD6);      //enable phone


_delay_ms(600);         // Wait for MAX1822 charge pumps to charge



//************* SPI WRITE *************



PORTB |= (1<<PB2);         // Disable CS


/* Enable SPI, Master, set clock rate fck/16 */

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);

//5.5V = 0x01  5V = 0x03  4.2V = 0x0A  3.6V = 0x10

cData = 0x02;

//Start transmission

PORTB &= ~(1<<PB2);         // Enable CS

SPDR = cData;


/* Wait for transmission complete */

while(!(SPSR & (1<<SPIF)))


PORTB |= (1<<PB2);      // Disable CS


PORTD |= (1<<PD0);      //enable input



n = 1;


//************* ADC READ *************



adc_value = ADCW;    //Read the ADC value


if((adc_value >= onehundred_mA) && (adc_value <= twohundred_mA)){

    PORTD |= (1<<PD3);   

    PORTD |= (1<<PD4);   //Turn both LEDs on


if(adc_value < onehundred_mA){

    PORTD |= (1<<PD3);    //If ADC value is above turn green led on

    PORTD &= ~(1<<PD4);   //If ADC value is above turn red led off


if(adc_value > twohundred_mA){

    PORTD |= (1<<PD4);    //If ADC value is above turn red led on

    PORTD &= ~(1<<PD3);   //If ADC value is above turn green led off




return 1;


bottom of page