Académique Documents
Professionnel Documents
Culture Documents
and Controller
ECE 480 Team 9
Tyler Borysiak | Myles Moore | Alex Sklar | Stephen Dunn | Joshua Lamb
MICHIGAN STATE UNIVERSITY COLLEGE OF ENGINEERING
ECE 480 SENIOR CAPSTONE DESIGN COURSE
Executive Summary
In a novel entrepreneurial enterprise, Dr. Pauliah and his sister Ms. Pauliah of the Sunrise
Orphanage in Bobbili, India, are seeking a product that can be manufactured and sold to
help support the orphanage and add a lowcost medical clinic to the existing facility.
The product they are seeking is an electric tricycle, which is in high demand in India and
around the world. Typically, electric vehicles are powered through the use of a costly DC
motor. To combat this problem, ECE 480 Team 9 utilized an inexpensive automotive
alternator that replaced the DC motor, providing high efficiency and increased torque at
wider ranges of speed.
Team 9 has developed and integrated a novel motorcontroller circuit, consisting of a
highspeed sensor and a microprocessor into the novel alternator design. The highspeed
sensor measures the magnetic field produced by a uniquely polarized magnet mounted on
the rotor shaft of the alternator. This sensor sends precise angle information to a
microprocessor. With this data, the microprocessor increases the efficiency of the electric
motor by applying precise power pulses at optimal angles within the motor as it rotates.
Efficiency is further maximized by automatically controlling the magnetic field in the
rotor. Having the ability to control the rotor field made it possible to significantly
improve stopping performance with the use of regenerative braking.
After running multiple design tests, it was proven that the use of the automotive
alternator and the motor controller circuit did in fact increase efficiency, provide wide
ranges of speed, and apply regenerative braking to improve stopping performance.
Page 1
of 103
Not only will this design be used to power an electric vehicle, it also has the potential for
use in other applications that require electric motors. These applications include electric
wheelchairs, industrial forklifts, and numerous industrial applications.
Acknowledgment
The completion of this design would not have been possible without the assistance of the
Team 9 facilitator Professor Virginia M. Ayres, Ph.D., Team 9 sponsor Mr. Stephen
Blosser, Assistive Technology Specialist for the Resource Center for Persons with
Disabilities (RCPD), Piotr Pasik for helping the team gather a suitable tricycle for a
design, Professor Timothy Grotjohn, Professor Lalita Udpa, the guest speakers in class,
Roxanne Peacock, and all of the assistance from the MSU College of Engineering ECE
Shop.
Throughout the design process, Professor Ayres has met with Team 9 frequently and
offered suggestions and guidance in order to successfully complete the project and the
deliverables. She has been a great mentor and has helped the team stay on track with the
design process and has helped the team produce quality work.
The team’s sponsor, Stephen Blosser, was always available to offer guidance to the team.
He has helped the team gather parts, discuss design specifications and deliverables, and
bring new ideas and innovations into consideration.
This project would not have been possible without all of the help that was provided.
Team 9 is very grateful and honored to have worked with such a great group of people.
Page 2
of 103
Table of Contents
1 Introduction and Background…………………………………………………...05
2 Strategic Goals and Design Requirements……………………………………...08
2.1 Customer Requirements Analysis………………………………………08
2.2 Budget…………………………………………………………………..15
2.3 Initial Project Management Plan………………………………………..18
3 Technical Description…………………………………………………………...22
3.1 Hardware Design………………………………………………………..22
3.1.1 Automotive Alternator…………………………………………..22
3.1.2 MOSFET Switching Circuit…………………………………….25
3.1.3 Battery Connections and Protection…………………………….38
3.1.4 Problems and Adjustments……………………………………...40
3.2 Microcontroller and Software Design…………………………………..45
3.2.1 Microcontroller…………………………………….……...…....45
3.2.2 AMS Sensor…………………………………………………….48
3.2.3 Throttle………………………………………………………….53
3.2.4 Software Algorithm……………………………………………..54
3.2.4A Core Design Principles…………………………….....54
3.2.4B Details of the Algorithm……………………………...56
4 Data Testing…………………………………………………………………......62
4.1 Revolutions Per Minute………………………………………………....62
4.2 Input Power……………………………………………………………...64
4.3 Torque…………………………………………………………………...66
4.4 Efficiency……………………………………………………………......68
4.5 Scope Measurements………………………………………………….....69
4.5.1 Common MOSFET Gate Pulses………………………………...69
Page 3
of 103
4.5.2 Rotor Gate Pulses……………………………………………….71
4.6 Design Specification Achievements………………………………….....72
5 Design Issues…………………………………………………………………....73
6 Final Cost, Summary, and Conclusions………………………………………...75
Appendix 1 Technical Roles, Responsibilities, and Work Accomplished…………..78
Appendix 2 References……………………………………………………………....84
Appendix 3 Software Reference Code…………………………………………….....85
Page 4
of 103
Chapter 1 Introduction and Background
Michigan State University is affiliated with the Sunrise Orphanage and its future clinic
through Asian Aid USA, a Christian nonprofit organization that is committed to making a
difference in the lives of children and people in poverty. Asian Aid High School students
in Jaipur, India learn electronic circuit design from Stephen Blosser, an Assistive
Technology Specialist at the Resource Center for Persons with Disabilities. Mr. Blosser is
an honorary ambassador volunteer with orphanages in the area and helps choose
technology for the orphanage members to work with. He has designed an electric tricycle,
which is in high demand in India and around the world. This tricycle could be
manufactured by student employees such as those residing at the orphanage. Students at
the orphanage sponsored by Asian Aid will benefit from the learning experience that the
manufacture and sale of these tricycles
can provide, as well as benefitting from
the parttime employment.
Mr. Blosser’s original design included
the use of a DC motor to power the
tricycle. The DC motor performed well,
but it was too expensive to be viable for
the proposed application. This motivated
a search for an effective costsaving
measure.
It has been previously demonstrated that an automotive alternator can be converted to a
motor and used in place of a standard DC motor. Most alternator conversions apply a
constant current to the rotor within the alternator to create the rotor fields, but by having
Page 5
of 103
to manually supply current to the rotor, the design efficiency is limited. A design that can
automatically control the field current to the rotor only when necessary would maximize
the motor efficiency.
Typically, automotive alternators are used to convert a vehicle’s mechanical energy into
electrical energy that can be used to power the electrical devices in the automobile. This
eliminates the need to stop and charge the battery. The normal application is executed by
applying a constant DC field current to the rotor shaft which then produces a magnetic
field around the core. This magnetic field couples to the set of stator coils fixed to the
shell of the alternator. This coupling produces AC current in the windings. These
windings are placed 120 degrees apart, therefore producing three separate phases. In
order for this current to be used by the electrical devices in the car, it needs to be
converted into DC current. This is done by the diode rectifier circuit. Diode rectification
produces a pulsed DC voltage that can be used to supply the devices in the vehicle. Some
of the more critical automotive components have internal filtering circuits to further
smooth out the pulsed DC voltage. Figure 2 below shows a circuit diagram of an
alternator circuit with a 6 diode rectifier for fullwave rectification.
Figure 2: Automotive Alternator Schematic
Page 6
of 103
The automotive alternator application described above is for an alternator acting as a
generator in order to supply electrical devices in a vehicle. For this project, the goal was
to convert this automotive alternator into a motor in order to drive an electric vehicle. In
order to achieve this, both the rotor and the stator need to be pulsed at the optimal angles.
This requires the development of more complex hardware and software in order to drive
the unusual motor configuration.
The Team 9 design makes use of a highspeed sensor that measures the magnetic field
produced by a uniquely polarized magnet. This sensor holds the potential to increase
efficiency of the motor by sensing the exact location of the rotor shaft which updates the
microcontroller and applies precise power pulses for a short period of time at the most
optimal angles. In order to apply pulses to the stator coils at specific times, a stator
switching circuit is needed to act as a motor controller. Pchannel and nchannel power
MOSFETs are used to turn on and off stator coils when directed by microcontroller logic.
The same circuitry is needed for the rotor in order to apply field current to the rotor shaft
at optimal angles. In order for pulses to be initiated, an external Halleffect throttle is
needed to control the amount of pulses applied to the stator and rotor, which will then
increase the revolutions per minute.
Team 9 proved to be very successful designing a motor and a controller circuit that meets
the sponsor requirements and specifications outlined in Chapter 2 below. This design has
the capability to revolutionize personal electric transportation globally and make a
difference in the lives of many people. Additionally, it has been proven to be a lowcost,
reasonably efficient, and rugged alternative to an expensive DC motor. Through the
eventual production of this design, funding will be generated for the medical clinic as
well, helping to support Asian Aid and improved healthcare.
Page 7
of 103
Chapter 2 Strategic Goals and Design Requirements
2.1 Customer Requirements Analysis
The first step taken during the product planning phase was the analysis and evaluation of
the project requirements given by the customer or sponsor. To effectively plan goals and
an efficient critical path, a design proposal needed to be identified quickly. The first step
in understanding the sponsor’s requirements was to set up an interview to discuss how the
design has the potential to positively impact society and to discuss design goals. Team 9
learned that the most important goal was the ability to make the design as inexpensive as
possible. Other important goals were to maximize efficiency and power consumption by
pulsing the rotor and stator coils, achieve a wide range of speeds, increase the torque at
low speeds, and implement regenerative braking. In order to understand and implement a
design that met all of the requirements, multiple analysis techniques were performed. One
technique was the development of a FAST diagram in order to understand and define the
product functionality and the scope of the project. Figure 3 below is the Team 9 FAST
diagram.
Page 8
of 103
Figure 3: EBike FAST Diagram
The basic function of the design is to use the alternator to control the electric vehicle’s
speed. This is done by either speeding up or slowing down the alternator. In order to
speed up the alternator, the throttle needs to be applied. In order to speed up the alternator
shaft, current needs to be applied to the stator and rotor at the quadrature angles. This is
done using the microcontroller and the software logic to switch the MOSFETs that are
connected to the stator and the rotor. In order to slow down the electric vehicle, the brake
lever needs to be applied. Slowing down the alternator is achieved by slowing down the
alternator shaft. This is done using regenerative braking. Regenerative braking is
executed by drawing current from the alternator to charge the battery that is supplying the
Page 9
of 103
circuit and the alternator. This can be done by controlling the field using the
microcontroller and the software.
Another technique that was utilized was the House of Quality analysis technique. This
analysis method proved to be quite useful because it helped Team 9 understand the
Critical Customer Requirements CCRs for the design. This helped prioritize the
project needs and gave direction for which specifications to look for when selecting
components. The House of Quality matrix is shown in Figure 4.
Figure 4: House of Quality Analysis
This type of analysis was very helpful because it was a tool used to assist in data based
decision making. It also helped to reduce design uncertainty because by understanding
Page 10
of 103
the customer requirements and how the quality characteristics or measures affect them. It
was easy to clarify how the data collected would help determine a bestapproach. It was
also a good tool to determine which measurements would prove to be of higher
importance for selecting a design that best matches all of the specifications. From the
House of Quality, it was determined that efficiency and speed were the easiest customer
requirements to analyze using the quality characteristics. One of the harder requirements
to measure was the reliability. It was also noticeable that high output power and power
dissipation had a strong inverse relationship because the more output power of the
alternator that is measured, the lower the power loss or dissipation. Some of the other
strong positive relationships as seen in the house of quality were high rpm and current
draw, high current draw and output power, and high output power and high torque.
Another useful piece of this type of analysis was being able to prioritize customer
requirements. The most important customer requirements for this design were cost,
efficiency, speed, and reliability.
Once the main project goals were prioritized, project design functionality planning could
begin. To make critical design component selections, decision matrices were developed
which allowed for the comparison of different options in relation to the established
design goals and sponsor requirements. The first major decision encountered was the type
of motor to be used with the prototype. From the motor decision matrix in Figure 5, an
automotive alternator clearly met the goals for the project over other available options, an
AC motor or a brushless DC motor. As can be seen from the decision matrix below, the
alternator is significantly better than its counterparts with regards to cost and speed.
Page 11
of 103
Figure 5: Motor Decision Matrix
The next major design decision the team faced was the choice of microcontroller that
would provide the speed, number of GPIO pins, and floating point operations desired. To
more easily analyze the possible options, another decision matrix was created and shown
in Figure 6. From this comparison, Texas Instruments was chosen over the Raspberry Pi
and the Arduino as it best supported the team’s design goals.
Page 12
of 103
Figure 6: Microcontroller Decision Matrix
The final design decision encountered was the selection of a rotary position sensor
needed to monitor the position of the rotor shaft within the alternator. The sensor decision
matrix shown in figure 7 outlines the criteria used to make the selection of an AMS
sensor over an Avago sensor.
Page 13
of 103
Figure 7: Sensor Decision Matrix
Page 14
of 103
2.2 Budget
One of the key constraints of this project was developing a design that is both cost
effective and efficient. The most expensive portion of the project are the automotive
alternators, which cost around $20 to $30. The use of these alternators instead of
brushless DC motors will save at least $60 per motor. Like most of the parts that are
required for this project, the automotive alternators were already provided to the team;
therefore the cost is not tracked in the $500 budget, but will be included in the cost per
unit budget. Additional parts that were needed include the diametrically magnetized
magnet, the AMS AS5132 rotary sensor, the pchannel and nchannel power MOSFETs,
terminal blocks, power recovery diodes, and an external throttle. Other hardware circuit
components such as color coded resistors, NPN and PNP transistors, zener diodes,
capacitors, heat sinks, and header pin connectors that were required for the MOSFET
switching PCB were not included in the budget since they were obtained from the ECE
shop at no cost. These circuit items were included in the cost per unit budget.
In order to have the opportunity to implement design changes throughout the design
process, extra components were ordered just in case components were damaged during
testing. The table below shows the cost of all of the components ordered by Team 9
throughout the design process. The total prototype design cost was $332.54, which is
within the $500 budget for the semester.
Page 15
of 103
Figure 8: Total Prototype Design Costs
The table above does not include the cost of the PCB fabrication, 10 AWG wiring used
for the stator coils and battery connections, two 12V batteries, and all other hardware
components mentioned above. This is because these components were obtained from the
sponsor or from the ECE shop. A majority of the prototype design costs were shipping
Page 16
of 103
costs. For example, the shipping cost for $0.38 magnets was greater than the product cost.
For the per unit production cost, the cost was calculated without the shipping costs of the
parts.
A per unit production cost was also calculated below to show the cost to make one
prototype Ebike motor and controller.
Figure 9: Cost of One Production Unit
It is easy to see that the cost of one production unit is significantly lower than the cost to
make the prototype design. This is due to the fact that additional components were
ordered even though not all of them were necessary. For future production, terminal
blocks like those used in the prototype design will not be necessary for attachment to the
Page 17
of 103
PCB from the stator coils. Prices for components such as the AMS sensor, recovery
power rectifier, pchannel and nchannel MOSFETs, 10 AWG wire are much cheaper if
bought in bulk quantity. For a production setting, all of these components will be
purchased in bulk.
2.3 Initial Project Management Plan
The initial project timeline consisted of seven main phases. These phases include project
definition, research of new designs, development of conceptual designs, initial prototype
preparation, initial testing, initial prototype construction, and final design construction.
The project schedule and project timing was organized using a Gantt chart. This Gantt
chart displayed the seven main phases, which were further broken down into tasks.
These tasks consisted of a start date and an end date. The project schedule consisted of a
critical path. Tasks on the critical path could not be started unless the task before was
completed. These tasks were the most critical to the project because any delay caused a
delay to the whole project. It was important to try to shift the critical path. Below is the
Team 9 initial Gantt Chart.
Page 18
of 103
Page 19
of 103
Figure 10: Initial Project Gantt Chart
For the most part, the project Gantt chart was followed exactly as noted above throughout
the design process. The only modification came near the end of the design process in the
“Construct Final Design” phase. Since the team decided to go with one PCB design, the
“design PCB layout” and “PCB fabrication/soldering” tasks were moved to the
Page 20
of 103
“Construct Initial Prototype” phase. The project prototype and final design were very
similar, and the PCB was fabricated before testing efficiency. This was because in order
to run and test the high current portion of the circuit, a PCB needed to be fabricated. A
breadboard could not be used for these tests.
Page 21
of 103
Chapter 3 Technical Description
3.1 Hardware Design
3.1.1 Automotive Alternator
The automotive alternator is perhaps the most important component or piece of the
design. Without the alternator, there would be no source of mechanical power to run the
electric tricycle. After selecting an automotive alternator to be the motor for the design, it
was important to select the correct stator coil orientation that best fit the design. The
figure below shows a common automotive alternator and its main components.
Figure 11: Automotive Alternator Components
The main hardware components that Team 9 utilized within the automotive alternator are
the rotor and the stator. The rotor of the alternator consists of a coil of wire wrapped
around an iron core. DC field current produces a magnetic field around the core. The
Page 22
of 103
stator is a set of coils fixed to the shell of the alternator. Magnetic field from the rotor
couples to the stator coils producing current in the stator windings. These stator coils are
placed 120 degrees apart, producing 3 separate phases.
The automotive alternators used in this design are of the hybridbrushless variety, having
no expensive, internal rareearth permanent magnets. Instead, the motors require that a
small amount of current be passed through brushes to a coil in the rotor in order to
magnetize it. Current is then applied to the outer stator coils in order to induce an
electromagnetic force to turn the rotor. The stator has 36 coils around its perimeter. The
test alternators have 36 coils that are wired into 3 phases connected in a “delta” pattern
such that each phase has 12 coils and each coil is separated by 10 degrees around the
stator.
The first step in the hardware design process was to determine the most effective way to
orient the stator coils in the alternator. As mentioned above, the alternator was originally
connected in a delta configuration. Delta configuration allows for lower voltage but
higher current. The figure below shows a delta connection and a Wye connection with a
common.
Figure 12: Wye Connection with a Common (Left) and Delta Connection (Right)
Page 23
of 103
In order to precisely pulse only one stator coil at a time, the alternator was reoriented to
a Wye connection with a common wire. This was less resistive than the delta connection
and allowed for more current to pass through the stator windings providing higher RPMs.
The first test that was run with the alternator before any hardware or software was
developed was a connection of the rotor field coil to a 12V battery, and the connection of
each stator phase to either 12V or ground. A current limiting resistor of 1Ω was placed
from the active stator coil to ground in order to limit the current and the torque in the
alternator. This was implemented strictly for testing purposes and was removed in the
final design.
This test was performed in order to find the alternator stepping states. This was a critical
design procedure because the software code uses this stepping theory in order to know
which stator coil to pulse in order to rotate the rotor shaft. When these connections were
made, each stator phase rotated 10 degrees when connected to the batteries. This covered
30 degrees in 3 phases and by activating the same three phases with the opposite polarity,
the next 30 degrees could be covered. This pattern then repeats 6 times every 60 degrees
to make a full 360 degree rotation. Because of the Wye configuration of our motor, one
end of each stator coil is exposed as an external connection. These three external
connections are arbitrarily labeled Black, Green, and Red. The other end of all three coils
are connected together and exposed as a single “common” external connection. The
following table describes the connections required to turn on on the 3 stator coils to rotate
the rotor 60 degrees in one direction.
Page 24
of 103
1 12 volts Black to ground
2 12 volts Green to ground
3 12 volts Red to ground
4 ground Black to 12 volts
5 ground Green to 12 volts
6 ground Red to 12 volts
Figure 13: Stator Coil Sequence
After the 12V stator switching tests, the rotor resistance was calculated. Since 12V was
used to supply the rotor, the current draw was measured at the rotor. This current value
was found to be 3A, so the resulting rotor resistance with 12V supplied to the rotor is 4Ω.
3.1.2 MOSFET Switching Circuit
After the alternator pulsing states were understood, the next step in the design process
was to develop a MOSFET switching schematic to interface with the microcontroller and
the software in order to pulse specific stator coils with current at specific moments in
time. Pchannel and nchannel MOSFETs have the capability of turning on or off
depending on the gate to source voltage difference. The figure below shows the circuit
symbol for a pchannel MOSFET.
Page 25
of 103
Figure 14: Pchannel (Left) and Nchannel (Right) MOSFETs
In order to understand the application of these MOSFETs in a power electronics setting
like this design, it was important to understand how they can be turned on and off. For
the hardware portion of the initial demo, a breadboard circuit was constructed after power
MOSFETs were ordered that simulated the switching of current to different stator coils.
The schematic for this simple MOSFET switching circuit is shown in the figure below.
Figure 15: Initial Demo MOSFET Switching Circuit
The pchannel MOSFETs are the top row of MOSFETs in the circuit diagram with their
sources connected to the 12V supply line. The drains of the pchannel MOSFETs were
connected to two LEDs (one red and one green) in parallel and oriented in reverse to
simulate the stator coils. If the top LED turned on, then it was known that current was
Page 26
of 103
flowing from the left side of the circuit to the right side, and vice versa for the other LED.
The nchannel MOSFETs are the bottom row of MOSFETs with their sources connected
to the ground line and their drains also connected to the stator coil LEDs. As mentioned
earlier, in order to turn on the MOSFETs, a voltage needed to be applied to the gates of
the MOSFETs. For the pchannel MOSFETs, the Vgs, or the gate to source voltage needs
to be greater than 3V to turn on. Therefore, in the demo Team 9 shorted the gate and the
source together to turn the pchannel MOSFET off. In order to turn it on, the gate voltage
was driven by 5V. For the nchannel MOSFETs, they were turned off by shorting both
the gate and the source to ground. In order to turn them on, a voltage of 5V was applied
to the gate. For example, if the goal is to turn on LED A in the circuit diagram above, the
pchannel MOSFET labeled “1” needs to be turned on, and the nchannel MOSFET
labeled “2” needs to be turned on. This lets current flow from the source of “1” through
the LED “A” and down to ground, or the source of “2”. This is how each stator state is
pulsed with current and activated. The figure below is a picture of the initial demo setup.
Figure 16: Initial Demo Setup
After successfully completing the initial demo and understanding how to switch states
and pulse the LEDs with the MOSFETs, the next step in the hardware design process was
to design a schematic that would allow for a 0V or 3.3V input from a microcontroller to
Page 27
of 103
control the gates of the MOSFETs, signifying which MOSFETs are on and off. To
achieve this, the circuit schematic in the figure below was developed for each of the
stator coils.
Figure 17: MOSFET Gate Circuit
The 3.3V inputs from the microcontroller are on the left side of RE1 and RE4 in the
schematic above. When 3.3V was applied to either of these resistors, it would turn on the
corresponding MOSFET. The final design consisted of four of these circuits, one for each
stator phase and one for the common phase.
The next step in the design process was to construct a prototype of the gate circuit and
test the functionality. This was done at low voltage and current levels and on a
Page 28
of 103
breadboard. The circuit in the schematic above was constructed. Only one stator phase
and the common phase was constructed because the rest of the switching circuitry will
have identical components and functionality. Below is a picture of the MOSFET gate
prototype circuit on a breadboard.
Figure 18: MOSFET Gate Circuit Prototype
In order to simulate the microcontroller code, a 3.3V power supply was connected to RE1
or RE4 depending on which MOSFET was to be activated. The remaining simulated
microcontroller inputs were grounded. The circuit was powered with 12V from another
power supply and the LEDs correctly simulated the activation of the stator coils.
The next step, and arguably the most critical hardware step, was the transfer of the
schematic and circuitry onto EAGLE software in order to fabricate a PCB. This was done
by first creating a schematic file and drawing the circuit connections. The first step was to
duplicate the gate MOSFET circuit for all of the stator phases. Once this was completed,
a connection to the batteries and the terminal blocks needed to be accounted for. There
were no footprints in EAGLE for high current connections, therefore terminal block
Page 29
of 103
footprints needed to be ordered and created in EAGLE. Below are the terminal blocks
that were used for the design.
Figure 19: Terminal Blocks on PCB
In order to pulse both the rotor and the stator, rotor pulsing circuitry was also critical.
This was done using the same concept as the nchannel portion of the stator pulsing
circuit. The rotor circuit schematic is shown below.
Figure 20: Rotor Gate Schematic
Page 30
of 103
It is easy to see that there is no 12V connection to the emitter of BJT14 like there is in the
stator switching circuit. This was a simple design error that was easily fixed by soldering
a wire from the emitter to the 12V source line on the PCB right after fabrication.
Now that the stator and rotor circuitry was developed, the next step was to develop a
power supply circuit in order to step down the voltage from 12V to 5V and 3.3V in order
to power the microcontroller and the remaining peripherals such as the AMS sensor, the
LCD display, and the halleffect throttle. Below is a highlevel block diagram of all of the
hardware used in the design. The block diagram proved to be very helpful in the
development of the rest of the peripheral circuitry and the connections to the
microcontroller in EAGLE.
Page 31
of 103
Figure 21: HighLevel Block Diagram
In order to support the MOSFETs and protect them during avalanche mode or
regenerative braking, the hardware design needed recovery power rectifiers from the
source to the drain of each pchannel MOSFET. These MOSFETs contain a protection
diode inside from the source to the drain, but with the amount of current used in the
design during avalanche mode, these would be damaged. These diodes are referenced in
the appendix 2 section.
Page 32
of 103
To make sure that the microcontroller pins would not erroneously send pulses to both the
pchannel and nchannel MOSFETs simultaneously, diodes were inserted from the
collector of the NPN transistors to the 1kΩ output of the microcontroller. This makes sure
that the MOSFETs of the same phase do not turn on at the same time.
Another design implementation that occurred during the development phase was
placement of the 9V zener diodes from the source of the pchannel to the gate in order to
keep the gate to source voltage a constant 9V difference when the MOSFET is activated.
The same zener diodes were also placed between the gate and the source of the nchannel
MOSFETs for the same reason.
The next step of the hardware design was to develop a power supply circuit in order to
convert 12V from the battery into 5V for the LCD display, throttle, and the AMS sensor.
Another portion of the power supply needed to step down 5V to 3.3V in order to power
the microcontroller. The circuit that was used is the power supply circuit from the earlier
ECE 480 labs and is shown in the figure 22 below. It contains two voltage regulators and
5 capacitors.
Figure 22: Power Supply Circuit
Page 33
of 103
Node 1 of IC1 is the 12V input from the battery supply. Node 3 of IC1 is the 5V output
that goes to the peripherals mentioned above. Node 3 of IC2 is the 3.3V output that goes
to the microcontroller.
After connecting the power supply circuit, the next step was to connect the peripheral
circuitry together. In the design, it was important to make sure that the spacing of the
microcontroller header pins was exactly 1.5 inches apart so that the microcontroller could
successfully connect to the PCB. Header connectors were also needed for the connection
of the AMS sensor, the throttle, and the LCD display. These were placed conveniently on
the board so that they could easily be connected and would not interfere with other
connections.
The rest of the schematic was wired together and double checked to make sure that all of
the correct connections were made. The final prototype schematic from EAGLE is shown
in the figure below.
Page 34
of 103
Figure 23: Final Prototype Schematic
After correct routing of the schematic, the next step was to transfer the schematic onto a
PCB. This was also performed using the EAGLE software. In this phase of the hardware
design, it was crucial that the high current and low current sections of the PCB were
separated and understood. In order to accomplish this, the high current traces from the
drains of the MOSFETs to the terminal blocks for the stator coils were given a width of
0.254 inches in order to sustain the high amount of current. These traces were routed on
Page 35
of 103
the top of the board. On the bottom of the board, the low current traces for the MOSFET
gate circuitry and the connections to the peripheral devices were routed using a width of
0.024 inches. Several vias were needed in order to route some of the traces. A figure of
the final prototype board is shown below.
Figure 24: Prototype PCB Design
The surrounding copper on the PCB that was not used for routing or for components was
the ground plane for the design. One of the terminal block pins was connected to this
plane from the negative terminal of the supply battery.
Page 36
of 103
Once the PCB was fabricated in the ECE shop, the throughhole components needed to
be soldered to the PCB. It was important to add wires from the top of the board to the
bottom of the board at all of the vias. Additional copper wiring was added to the drain to
stator connections as well as the 12V source line on the PCB. This was so that the current
limit was never reached and the traces were able to handle at least 70A of current. The
figure below shows the copper wire added to the physical PCB.
Figure 25: Copper Wire on the High Current Traces
After the soldering was complete and all components were placed onto the board, the
next step was to make the battery and stator connections to the terminal blocks and to
develop a circuit protection system.
Page 37
of 103
3.1.3 Battery Connections and Protection
The diagram below shows how the connections were made into the terminal blocks from
the battery and from the alternator.
Figure 26: Battery/Alternator Connections
The terminal block on the left has connections to ground (negative terminal of the
battery), negative slip ring of the rotor, positive slip ring of the rotor, and the 12V battery
positive terminal. The 12V positive terminal and the positive slip ring of the rotor were
shorted together since both the rotor and the circuit are both supplied with 12V. The
Page 38
of 103
second terminal block is for the connection to each of the stator coils. There are 4 phases
in the Wyeconnected alternator with a common. These were named black, green, red,
and common.
In order to make sure that a secure and rugged connection was made to the battery
terminals, eyelet connectors were used. Other hardware protection techniques were made
as well. In order to make sure that only a specific amount of current was drawn by the
circuit for the prototype, a 20A circuit breaker was placed at the negative terminal of the
battery.
Another protection requirement was to make sure that the MOSFETs were protected from
heat. To meet this requirement, large metal heat sinks were attached to the drain tabs of
each MOSFET. The figure below shows these heat sinks. Later in the design process, a
heat sink was also added to the nchannel MOSFET in the rotor circuit.
Figure 27: Heat Sinks Attached to MOSFETs
In order to protect the entire PCB, a metal box was constructed so that the PCB and all of
the components are protected from any external electrical interference. The figure below
shows the metal box with the PCB inside.
Page 39
of 103
Figure 28: Enclosure with PCB Inside
3.1.4 Problems and Adjustments
One of the first issues that occurred during the hardware design was that the footprints for
the MOSFETs utilized different pin configurations than what the team was using for the
design. In order to adjust for this, the team had to modify the existing footprint in order to
have the pins oriented as “Gate, Drain, Source”. In the future, the MOSFET footprints
Page 40
of 103
should also be modified so that the individual pins have more separation. This would
prove to make soldering and placing the components much easier.
The same issue occurred with the NPN and PNP transistors. This was fixed in the same
way by modifying the component footprints in EAGLE so that the pins were oriented as
“Emitter, Base, Collector”.
Another hardware issue that came up was that the microcontroller was not reading the
throttle as accurately as it should have been. This was due to an incorrect voltage divider
resistor value from the throttle output to the microcontroller input. This was adjusted and
resolved by changing the resistance from 22kΩ to 2.2kΩ.
From running tests on the gate of the red phase stator circuit, a bad diode was also found
by running a continuity test at both of the diode leads. This was quickly replaced and the
circuit worked properly.
During initial testing, the microcontroller was erroneously resetting. The issue was
resolved by placing a 1uF capacitor from the reset pin on the microcontroller to ground,
and placing a 1kΩ pullup resistor to 3.3V to fix the issue.
Throughout the hardware design process, the team faced two major design issues. The
first issue was that the common pchannel MOSFET was not functioning properly. This
was a direct result of the nchannel common fall time being too long because the gate
circuit had too much resistance. Below in Figure 29 is a graph of the pchannel gate pulse
(top) and the nchannel gate pulse (bottom).
Page 41
of 103
Figure 29: PChannel and NChannel Common Gate Pulses
This problem was resolved by altering the resistance values of the common gate circuitry.
All of the 10kΩ resistors in the common pchannel and nchannel gate circuitry were
changed to 1kΩ. All of the 3.3kΩ resistors in the same circuit were changed to 330Ω
resistors. These alterations fixed the pchannel common MOSFET issue.
The second major hardware design issue was that the 12V battery source line was
producing a lot of noise in the gate circuitry and at the microcontroller pins. This is a
common problem in many circuit designs. Below in Figure 30 is a graph showing the
noisy supply voltage (second from bottom) and the noise generated at the microcontroller
Page 42
of 103
pin (second from top). The top channel is the pchannel common gate pulse and the
bottom channel is the nchannel common gate pulse.
Figure 30: 12V Supply Noise Issue
To fix this issue, the team added 100uF (50V) capacitors to the 12V source line on the
PCB right before the connection to the gate circuits and the microcontroller. A diode was
also added in series to the 12V supply line after the MOSFET connection and before the
gate circuit connection. This diode limited the current to one direction. A 100uF capacitor
was also added to the 12V terminal block connection to further limit the 12V source
noise. The graph in Figure 31 shows the supply voltage (top channel) with the noise
Page 43
of 103
significantly reduced. It also shows a working pchannel common gate pulse (middle
channel) and a working nchannel common gate pulse (bottom channel).
Figure 31: Graph Showing Design Issue Resolution
Page 44
of 103
3.2 Microcontroller and Software Design
3.2.1 Microcontroller
A microcontroller was integral in the design of the circuit as it allowed an interface
between custom developed software and the hardware circuits. A microcontroller is a
computer chip that integrates a microprocessor, memory, hardware modules and physical
interfaces into one package. The microcontroller provided the pulses for the circuit to
turn on and off the MOSFETs to drive the motor. The microprocessor processes the
calculations for the pulsing of the stator in real time. The hardware modules interface
with the physical pins on the chip to allow communication with external peripherals.
These modules include analogue to digital converters, pulse width modulation generators,
digital pulse generators, digital interfaces and timers.
The microcontroller to be chosen had a series of requirements that needed to be met. The
microcontroller needed to be sufficiently fast. The upper limit of the rotational speed for
the motor was initially thought to be 10,000 rotations per minute. This would translate to
3,600,000 angles per minute or 60,000 angles per second. The microcontroller would
need to read the data at a speed of 60kHz. As data is usually transmitted in bytes (8
digital bits), the microcontroller would need to be able to take in multiple bytes at this
rate, calling for a higher clock rate. The microprocessor also needed to be able to make
calculations on which motor phases to enable at each of these angles, increasing needed
processing power. The microprocessor needed to be able to calculate fractions in real
time to be able to make more accurate calculations with no loss in speed. These
calculations can be simulated on the microprocessor itself, however, a Floating Point Unit
(FPU) allows the processor to offload fractions and thereby decimal values to the unit to
improve the speed of microprocessor. The microcontroller needed to be energy efficient
Page 45
of 103
to lower the overall power consumption. It needed to be able to have at least 19 hardware
interface ports to allow an interface to the MOSFETs, a throttle, a sensor, and an LCD for
testing. These hardware interface ports are called General Purpose Input Output (GPIO)
ports. The MOSFETs needed 9 ports, 2 for each phase, 2 for the common and 1 for the
rotor. The sensor needed 3 ports, the throttle needed 1 and the LCD needed 6.
Many microcontroller choices were available. The top 3 most commonly used
microcontrollers are available from Texas Instruments, Raspberry PI and Arduino. Each
had strengths and weaknesses, which required a starting point be set for research. The
first requirement that was chosen to research was the floating point unit. A floating point
unit is part of the architecture of the chip itself,
rather than a module added by specific
manufacturers. A search of lowcost
microcontrollers from these manufacturers show
the Arduino does not have a floating point unit.
The other two manufacturers have solutions
with a floating point unit. These
microcontrollers are based on the Acorn RISC
Machine (ARM) Cortex family of
microcontrollers.
With an architecture, the next requirement was
low cost. The lowest cost solution came from Texas
Instruments. The Texas Instruments board has a Cortex M4F microcontroller which is
the lowest in the family of Arm Cortex microcontrollers with integrated floating point.
The Texas Instruments boards range from $13.03 to $13.49 for the lowest cost models.
The microcontroller used for this design is the Texas Instruments TM4C123GH6PMI.
This microcontroller runs at a max clock speed of 80MHz, which allows the chip to be
Page 46
of 103
able to make the required calculations in real time. This microcontroller has a hibernation
module that allows the chip to improve power usage by going into hibernation during
periods of inactivity. This microcontroller has up to 43 GPIO ports, exceeding
requirements. This microcontroller also has a great deal of documentation,that is
referenced in the appendix below, which contributed to the development phase of the
software. For prototyping purposes, a TI Launchpad TM4C123GXL evaluation board
was used. This board has the chosen microcontroller on a presoldered board with easy to
use pins for testing. Another iteration of the design would use the microcontroller
soldered directly to the board.
The microcontroller evaluation board was integrated into the circuit by using rows of pins
that the board could plug directly into, as it has connectors on the bottom that accept the
pins. These connections can be seen in the hardware section. Header pins were routed to
the various devices on the board that needed a direct connection to the microcontroller.
Groupings of pins are dedicated to the MOSFETs, an LCD, a throttle, and an AMS
sensor. The board design allowed for the microcontroller to be easily removed and
reprogrammed safely. The evaluation board also allowed for the pins to be tested through
the use of the pins on the top of the board. Integration required enabling of the general
purpose output pins for digitally pulsing the pins. These pulses drove the pins at a voltage
of 3.3V for a digital 1 and 0V for a digital 0. This pulsed the bipolar junction transistors
in the circuit to turn on and off the MOSFETs. The throttle required the enabling of an
analogue to digital converter that used the voltage output of the throttle to provide
percentage values for the software.
Page 47
of 103
3.2.2 AMS Sensor
To sense the rotational angles of the rotor shaft of the alternator, a specialized sensor was
required. In a DC brushless motor, a Halleffect sensor is used to measure the magnetic
field from the rotating magnets on the rotor.
Hall sensors work on the Halleffect
principle that when a currentcarrying conductor is exposed to the magnetic field, charge
carriers experience a force based on the voltage developed across the two sides of the
conductor. As the permanent magnets in the rotor pass the sensor, a voltage is read which
determines the location of the field in relation to the sensor.
These sensors are built into
the design of the DC motor. The sensor to be used would need to be external to the
device to reduce costs and lower future manufacturing complexity. A solution to this
problem is to use a magnet affixed to the end of the shaft and a sensor placed externally
to read the field as the magnet spins. The sensor for this application is a magnetic rotary
encoder. A magnetic rotary sensor uses an array of Halleffect sensors to measure the
field as a diametrical magnet spins a few millimeters from the center of the array. by
using such a device, the angle of the shaft in relation to the stationary stator can be read
by the microcontroller.
Multiple companies manufacture magnetic rotary sensors. The
Austrian Micro Systems (AMS) AS5132 and Avago Technologies
AEAT6600T16 are two solutions available
. To choose from the
available options, a set of requirements were made. The first was
cost, the AMS chip , the Avago chip costs $8.04 for a
production chip, the AMS is $2.79 for a production chip.
The second was for the sensor to be easily purchased, as
the sensor would need to be purchased from different nations, both companies provide
easily available parts. The third was for the chip to be able to handle very high rotations
Page 48
of 103
per minute as the motor would have the potential to rotate at thousands of rotations per
minute. The AMS is able to read 72,900 rotations per minute (rpm), while the Avago can
read 30,000 rpm. The fourth was for the chip to be able to read at least 360 discrete
angles, the AMS chip reads 360 angles, the Avago reads 65,536. Finally, the availability
of a development board for testing was weighed. The AMS chip is available as a
development board, while the Avago is not. The chip chosen for the task is the AMS
AS5132 chip shown in Figure 34.
Figure 34: AMS Block Diagram
With a chip selected, the next step was to read the data from the sensors. Initially, the
format used by the AMS sensor appeared to follow a subset of the Synchronous Serial
Interface standard. This subset, called Microwire, was developed by the National
Semiconductor Corporation. The interface defines a way that information is sent and read
by the chip. The way the chip first received instructional data to enable either reading or
writing to the chip and then communicated data afterwards closely resembled this format.
After testing, it was found that although the chip appeared to use Microwire, the chip had
a slight offset between the instruction and the data right after the 0 bit of the 8bit control
shown in figure 35.
Page 49
of 103
Figure 35: AMS Sensor Data, Upper is Microwire, Lower is Tested Pulses
This led to a custom software solution that sent the control data to the chip and sent
received the data from the chip when the microcontroller is able to read it. This data was
read in a binary format that corresponded to 360 angles, from 0 to 359. With these values,
angle data could be used within the software to trigger pulses of the stator coils based on
which grouping of angles the sensor fell within, the optimal quadrature angles.
Page 50
of 103
The needed optimal quadrature angles were measured using the angle data from the AMS
sensor, displayed on an LCD, and the force of the motor when it was locked into one of
the phases using a test setup shown in figure 36. To do this, the rotor was powered
directly from the battery, to produce full field. One of the stator coils was also powered
directly from the battery, to produce full field. This locked the rotor into a stationary
position. The angle was then read, this is the center of each of the 6 poles for the phase.
The rotor was then turned and the force exerted by the turning of the rotor was measured
on a scale. This force was due to the tendency of the field to want to stay locked into the
pole position. As the rotor was turned further, the scale showed the force to increase as it
moved away from the pole. The force was measured at each of the poles and the
maximum was found to be approximately 12 degrees away from the pole shown in
figures 37 and 38. With this data there was a starting point for implementing quadrature
angles within the software.
Figure 36: Picture of Quadrature Angle Measurement with Initial Sensor Integration
Page 51
of 103
Figure 37: Quadrature Data
Figure 38: Pole Averages with Quadrature Value
Page 52
of 103
The final design has the sensor mounted directly to the casing of the alternator. A
presoldered board was used for this
design. The chip on the board is placed
directly over the magnet, which is bonded
to the end of the rotor shaft as shown in
Figure 39. This design would ease future
manufacturing as only minor alterations to
the alternator would be required.
Integration into the circuit required
certain GPIO pins to be enabled a
physical interface for the software.
3.2.3 Throttle
A throttle was needed to provide a user interface to the motor. The throttle needed to be
rugged and bike mountable. The throttle selected by Team 9 is the Electric Scooter
Throttle, Type2 by Parts for Scooters shown in Figure 40. This throttle uses a Halleffect
sensor, instead of the variable resistor sometimes found
in electric throttles. Twisting the throttle varies the
strength of the magnetic field adjacent to the sensor,
which sends a corresponding voltage between .74V and
4.15V to the microcontroller. By using the halleffect
sensor, the throttle is more rugged and reliable as
there are no moving electrical components, in
Page 53
of 103
contrast to the variable resistor which can wear over time.
3.2.4 Software Algorithm
3.2.4A Core Design Principles
One of the largest tasks in the development of the motor controller was the development
of an algorithm suitable for correctly and efficiently driving the power MOSFET
hardware in order to operate the motor. The final solution provides a central hub
connecting the throttle, AMS rotary position sensor, and power MOSFET circuitry in a
meaningful and intelligent manner. Throughout the development of the software portion
of the project, there were four core software design principles essential to the immediate
and continued success of the project: Correctness, Maintainability, Rapid Development
and Speed of Execution.
Above all, correctness was the most important value. Without a correct algorithm, the
motor controller would be largely useless. This is a well known, but very important
concept within computer science and engineering in general. Only after a correct solution
was found did we focus on the other three design principles.
Maintainability was important because the code for this motor controller will very likely
have a long service life and see several different programmers and maintainers in future
iterations. Realworld maintainability was achieved through the use of good coding
practices including the appropriate use of commenting, good coding structure, consistent
formatting, and clear and concise naming. Additionally, much care was taken to not
“overengineer” the code. In other words, in order to make the code more easily
understood by future programmers, simpler code structures and algorithms were
Page 54
of 103
employed whenever complex algorithms and code structures were not needed for
correctness or speed of execution.
The capability for rapid development was needed due to the tight time constraints
imposed on the project. It was known from the beginning of the semester that the length
of the semester was going to be a limiting factor on the capabilities of the software.
Importance was placed on getting a working solution as quickly as possible so that
iterative improvements could be implemented continuously until the end of the semester.
Rapid development was achieved in several ways. First, it was decided that the software
would be written in C++, a language intimately familiar to all of the team members
collaborating on the software. Second, it was decided that the development environment
used would need integrated debugging support so that problems with the code could be
quickly and decisively corrected. The development environment that was eventually
chosen (Code Composer Studio, by Texas Instruments) allows the code running on the
microcontroller to be paused and stepped through linebyline while, at the same time,
showing the contents of memory and other variables. This last capability proved
invaluable when troubleshooting complex software issues. The software development
was started very early in the semester with the bare minimum supporting hardware being
implemented on a protoboard. This allowed drivers to be written to communicate with the
AMS rotary position sensor and throttle peripherals before the software and hardware
were ready for integration.
The design principle integral to the success of the software portion of the project was
speed of execution. Only after a portion of the code was deemed to be logically correct
and maintainable, was it considered for optimization. Indeed, a great deal of optimization
is done automatically by the C++ compiler when it translates the C++ code into ARM
assembly language. Additionally, a sufficiently fast microcontroller was chosen such that
speed would not be an issue that would limit the functionality of the final product. Future
Page 55
of 103
iterations of the design could make use of a less expensive yet slower microcontroller by
implementing more aggressive code optimizations.
3.2.4B Details of the Algorithm
In the most basic sense, the software algorithm to drive an alternator as a motor only
needs to make one major decision on each loop through the algorithm. Namely, the
software needs to decide which coils of the stator to turn on and which ones to turn off at
any given point in time. In order to do this effectively, two main pieces of information
need to be gathered: the absolute angle of the rotor shaft relative to the stator coils, and
the throttle input from the user. As mentioned previously, this design uses C++ and as
such, takes advantage of the objectoriented software design patterns available when
using this language. For those unfamiliar with the meaning of “objectoriented design
patterns” this means that the language allows for the definition of “objects” within the
code which can represent both abstract concepts and real world objects. These definitions
are called “classes.” Within the code implemented for this design, four main classes were
defined to represent the four primary components of the physical hardware. These classes
are the RotorManager, StatorManager, ThrottleManager and finally the AS5132Sensor
representing the rotor, stator coils, throttle input, and rotary position input respectively.
Various other small supporting classes were created as well. The motor control algorithm
operates in a tight repetitive loop with three simple steps: Update the throttle, update the
rotor, and finally update the stator. Each step is important and generates some bit of
information needed by the next step.
First, within the update method of the throttle a value is read from the analog to digital
converter (ADC) connected to the throttle pin. This value is converted to a percent
between 0 and 100 based on experimentally predetermined limits on the numerical
Page 56
of 103
outputs of the ADC. The following equation is used to convert the numerical output of
the ADC into a percentage:
The percentage is then stored internally for later use. If the ADC can not be read in a
reasonable amount of time, this step is skipped and the previous value for the throttle
percentage is used. This is done to prevent the microcontroller code from from freezing
and potentially causing an unsafe mode for the motor.
Second, the rotor is updated. This step is significantly more involved than the throttle
update because it involves reading an angle value from the AMS rotary position sensor.
The first step in updating the rotor mager is to determine how much time has passed since
the last update. This is used primarily to determine the speed of the rotor by comparing
the elapsed time between updates with the change in angle measurement between
updates. After the elapsed time has been recorded and the timer started again
immediately, the AS5132 driver component is instructed to take an angle reading from
the AMS rotary position sensor. The driver does this by implementing the serial protocol
described in the data sheet for the AS5132 sensor.
First, the chip select pin is pulled low to begin the transmission. Then the first seven out
of eight command bits are clocked in by writing the corresponding command bit to the
DIO pin and then pulsing the clock pin. The last data bit needs to be handled differently
due to the nature of the protocol. The 8th command bit is written to the DIO line and the
rising edge of the clock is given to latch the bit into the memory of the AMS chip.
However, on the falling edge of this clock pulse the sensor chip will immediately change
Page 57
of 103
its end of the shared DIO line to an output and begin driving bits on the line. If the
microcontroller does not switch its end of the shared DIO line to an input before this
happens, two microcontroller outputs may be inadvertently tied together creating a short
circuit that could cause damage to either chip. For this reason, the microcontroller side of
the DIO line is changed to an input before allowing the falling edge of this clock pulse to
occur. This ensures both the correctness of the protocol and the safety of both the rotary
position sensor and the microcontroller. Finally, 16 data bits are clocked in from the chip
and the chip select pin is pulled high to terminate the transmission. The raw data is
unpacked into the individual readings including the strength of the magnetic field begin
sensed and (most importantly) the angle of the field. This last value is interpreted as the
angle of the rotor shaft itself. Following the update of the AS5132 driver, the actual angle
of the rotor can be obtained and used for processing.
Now that the rotor class knows the angle of the actual rotor, it first checks to make sure
the reading is valid. There are several errors that can occur in transmission and if any one
of them has indeed happened, the rotor manager throws away the faulty angle reading
and retains the last known good reading. For example, the rotary position sensor contains
an internal ADC and if a read of the angle is attempted while that ADC is locked, the data
is unreliable. Additionally, if a bit is flipped in transmission or if the previous angle
reading is equal to the current angle reading, the new reading is discarded because it is
meaningless. Assuming, however, that the angle reading is a good one, it is written down
to be used later. If there have been at least two good angle readings, the velocity of the
rotor is also computed and written down for later use.
The third and final step is the updating of the stator performed in the stator manager
class. This step synthesizes the information gathered in the first two steps regarding the
position and speed of the rotor as well as the position of the throttle. It is in this step that
the microcontroller actually chooses the driven stator coil and whether or not to drive the
Page 58
of 103
rotor coil. First, the rotor angle and the throttle percent are retrieved from the rotor
manager and throttle manager respectively. The stator manager then computes an
effective angle for the rotor given its actual angle. Because the stator coil configuration is
repeated six times in one rotation of the rotor, the actual angle of the rotor can be
converted into an equivalent angle in the range 0 to 60 degrees without changing the
operation of the motor. This is done using a modulus operation.
The stator manager now needs to make a decision regarding the rotor. During motor
startup, a large amount of torque is desired in order to reliably start the motor and prevent
stalling. This can be achieved by turning the rotor coil on at all times as long as the rotor
is spinning slower than a predetermined speed. Once the rotor is spinning fast enough,
efficiency and top speed can be achieved by lessening the field strength in the rotor. This
is done by modulating the rotor to only be active half as much as it would be under
startup conditions. The following code snippet is responsible for deciding how to handle
the rotor pulses:
It is interesting to note that, during the startup state, not only is the modulation of the
rotor turned off, the throttle is also assumed to be at 100 percent regardless of the actual
Page 59
of 103
throttle position. This allows the motor to start reliably no matter the angle at which the
rotor finds itself when it needs to start spinning. As soon as the rotor begins to turn, the
throttle resumes its normal operation and the rotor coil begins modulating to improve
performance and efficiency.
Next, the stator manager needs to decide which coil to turn on given the current rotor
angle and throttle percent. This is done by asking each state (there are only 6 of them) if
it can handle the current rotor angle given a particular throttle percent. Each state has a
method on it called “CanHandleAngle” which returns true if the state should be on right
now and false if the state should be off. If a state reports that it should be active, it is
recorded as the active state to be turned on after the loop. The reason for this is one of
circuit safety. When moving from one state to another, it is important to turn the previous
state off before turning the next state on so that a short circuit is not created in the
Hbridge mosfet circuitry. For this reason, if a state reports in this loop that it should be
inactive, it is turned off immediately. After the loop completes, whichever state reported
itself to be active (if any) is enabled along with the rotor coil. To really understand when
a coil should be on or off, it is necessary to look at the contents of the previously
mentioned “CanHandleAngle” method.
Each state has the ability to determine if it should be on or off for any given angle and
throttle percent. When the state is constructed, an optimal push angle (quadrature) for that
state is computed by taking the base angle for the stator coil and subtracting a timing
angle:
Now, the state needs to compute a range of angles around this quadrature point at which
the relevant stator coil should be active. Knowing that there is a 10 degree separation
Page 60
of 103
between stator coils (and therefore, between states also), the maximum width of this
range of angles is 10 degrees (that is, 5 degrees before and after the quadrature point).
Additionally, at low throttle input the pulse should be narrower but still centered on the
quadrature point. At maximum throttle percent, the pulse should be as wide as possible.
This is accomplished using the following equation to compute the minimum and
maximum angles for the pulse centered on the quadrature point.
Notice the use of floating point to compute the min and max angles. This allows for more
possible pulse widths and finer control over the torque of the motor using the throttle. At
this point, it is simply a matter of determining if the given angle for the rotor is between
the min and max angles just computed. If the rotor angle is between the min and max
angles, CanHandleAngle will return true and the stator manager will enable the pins
associated with this state. Otherwise it will return false and the state will be deactivated
immediately.
The entirety of the code required to implement this above described algorithm has been
included in Appendix 3.
Page 61
of 103
Chapter 4 Data Testing
For validation of the constructed motor controller, data collection of key performance
characteristics were taken to compare the design of Team 9 to the design of DC motors
that are already in the market. The results demonstrate the that the Team 9 alternator with
motor controller design can achieve a satisfactory performance at a much more affordable
cost than a DC motor.
4.1 Revolutions Per Minute
For the electric vehicle application, a
major factor of performance is the speed
that the vehicle is able to achieve. The
speed is correlated to the revolution per
minute of the alternator rotor and varies
with different throttle levels. To measure
the revolutions per minute, a stroboscope
was used. As shown in Figure 41 on
the right, a stroboscope is a device
that that emits a flashing light with a tunable frequency. One fin of the alternator was
marked with white tape and the stroboscope was faced toward the alternator.The
alternator was then driven at a constant throttle level and the dial on the stroboscope was
adjusted until the white tape on the rotor fin appeared to be stationary. This occurred
when the frequency of the strobe flashed matched the frequency of the motor. This test
was done at increasing throttle levels and the results are shown in the figures below. It is
shown that the revolutions per minute of the motor increase linearly with the throttle until
the throttle reaches a level of about 50%. After this point the slope drastically decreases
Page 62
of 103
and the correlation between throttle percentage and revolutions per minute increase
linearly once again. This is because the sensitivity of the throttle varies at different
throttle percentages. It is useful to have more sensitivity at lower throttle levels to help
start the vehicle and less sensitivity at higher speeds so the driver is able to maintain their
chosen speed. Throttle percentage versus RPM is shown below in Figures 42 and 43.
Figure 42: Throttle Percentage vs RPM
Figure 43: Throttle Percentage vs RPM
Page 63
of 103
4.2 Input Power
With any electric vehicle, the input power required to drive the vehicle is a key
parameter. In the case of Team 9, this power is in the form of electrical power. To
calculate electrical power the equation,
P = V rms * I rms , may be used. While it is
simple to use the digital multimeter
supplied in the ECE 480 lab to measure
the input voltage, it was more difficult to
measure the Irms value. The initial thought
to use a series connection to the digital
multimeter supplied in the ECE 480 lab to
measure the input current was not feasible
because the input current is higher than the
rated current of the multimeter. An “Ideal
61772”model multimeter with a current
clamp was then acquired because it is able
to measure the high current and has a true
rms feature that will calculate the rms
value of nonsinusoidal waveforms. This
was an important feature because the
input current is in the form of a square wave and using other meters could cause major
errors in the current calculation.
The bench multimeter was connected to the terminals of the battery, and the “Ideal
61772” multimeter was clamped around the negative terminal wire. The values of each
meter were observed , with no load connected to the alternator, at increasing throttle
levels and are displayed in the figures below. It was observed that the input power
Page 64
of 103
increases until the throttle level reaches around 50% and then drops off. This is because
around this throttle level the code enters a phase where the duty cycle of the rotor is 50%
instead of 100%. While this results in a desirable reduction input power, some torque is
lost at higher speeds as shown in Figures 45 and 46.
Figure 45: Throttle Percentage vs Input Power
Figure 46: Throttle Percentage vs Input Power
Page 65
of 103
4.3 Torque
Torque is an important mechanical parameter of interest in vehicles because it translates
into the amount of force that the vehicle can provide. In industry, this important
parameter is typically measured with a dynamometer and can be done quite easily, but in
a student laboratory setting, Team 9 was not able to access a dynamometer for testing.
Two alternate torque measuring techniques were devised by Team 9.
The first measuring
technique used old bicycle
components and simple
physics to measure the force
provided by the motor. As
shown in the figure on the
right, an apparatus was
constructed in which the
alternator was secured onto a
rotating fixture that was connected
to an arm. A scale was place under the arm and when a load was applied to the energized
alternator, the scale measured the force applied by that arm. Using the equation
T orque = |r||F |sin(theta) the torque was able to be calculated. The variable “r” is the
length of the arm which was measured to be .298m, “F” is the force that the arm exerted
on the scale, and theta was measured to be approximately 90 degrees because the arm is
perpendicular to the scale.
In the lab, the alternator was energized at increasing throttle percentages and a load was
applied to the rotor. This load was large enough to stop the rotation of the rotor, which
Page 66
of 103
causes the rotor to operate very near the maximum torque. At each throttle level, the
available torque was calculated and is displayed in figures 48 and 49 below.
Figure 48: Maximum Torque vs Throttle Percentage
Figure 49: Maximum Torque vs Throttle Percentage
In order to verify the quality of the data obtained using the first torque measuring
technique a second method was devised using only the mass of the rotor itself as the load.
It is possible to determine the average torque over a period of time using the equation
T orque = α ∙ I where alpha is the angular acceleration of the rotor and I is the moment of
inertia of the rotor. The rotor itself was weighed outside of the motor and found to be
2.24 kg. It’s radius was also measured to be .0508 meters. Using the equation for the
moment of inertia of a solid cylinder: I = 12 m ∙ r 2 the moment of the rotor was determined
2
to be 0.003097
kg∙m.
The motor was then reassembled and run from 0 rpm to it’s
maximum speed of 2075 rpm at full throttle. After averaging several stopwatch
Page 67
of 103
measurements it was determined that, at full throttle, the motor was able to accelerate the
rotor from 0 rpm to 2075 rpm in 1.8 seconds. After some unit conversion, this gives an
2
average angular acceleration of 120.7 rad/s. The torque equation listed above can now be
filled in, giving an average torque (at full throttle) over the full rpm range of 0.37 Nm.
This value validates that the values measured using the first method were reasonable and
consistent with basic kinematics.
4.4 Efficiency
Efficiency is one of the most important factors in the design of electric motor controller
systems. The formula used to calculate efficiency is efficiency = P out/P in . Typically
efficiency would be calculated using a dynamometer but the team was able to calculate a
value from data collected using the test fixtures.
The input power from the battery was calculated by multiplying the input current with the
input voltage while the rotor was under an external load. Averaging the values from the
figure above, the average input power under a variety of loads was found to be 128
Watts. The average output power was calculated by multiplying the average output
torque by the average output speed. P = T orque ∙ v In this equation torque is in
v
Newtonmeters and velocity () is in radians per second. The average velocity is exactly
half of the maximum velocity if a linear speed increase is assumed. Given an average
torque of 0.37 Nm and an average velocity of 108.5 radians per second, the average
mechanical output power was 40.14 Watts. This value takes into account all electrical
and mechanical losses including friction and heat losses. Given these values for input
40W
and output power, the efficiency of the design was found to be 128W × 100% = 31% .
Page 68
of 103
4.5 Scope Measurements
4.5.1 Common MOSFET Gate Pulses
The following diagrams show the pulses that are applied to the gates of the MOSFETs.
The pchannel mosfets are driven with a negative pulse below the supply voltage while
the nchannel mosfets are driven by a positive pulse above ground. In the following two
diagrams, the three negative pulses on the pchannel mosfet and the three positive pulses
on the nchannel are interleaved like the teeth on a set of gears. When the pchannel
pulses are idle, the nchannel mosfet is being pulsed and vice versa. When the throttle
percent is lessened, the distance between consecutive pulses is increased creating more
idle time for the stator coils and reducing torque output. The following diagrams in figure
50 and 51 show the operation of the mosfet gates at maximum throttle which is also the
point of maximum stress on the circuitry.
Figure 50: PChannel Common Gate Pulses at 100% Throttle
Page 69
of 103
Figure 51: NChannel Common Gate Pulses at 100% Throttle
Page 70
of 103
4.5.2 Rotor Gate Pulses
Any time that a stator coil is active, the rotor coil is also activated in order to produce
torque. The following diagram in Figure 52 shows the pulses given to the gate of the
nchannel rotor mosfet at 100% throttle. It is important to note that, although the rotor is
activated often (every time a stator coil is on), the total area underneath the curve is
significantly less than it would be if the rotor were activated permanently. This is due to
the modulation of the stator coil at high RPMs. This modulation weakens the rotor field
and allows for increased speed and efficiency.
Figure 52: Rotor Gate Pulses at 100% Throttle
Page 71
of 103
4.6 Design Specification Achievements
The chart below documents the success of Team 9 in achieving the project goals:
Page 72
of 103
Chapter 5 Design Issues
As this project is sponsored by and partnered with MSU RCPD, accessible design is
extremely important in the production of an EBike Motor and Controller. Since the
Team 9 design is very versatile in the number of applications it could be applied to, there
are numerous ways accessibility could be improved in the prototype. For example, for
someone with extremely limited physical dexterity, it may be difficult to accurately
control the throttle input. To make the design easier to use, a joystick modification could
be implemented which would allow for the user to control the entire vehicle with a single
hand. This modification could also allow for the vehicle to be designed at a much smaller
size similar to that of a wheelchair.
Another modification that could be made to the design is the use of hand pedals which
could provide assistance to the motor in propelling a vehicle. Accompanied with
appropriate circuitry, these hand pedals would also be able to charge the vehicle’s
battery. This addition would allow for people with limited lower body functionality to use
the vehicle effectively.
Environmental issues must also come into consideration when designing any type of
vehicle, especially when dealing with electronics. Since the vehicle is projected for use in
a rugged environment, water and humidity resistance is critical. To prepare the product
for production on a large scale, some type of waterproof casing or waterproofing spray
must be applied to the motor controlling circuit to ensure a long lifetime. Similarly,
environmental heat will also cause many problems if not addressed. To ensure the motor
circuit components do not overheat and malfunction, good heat sinks and potentially
some sort of active cooling should be applied to the controlling circuit.
Page 73
of 103
With any design that is mass produced for the public, it is important to take into
consideration the safety issues that can arise with use of the design. Electric vehicles
come with inherent risk, but with careful design these risks can be reduced. These risks
include the use of a chemical battery, such as one found in in an automobile and used in
this design and the use of high current electronics. Motor controllers are the driving force
of these vehicles and added features to this component can help solve many safety issues.
Quick acceleration at the startup could cause an unexpected jostle to the rider. This may
cause the rider to experience whiplash, develop contusions, or lose control of the vehicle.
A key feature of the Team 9 design is that this can all be prevented with added code to
the microcontroller. The code could have an algorithm that does not allow the throttle
input to be a large value during the startup phase of the code. This would help an
unknowing rider who started the vehicle at full throttle avoid quick acceleration.
The various terrain and conditions that the vehicle will be exposed to may cause
unforeseeable adverse effects to the circuit. Increased loads may cause the circuit to draw
large amounts of current. Large amounts of current may cause the circuit to overheat and
even become damaged beyond repair. This could cause the rider to lose control of the
vehicle. While the current circuit has many protection devices installed such as breakers,
rectification diodes, and reinforced traces; a “smart” overcurrent protection device could
be used to further protect the circuit. This device could take the place of the breaker and
allow for short spikes of high current while suppressing sustained overcurrent conditions.
This allows for the circuit to continue to run if spikes of current occur that are not
threatening to the circuit.
Sustained usage of the vehicle in hot conditions could cause parts of the design to
become very hot. This could not only cause burns to the rider, but also may damage
components on the circuitboard. To combat this problem heatsinks are installed on
Page 74
of 103
components that are at risk of overheating. While these heatsinks do a great job of
keeping these components cool at normal operating conditions, there are some
circumstances that could still cause these components to overheat. To prevent this
occurrence, temperature sensors could be installed that signal to the microcontroller that
the circuit is getting too hot and provide a warning to the rider and potentially
automatically shut down the circuit.
Chapter 6 Final Cost, Summary, and Conclusions
Over the course of this project, multiple steps were taken to complete the task of
modifying an automotive alternator for use as a DC motor. The alternator itself was
modified from its original design to improve efficiency. A complex power switching
circuit was designed to allow the exterior stator coils and the rotor field coils to be pulsed
in a novel way, at optimal quadrature angles. A microcontroller was used to drive the
hardware circuits such that they would effectively operate the alternator as a motor. A
magnetic rotary position sensor was used to provide the microcontroller with the data
needed to perform the calculations for pulsing the stator and rotor. This design proved to
be a unique alternative to a DC motor and a cost effective way of powering a small
electric vehicle.
The project had both successes and challenges. The design of the circuit proved
troublesome. Although eventually a success, the circuit is complex, and a great deal was
learned regarding the intricacies of switching mosfets at high frequencies. The early
phases of the design worked by simulating the switching of one phase of the MOSFET
circuit. This design would ultimately be integrated into the final design. After the initial
design was complete, the next phase of designing the PCB proved problematic. The
complexity of the circuit proved to be difficult in the process of providing an effective
Page 75
of 103
design that allowed for high voltages and currents to the MOSFETs. The software is also
complex, which provided its own set of problems. The building of the software went
slowly, for each new success, new complications arose. When it was believed that the
software and circuit were complete, integration was the next phase. This also proved to
be problematic. Initially, the software was changed frequently to solve problems such as
a stuttering effect that the motor kept exhibiting. The software was refined, and the motor
appeared to be working. The next phase of testing showed that the bipolar junction
transistors were not switching fast enough to be able to handle the high frequency of the
pulses. This caused a multitude of issues including overheating and malfunctioning
MOSFETs. The culmination of all of the hardware issues up to this point were resolved
through minor alterations to gate driving circuitry. Ultimately, the problems were
resolved, and the design was finalized.
The project was able to stay near the original timeline. Some of the intended stages of the
critical path were naturally condensed from the original timeline as the circuit design
required only minor tweaks, not a complete redesign. This allowed for more testing of the
design and better characterization of the performance of the motor.
The final cost for prototype development of the design was $332.54. This cost included
all materials that were used in the prototyping phase. This cost was well under the budget
for the project. The final cost of a single production unit was $99.01. This value
represents a success to the team, because one of the major objectives of the project was
an inexpensive design. This final cost could be reduced by buying the components in
bulk from wholesalers. This cost is not representative of the cost in the nation in which
the final design will be manufactured. The cost of manufacturing will likely be reduced
as parts such as the alternator are available in India locally for much less than in the
United States.
Page 76
of 103
At the beginning of the project, it was assumed that costs could be reduced by using
inexpensive discrete components (junction transistors, resistors, diodes, etc.) to drive the
gates of the MOSFETs. While the design has successfully accomplished this, the effort
has required the addition of a large number of these devices to improve performance.
Considering the actual component costs, PCB space, and cabinet costs required to
accommodate this, it is now obvious that MOSFET gate driver circuits are easier to use,
less costly to manufacture, and provide higher performance. TI makes a driver,
UCC27714 for example, that can outperform the circuit at a cost of $2 each in quantity.
This driver also saves cost because it can drive nchannel MOSFETs on the high side of
the supply, thereby eliminating the need to use expensive pchannel MOSFETs and
additional avalanche rectifiers.
Additional cost saving could be obtained by soldering the 10 AWG wire to the printed
circuit board to replace the expensive terminal blocks as well as using a fuse and switch
to replace the circuit breaker. The original design was constructed with parts that are
rated well beyond their use in the circuit. This allowed for a more robust design and
eliminated the chance of hardware failure while testing different codes or conditions.
The Team 9 design proved that it is in fact entirely feasible to convert a standard
alternator into a motor. Through the study of the components used in the design, along
with the data gathered, a conclusion can be drawn that the automotive alternator can and
will be used in the future as a motor. Measuring the optimal angles and using that data as
a way to improve the efficiency of an alternator to motor conversion is very unique. This
uniqueness should provide others with an area to study for future improvements. Team 9
is happy to have contributed its implementation of a very promising design and to have
delivered a complete working prototype. Team 9 has assigned its intellectual property
rights to RCPD and sincerely hopes that the technical and societal benefits of the EBike
will be fully realized.
Page 77
of 103
Appendix 1 Technical Roles, Responsibilities, and
Work Accomplished
The picture above from left to right: (Myles Moore Document Prep, Tyler Borysiak
Project Manager, Alex Sklar Lab Coordinator, Joshua Lamb Presentation Prep,
Stephen Dunn Web Developer)
Myles Moore
The design team we established was partially split into two subgroups, hardware and
software. This was to increase the efficiency of the team so that two parts of the project
could be developed simultaneously. As an electrical engineer, I was part of the hardware
subgroup which was mainly focused on learning how the different alternator parts
worked, developing a MOSFET switching circuit, and developing an efficient PCB
layout for the final design. The first step taken during the semester was to determine how
to make the alternator spin. To do this, I helped manually attached a 12V car battery to
each phase of the stator coils to make the alternator act similar to a stepper motor. Once
we figured out the sequence of the stator coils to make the alternator complete a full
Page 78
of 103
rotation we could begin to design the highvoltage MOSFET switching circuit. The first
step in this process was to verify the turnon voltage of the MOSFETs and determine how
to safely use them. To experiment with the MOSFETs, I helped create a proofofconcept
switching circuit with LEDs acting as the stator coils for safety purposes. Once this
circuit was working as intended, we began to integrate all the circuit elements we were
going to use as footprints in Eagle’s PCB designer. When all the footprints were created,
we then connected all the elements in the circuit schematic and imported the schematic
into the PCB designer layout. At this part we were able to brainstorm a space efficient
way to layout the different circuit elements and began to construct the traces. Once the
entire layout was completed and printed in the ECE shop, we began soldering the
different elements to the board. Since the MOSFETs would be handing a lot of current
we added heat sinks to dissipate the power lost to heat. At this point we were able to
integrate the hardware and software subgroups to construct our prototype. The final
steps in this project before design day are to optimize our software algorithm to make the
motor run the most efficiently, as well as prepare the prototype for demonstration.
Tyler Borysiak
Along with the project management role, I was also continuously involved with the
technical portion of the project as the hardware design lead. Throughout the semester, I
set up hardware meetings in order to discuss technical specifications and design issues.
On the hardware side, I designed the MOSFET stator switching schematic along with the
rotor circuit and the peripheral connections to the microcontroller on the EAGLE
schematic software. After designing the schematic, I organized the components on the
board file and correctly routed the PCB traces and vias. After the fabrication of the board,
I was involved in the component soldering and also in the connection of the software and
hardware. After connecting the hardware and running tests, I was in charge of
troubleshooting the hardware in order to find simple adjustments that needed to be made.
I also have been suggesting new design alterations such as slight adjustments to the stator
Page 79
of 103
quadrature angle based on alternator performance during testing. I was also actively
involved with the stator and rotor pulsing theory. The original plan was to read the angle
of the rotor using the AMS sensor and pulse the stator coils every time that this was read.
A more effective and efficient solution was to pulse the stator states less frequent at
higher RPMs, allowing for less power consumption and wider ranges of speed. From a
rotor theory standpoint, I have been involved in maximizing the field current efficiency
by figuring out ways to only apply field current to the rotor when necessary. For
example, we have found it more practical to constantly magnetize the rotor at start
up for
a short amount of time, and then gradually reduce the rotor field supply pulses. Towards
the end of the design process, I also was actively involved in finding a solution to the two
major hardware issues, which were the pchannel MOSFET not activating properly and
the noise issue from the voltage source.
Alex Sklar
To achieve the proposed design there were two main components of the motor controller,
the hardware/power electronics, and the microcontroller/software. I elected to focus most
of my time on the hardware/power electronics because I have more knowledge on about
hardware and less experience and knowledge of microcontrollers than the computer
engineers in our team.
As a team we selected the properly rated mosfets for our project that had the proper
switching capabilities and current ratings for our project. Once we had the parts, I created
an HBridge circuit with the mosfets that allowed for each coil of our alternator to be
energized individually and in each polarity. This circuit also has diodes that are used for
regenerative braking. I was able to test this circuit by connecting it to LEDs to signify
each coil and separate polarities. I then worked with our sponsor and team to interface
BJT transistors to drive the gate of the mosfets. This allowed the 3.3V output of the
microcontroller to drive the gate of the mosfets.
Page 80
of 103
After the HBridge circuit was working I designed a similar circuit to control the rotor of
the alternator. This used just one N channel mosfet and allowed the rotor coil to be
connected to either 12V or just an open circuit.
Because our circuit can draw large amounts of current it was difficult to test our design
using a breadboard. This required the design of a printed circuit board. Tyler and I
designed a printed circuit board in Eagle that contained very thick traces connected to the
mosfets. This allowed for the circuit to draw high currents without the board melting.
These abnormally thick traces required us to manually route the traces on the board
instead of using the popular “autoroute” feature.
During the design of the PCB I was also in charge of ordering parts for the final board.
Because many of these parts are not in the included library of Eagle it was necessary to
model many of these parts to be used in our PCB.
Once our PCB was fabricated I was able to work on the soldering portion of our project. I
then worked with my team to troubleshoot all of the problems with our board and finalize
our hardware circuit and got it ready to be used to optimize the code on the
microcontroller. I then worked on securing testing equipment and coordinated with the
team to test each code and come up with solutions to each problem that degraded our
efficiency and perfect the “startup” and “high speed” phases of our code.
Joshua Lamb
My defined part of the project was to serve as one of two Software Specialists. The
software specialists were responsible for implementing the motor control algorithm
which effectively interfaced with the AMS sensor, throttle sensor, and the power
MOSFET switching circuits. I was a part of researching the steps needed to enable the
Page 81
of 103
functionality on the microcontroller. I assisted in the communication of the AMS sensor
with the microcontroller. I made decisions regarding the design of the interface between
the microcontroller and the circuit. As one of the software specialists, I became an expert
in the specifications and use of the sensor and microcontroller used in the project. I used
computer language standards, electrical standards, schematic standards and many more
over the course to communicate with the team. I was involved in creating a list of
specifications the microcontroller needed to satisfy as well as researching and choosing a
microcontroller to be used for the project. I researched and helped choose the magnetic
rotary sensor used in the project based on a list of requirements we created. I helped
create a list of requirements that would need to be satisfied for the PCB board that would
need to be created. I was involved in the building and testing of the alternator initial
design. I recognized potential issues that would need to be addressed in the final design. I
was involved in the initial framework of the software design as well as the research into
the documentation of the microcontroller to enable the needed features. I was then
involved in the process of building the software. This process involved multiple steps to
build the scaffolding of the design. I was involved in a great deal of the testing of each
design iteration, from software to hardware. I was involved in the building of the final
circuit. My role within the project stayed specialized but became more robust.
Stephen Dunn
For this project I served as both the software specialist webmaster and as a webmaster. I
began design work on the project by helping to select a microcontroller and rotary
position sensor. Part of the motivation for selecting the Texas Instruments
microcontroller was the familiarity that myself and Josh had with the platform. Once the
microcontroller and rotary position sensor were selected I began the process of
prototyping a development environment that would allow Josh and I to work on the code
collaboratively. This involved setting up a source control repository on the CSE servers
here at MSU. Once the source control environment was setup, I created a code composer
Page 82
of 103
studio project specifically designed to work with our development board. This included
selecting the appropriate header files and libraries and setting up the memory map on the
microcontroller. All of these tasks were needed in order to make rapid development on
the microcontroller possible. Next, I began work prototyping the circuitry needed to
connect to the rotary position sensor, throttle and LCD to the microcontroller. With these
circuits setup on a protoboard, I began writing the code to communicate with these
devices. Around this same time in the design process, Josh and I disassembled the
alternator, rewired it from a delta configuration to a wye configuration, and
experimentally discovered the sequence of stator pulses needed to drive the rotor. I was
also responsible for writing the logic needed to drive the stator coils at the appropriate
angles. When it came time to assemble the circuit I was one of the primary solderers and
took an active role in helping to debug the circuit when trouble was encountered. Finally,
I proposed and executed one of the testing methods used to measure the average torque of
the rotor using basic kinematic physics concepts. I was very excited about this project
from the beginning and decided to take an active role in as much of the project as
possible even outside my software speciality. As webmaster, it was as much a pleasure as
responsibility to make our course deliverables accessible to the team and to the public.
Page 83
of 103
Appendix 2 References
AMS AS5132 Rotary Sensor Data Sheet:
http://ams.com/eng/content/download/254823/1001597/147615
TivaWare Peripheral Driver Library:
http://www.ti.com/lit/ug/spmu298a/spmu298a.pdf
Tiva TM4C123GH6PMI Microcontroller Data Sheet:
http://www.ti.com/lit/ds/symlink/tm4c123gh6pm.pdf
Hall Effect Sensor:
http://www.edn.com/design/sensors/4406682/BrushlessDCMotorsPartIConstructio
nandOperatingPrinciples
Hyperfast Recovery Diode Datasheet:
http://www.mouser.com/ds/2/149/FFH75H60S244361.pdf
PChannel MOSFET Datasheet:
http://www.mouser.com/ds/2/205/DS100024B%28IXTATHTP76P10T%29312838.pdf
NChannel MOSFET Datasheet:
http://www.mouser.com/ds/2/196/IPP045N10N3%20G_Rev2.596667.pdf
Automotive Alternator Schematic Illustration:
http://www.alternativeenergytutorials.com/windenergy/pmdcgenerator.html
Delta vs Wye:
https://en.wikipedia.org/wiki/Deltawye_transformer
Automotive Alternator Diagram:
http://www.examiner.com/article/introductiontoalternatorspartthreealternatorcompo
nents
MOSFET Diagram:
http://www.eeweb.com/companyblog/ixys/pchannelpowermosfetsandapplications
Page 84
of 103
Appendix 3 Software Reference Code
/*
* main.cpp
*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/ssi.h"
#include "driverlib/systick.h"
#include "GeneralUtil.h"
#include "LiquidCrystal.h"
#include "AS5132Sensor.h"
#include "RotorManager.h"
#include "Timer.h"
#include "StatorManager.h"
#include "ThrottleManager.h"
LiquidCrystal* lcd;
RotorManager* rotor;
ThrottleManager* throttle;
StatorManager* stator;
void setup(void) {
// max clock speed.
GeneralUtil::SystemClock80MHz();
// enable GPIO modules
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
// small delay required to let the peripheral devices turn on.
GeneralUtil::DelayMicro(10);
// write a pin to indicate setup time
GeneralUtil::PinMode(GPIO_PORTB_BASE, GPIO_PIN_0, OUTPUT);
ROM_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0xFF);
// LCD talks on port B
// set up the LCD's number of columns and rows:
lcd = new LiquidCrystal(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6,
GPIO_PIN_7);
lcd>begin(20, 4);
// throttle ADC is on port E
throttle = new ThrottleManager(GPIO_PORTE_BASE, GPIO_PIN_3);
Page 85
of 103
// rotor talks on port A
rotor = new RotorManager(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_2, GPIO_PIN_4,
GPIO_PORTA_BASE, GPIO_PIN_7, throttle);
// stator talks on ports C and F
stator = new StatorManager(
rotor, throttle,
GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7,
GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4);
// write a pin to indicate setup time
ROM_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0x00);
}
int main(void) {
setup();
// toto: if needs calibration, calibrate!
// else, continue with normal operation
while(1){
/*
* Basic algorithm
*/
throttle>Update();
rotor>Update();
stator>Update();
/*
* Debug Printing. VERY SLOW! Disable for actual operation!
*/
// if(calcIterations > 5000) {
// lcd>setCursor(0, 0);
// lcd>print('[');
// lcd>print(rotor>GetAngle());
// lcd>print(']');
// calcIterations = 0;
// }
/**/
}
return 0;
}
/*
* AS5132Sensor.cpp
*
* Created on: Oct 20, 2015
* Author: Stephen Dunn, Josh Lamb
*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
Page 86
of 103
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "GeneralUtil.h"
#include "AS5132Sensor.h"
AS5132Sensor::AS5132Sensor(uint32_t port, uint8_t pinCS, uint8_t pinCLK, uint8_t pinDIO) {
mPort = port;
mPinCS = pinCS;
mPinCLK = pinCLK;
mPinDIO = pinDIO;
// set pin directions
ROM_GPIOPinTypeGPIOOutput(mPort, mPinCS);
ROM_GPIOPinTypeGPIOOutput(mPort, mPinCLK);
ROM_GPIOPinTypeGPIOInput(mPort, mPinDIO);
// ChipSelect>high means no transmission
ROM_GPIOPinWrite(mPort, mPinCS, ALL_HIGH);
ROM_GPIOPinWrite(mPort, mPinCLK, ALL_LOW);
mAngle = 0;
mSensorGain = 0;
}
void AS5132Sensor::TakeReadings() {
// read the raw bit data into a structure
ReadAngleResponse raw;
raw.value = Command(AMS_RD_ANGLE);
// grab the values from the bitfield
mAngle = raw.fields.AngleReading;
mSensorGain = raw.fields.SensorGain;
mLockADC = raw.fields.LockADC;
}
uint16_t AS5132Sensor::Command(uint8_t command) {
uint16_t tmp = 0;
uint16_t data = 0;
// pull chip select low to start the transmission
ROM_GPIOPinWrite(mPort, mPinCS, ALL_LOW);
// the first 7 of the 8 command bits
ROM_GPIOPinTypeGPIOOutput(mPort, mPinDIO); // set DIO pin to an output.
for(int i = 0; i < 7; i++) {
// write data bit, MSB first
ROM_GPIOPinWrite(mPort, mPinDIO, (command & 0x80) >> 7);
command = (command << 1);
// pulse the clock to latch the bit in the AS5132
ROM_GPIOPinWrite(mPort, mPinCLK, ALL_HIGH);
ROM_GPIOPinWrite(mPort, mPinCLK, ALL_LOW);
}
// The last data bit is handled differently in read mode because the DIO
// pin needs to change from an output to an input.
// write last data bit
Page 87
of 103
ROM_GPIOPinWrite(mPort, mPinDIO, (command & 0x80) >> 7);
command = (command << 1);
// clock it in on the rising edge
ROM_GPIOPinWrite(mPort, mPinCLK, ALL_HIGH);
// before the falling edge of the clock, change the pin mode
ROM_GPIOPinTypeGPIOInput(mPort, mPinDIO);
// now let the clock fall.
// the AS5132 will immediately begin outputing data on the DIO line
ROM_GPIOPinWrite(mPort, mPinCLK, ALL_LOW);
// 16 data bits
for(int i = 0; i < 16; i++) {
// read data bit (MSB first)
tmp = ROM_GPIOPinRead(mPort, mPinDIO);
tmp = tmp >> 4; // get the bit in the ones position
data = data | (tmp << (15 i)); // shift it into the result
// clock in the next bit.
ROM_GPIOPinWrite(mPort, mPinCLK, ALL_HIGH);
ROM_GPIOPinWrite(mPort, mPinCLK, ALL_LOW);
}
// finish the transmission by pulling the chip select pin high
ROM_GPIOPinWrite(mPort, mPinCS, ALL_HIGH);
return data;
}
/*
* AS5132Sensor.h
*
* Created on: Oct 20, 2015
* Author: Stephen Dunn, Josh Lamb
*/
#ifndef AS5132SENSOR_H_
#define AS5132SENSOR_H_
#define AMS_RD_ANGLE 0x00 // read angle command bits
#define AMS_RD_MT_COUNTER 0x04 // read multiturn counter command bits
// bitfield for raw reading
struct ReadAngleStruct {
uint8_t Parity : 1;
uint8_t SensorGain : 5;
uint8_t LockADC : 1;
uint16_t AngleReading : 9;
};
// a union to allow setting all the bits at once
union ReadAngleResponse {
struct ReadAngleStruct fields;
uint32_t value;
};
// the class that represents the AMS sensor
class AS5132Sensor {
public:
Page 88
of 103
// constructor
AS5132Sensor(uint32_t port, uint8_t pinCS, uint8_t pinCLK, uint8_t pinDIO);
// causes the class to take a fresh set of readings from the sensor
void TakeReadings();
// various possible fault modes of the sensor itself can be queried
// with these three methods here:
// field strength is too low to detect
bool GetIsFieldStrengthFault() { return mSensorGain > 60; }
// sensor internal ADC was locked when angle was read
bool GetLockADC() { return !mLockADC; }
// somehow the angle is out of bounds
bool GetIsRangeFault() { return mAngle > 359; }
uint32_t GetAngle() { return mAngle; }
uint32_t GetFieldStrength() { return mSensorGain; }
private:
// the angle last reported by the sensor
uint32_t mAngle;
// the gain last reported by the sensor
uint32_t mSensorGain;
// during the last reading, was the internal ADC locked?
bool mLockADC;
// raw data from the sensor
uint16_t mRaw;
// GPIO ports and pins for communication
uint32_t mPort;
uint8_t mPinCS;
uint8_t mPinCLK;
uint8_t mPinDIO;
// sends the given command bits and returns the result from the sensor
uint16_t Command(uint8_t command);
};
#endif /* AS5132SENSOR_H_ */
/*
* GeneralUtil.cpp
*
* Created on: Oct 6, 2015
* Author: Stephen Dunn, Josh Lamb
*/
#include "GeneralUtil.h"
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
Page 89
of 103
#include "driverlib/sysctl.h"
uint32_t GeneralUtil::mSysClock = 0;
uint32_t GeneralUtil::GetSysClock() {
return mSysClock;
}
void GeneralUtil::SystemClock80MHz() {
// Run from the PLL at 80 MHz.
ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
SYSCTL_OSC_MAIN);
mSysClock = ROM_SysCtlClockGet();
}
void GeneralUtil::DelayMicro(uint32_t us) {
// assumed 80MHz clock
ROM_SysCtlDelay((float)us * 26.67);
// real calculation
// ROM_SysCtlDelay(us * ((float)mSysClock / (float)3 / (float)1000000));
}
// used to port the liquid crystal library
void GeneralUtil::DigitalWrite(uint32_t portbase, uint8_t pinmask, uint8_t value) {
ROM_GPIOPinWrite(portbase, pinmask, value);
}
// used to port the liquid crystal library
void GeneralUtil::PinMode(uint32_t portbase, uint8_t pinmask, uint8_t value) {
if(value == OUTPUT) {
ROM_GPIOPinTypeGPIOOutput(portbase, pinmask);
} else {
ROM_GPIOPinTypeGPIOInput(portbase, pinmask);
}
}
/*
* GeneralUtil.h
*
* Created on: Oct 6, 2015
* Author: Stephen Dunn, Josh Lamb
*/
#ifndef GENERALUTIL_H_
#define GENERALUTIL_H_
#include <stdint.h>
#include <stdbool.h>
#include "driverlib/gpio.h"
#define HIGH 0x01 // first bit high
#define ALL_HIGH 0xFF // all bits high
#define LOW 0x00 // first bit low
#define ALL_LOW 0x00 // all bits low
#define INPUT GPIO_DIR_MODE_IN // naming shortcut
#define ALL_INPUT 0x00 // naming shortcut
#define OUTPUT GPIO_DIR_MODE_OUT// naming shortcut
#define ALL_OUTPUT 0xFF // naming shortcut
#include <stdint.h>
Page 90
of 103
#include <stdbool.h>
class GeneralUtil {
private:
// System clock rate in Hz.
static uint32_t mSysClock;
public:
static uint32_t GetSysClock();
static void SystemClock80MHz();
// looses accuracy below ~10us
static void DelayMicro(uint32_t us);
static void DigitalWrite(uint32_t portbase, uint8_t pinmask, uint8_t value);
static void PinMode(uint32_t portbase, uint8_t pinmask, uint8_t value);
};
#endif /* GENERALUTIL_H_ */
/*
* RotorManager.cpp
*
* Created on: Oct 27, 2015
* Author: Stephen Dunn, Josh Lamb
*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/pwm.h"
#include "GeneralUtil.h"
#include "AS5132Sensor.h"
#include "RotorManager.h"
#include "Timer.h"
RotorManager::RotorManager(uint32_t port, uint8_t pinCS, uint8_t pinCLK, uint8_t pinDIO, uint32_t coilPort, uint8_t coilPin,
ThrottleManager* throttle) {
// initialize the sensor object and throttle dependency
mAms = new AS5132Sensor(port, pinCS, pinCLK, pinDIO);
mThrottle = throttle;
// store port and pin information for later
mCoilPort = coilPort;
mCoilPin = coilPin;
// assume the coil is off to start
mCoilEnabled = false;
// configure the coil pin and actually turn the coil off.
GeneralUtil::PinMode(mCoilPort, mCoilPin, OUTPUT);
DeactivateCoil();
Page 91
of 103
// initial values
mMicrosSinceMeasurement = 0;
mMeasuredAngle = 0;
mMeasuredVel = 0;
mAngle = 0;
mVel = 0;
mIsFirstReading = true;
mIgnoreCount = 0;
}
RotorManager::~RotorManager() {
delete mAms;
}
void RotorManager::Update() {
// the first reading is handled slightly differently because there
// is no previous reading to compare with.
if(mIsFirstReading) {
Timer::ResetAndStart(); // start the timer for next time
mAms>TakeReadings(); // grab some angle readings
// multiply by 1000 to bring the values into a better range for computation
mMeasuredAngle = mAngle = mAms>GetAngle() * 1000;
mIsFirstReading = false;
return;
}
uint32_t microsSinceUpdate = Timer::GetElapsedMicro(); // first note the timestamp of the readings
Timer::ResetAndStart(); // start the
timer again for next time
mAms>TakeReadings();
// grab some angle readings
mMicrosSinceMeasurement += microsSinceUpdate; // keeping track of time between good
measurements
int32_t newAngle = mAms>GetAngle() * 1000; // again, brings the values into a better range
for computation.
int32_t oldAngle = mMeasuredAngle;
// only take a real reading if there are no error conditions from the sensor,
// and the angle reading is different from last time.
if((mAms>GetIsRangeFault() || mAms>GetLockADC() || newAngle == oldAngle) && mIgnoreCount < 100) {
// the ams did not read a new angle, or some other error occored.
// ignore the reading and estimate the next angle based on the known speed of the rotor.
//mAngle += mVel * microsSinceUpdate;
mIgnoreCount++;
} else {
// the ams read a new angle, or there have been more than 10 identical readings in a row.
// store the new angle
mMeasuredAngle = mAngle = newAngle;
// properly handle the transition from zero to 359 or from 359 to zero.
int32_t delta = (newAngle oldAngle);
if(delta < 180) {
oldAngle = oldAngle 360;
delta = newAngle oldAngle;
} else if(delta > 180) {
newAngle = newAngle 360;
delta = newAngle oldAngle;
}
Page 92
of 103
// calculate measured velocity
mMeasuredVel = mVel = (float)delta / (float)mMicrosSinceMeasurement;
// reset some variables
mMicrosSinceMeasurement = 0;
mIgnoreCount = 0;
}
// idle state
if(IsIdle() && mThrottle>GetPercent() == 0) {
DeactivateCoil();
return;
}
}
void RotorManager::ActivateCoil(bool modulate) {
// this logic allows the rotor to actually turn on only everother time it is told to
// if "modulate" is set to true. This reduces the field strength in the rotor
// allowing for higher speeds with less back emf.
if(modulate) {
if(!mCoilEnabled) {
ROM_GPIOPinWrite(mCoilPort, mCoilPin, 0xFF);
mCoilEnabled = true;
} else {
DeactivateCoil();
}
} else {
ROM_GPIOPinWrite(mCoilPort, mCoilPin, 0xFF);
mCoilEnabled = true;
}
}
void RotorManager::DeactivateCoil() {
ROM_GPIOPinWrite(mCoilPort, mCoilPin, 0x00);
mCoilEnabled = false;
}
/*
* RotorManager.h
*
* Created on: Oct 27, 2015
* Author: Stephen Dunn, Josh Lamb
*/
#ifndef ROTORMANAGER_H_
#define ROTORMANAGER_H_
#include <math.h>
#include "ThrottleManager.h"
#include "AS5132Sensor.h"
/*
* The rotor manager class manages the rotor of the motor. It is able to report the angle and speed of the rotor
* using information from the rotary position sensor. This class is tolerant to bad readings from the sensor
* and will estimate the position of the rotor using previously obtained data. This class is also used to turn the
* coils within the rotor on and off.
*/
class RotorManager {
public:
Page 93
of 103
RotorManager(uint32_t port, uint8_t pinCS, uint8_t pinCLK, uint8_t pinDIO, uint32_t coilPort, uint8_t coilPin,
ThrottleManager* throttle);
virtual ~RotorManager();
// turn on the rotor coil
void ActivateCoil(bool modulate);
// turn off the rotor coil
void DeactivateCoil();
// update the position information of the rotor coil.
void Update();
// in degrees
float GetAngle() { return mAngle / 1000.0; }
// degrees per second
float GetVel() { return mVel * 1000.0; }
bool IsIdle() { return fabs(GetVel()) < 100.0; }
private:
// sensor object
AS5132Sensor* mAms;
// microseconds since a realdata measurement
uint32_t mMicrosSinceMeasurement;
// private measurements. Always equal to the last real measurement.
int32_t mMeasuredAngle;
float mMeasuredVel;
// the "public" values. Can be actual or estimated values depending on the situation.
float mAngle; // thousandths degrees
float mVel; // thousand degrees per microsecond
// special handling for the first update.
bool mIsFirstReading;
// remembers if the coil is currently on or off
bool mCoilEnabled;
// if too many readings are ignored in a row due to the data being duplicated,
// go ahead and take a new reading anyway.
uint8_t mIgnoreCount;
// port and pins for controlling the rotor coil
uint32_t mCoilPort;
uint8_t mCoilPin;
ThrottleManager* mThrottle;
};
#endif /* ROTORMANAGER_H_ */
/*
* State.cpp
*
* Created on: Nov 5, 2015
* Author: Stephen
*/
Page 94
of 103
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "State.h"
#include "GeneralUtil.h"
State::State(PinAssignments* pins, int32_t baseAngle, int32_t timing) {
// store off the pin assignments
mPins = pins;
// configure the pins for output
GeneralUtil::PinMode(mPins>OnPortP, mPins>OnPinP, OUTPUT);
GeneralUtil::PinMode(mPins>OnPortN, mPins>OnPinN, OUTPUT);
// but turn them off to start
Deactivate();
// the optimal quadrature angle at which to push the rotor is calculated given
// the base angle of the stator coil minus (that is, counterclockwise) the timing
// angle. This greates a quadrature point around which to pulse the stator.
mOptimalAngle = baseAngle timing; // for clockwise operation, make this a plus instead.
// make sure the angles play nice with the 0>360 border
if(mOptimalAngle > 359) mOptimalAngle = 360;
if(mOptimalAngle < 0) mOptimalAngle += 360;
}
bool State::CanHandleAngle(uint32_t rotorAngle, uint32_t throttlePercent) {
// short circuit to speed up logic if the throttle is off
if(throttlePercent == 0)
return false;
// this will be the number of degrees before and after the quadrature point
// to start and stop the rotor pulse
float angleDelta = (HALF_STATE_SEP_DEGREES * (float)throttlePercent) / 100.0;
// min and max angles
float minAngle = mOptimalAngle angleDelta;
float maxAngle = mOptimalAngle + angleDelta;
// make them play nice with the 0>360 border
if(minAngle < 0) minAngle += 360.0;
if(minAngle > 359) minAngle = 360.0;
if(maxAngle < 0) maxAngle += 360.0;
if(maxAngle > 359) maxAngle = 360.0;
// range does not overlap the 0 degrees mark.
// traditional min/max apply here
if(minAngle < maxAngle) {
if(rotorAngle >= minAngle && rotorAngle < maxAngle)
return true; // rotor angle is within the quadrature pulse angle range.
else
return false; // rotor angle is outside the quadrature pulse angle range.
} else {
// range overlaps the 0 degrees mark.
Page 95
of 103
// use different concept of min/max here
if((rotorAngle >= 0 && rotorAngle < maxAngle) || (rotorAngle <= 359 && rotorAngle >= minAngle))
return true; // rotor angle is within the quadrature pulse angle range.
else
return false; // rotor angle is outside the quadrature pulse angle range.
}
}
bool State::Activate() {
// set the pins on.
ROM_GPIOPinWrite(mPins>OnPortP, mPins>OnPinP, ALL_HIGH);
ROM_GPIOPinWrite(mPins>OnPortN, mPins>OnPinN, ALL_HIGH);
}
void State::Deactivate() {
// turn the pins off
ROM_GPIOPinWrite(mPins>OnPortP, mPins>OnPinP, 0);
ROM_GPIOPinWrite(mPins>OnPortN, mPins>OnPinN, 0);
}
/*
* State.h
*
* Created on: Nov 5, 2015
* Author: Stephen
*/
#ifndef STATE_H_
#define STATE_H_
#include <stdint.h>
#define STATE_SEP_DEGREES 10.0 // the seperation in degrees between stator coils
#define HALF_STATE_SEP_DEGREES 5.0 // half that value...
/*
* A structure to associate 2 pins with eachother, one controlling a PChannel MOSFET
* and another controlling an NChannel MOSFET
*/
struct PinAssignments {
PinAssignments(uint32_t onPortP, uint8_t onPinP, uint32_t onPortN, uint8_t onPinN) {
OnPortP = onPortP;
OnPinP = onPinP;
OnPortN = onPortN;
OnPinN = onPinN;
}
// for the PChannel mosfets (highside switches)
uint32_t OnPortP;
uint8_t OnPinP;
// for the NChannel mosfets (lowside switches)
uint32_t OnPortN;
uint8_t OnPinN;
};
/*
* Represents a single state in the sequence of states needed to run the motor.
* Essentially, this is coorelated with a particular stator coil polarized in a particular direction.
* These states repeat 6 times every 60 degrees for a total of 360 degrees.
Page 96
of 103
* Each state is assigned a particular set of pins. When the state is on, those pins are on. Otherwise, those pins are off.
*/
class State {
public:
State(PinAssignments* pins, int32_t baseAngle, int32_t timing);
// returns true if the given angle is suitable to be handled by this state
bool CanHandleAngle(uint32_t rotorAngle, uint32_t throttlePercent);
// activates the pins associated state
bool Activate();
// deactivates the pins associated with the state
void Deactivate();
private:
// the pins associated with this state
struct PinAssignments* mPins;
// optimal torque angle for this state.
// calculated once at startup.
int32_t mOptimalAngle;
};
#endif /* STATE_H_ */
/*
* StatorManager.cpp
*
* Created on: Oct 29, 2015
* Author: Joshua, Stephen
*/
#include "StatorManager.h"
StatorManager::StatorManager(
RotorManager* rotor, ThrottleManager* throttle,
uint32_t portC, uint8_t pinC4, uint8_t pinC5, uint8_t pinC6, uint8_t pinC7,
uint32_t portF, uint8_t pinF1, uint8_t pinF2, uint8_t pinF3, uint8_t pinF4) {
mRotor = rotor;
mThrottle = throttle;
mModulateCoil = false;
// this is where the pin assignments, base angles and quadrature angles are configured
// for each state (stator coil). This list need not be in any particular order
// as long as each coil is configured correctly.
mStates[0] = new State(new PinAssignments(portF, pinF3, portC, pinC5), 10, STATOR_TIMING);
mStates[1] = new State(new PinAssignments(portF, pinF3, portC, pinC7), 20, STATOR_TIMING);
mStates[2] = new State(new PinAssignments(portF, pinF3, portF, pinF2), 30, STATOR_TIMING);
mStates[3] = new State(new PinAssignments(portC, pinC4, portF, pinF4), 40, STATOR_TIMING);
mStates[4] = new State(new PinAssignments(portC, pinC6, portF, pinF4), 50, STATOR_TIMING);
mStates[5] = new State(new PinAssignments(portF, pinF1, portF, pinF4), 60, STATOR_TIMING);
}
void StatorManager::Update() {
// grab the needed info from the rotor and throttle
float rotorAngle = mRotor>GetAngle();
uint32_t throttlePercent = mThrottle>GetPercent();
// convert the rotor angle to an effective angle.
// This is possible because the 6 states repeat 6 times every 60 degrees
Page 97
of 103
// to make a full 360.
float effectiveAngle = (uint32_t)rotorAngle % 60;
// keep track of which state should be on.
int32_t activeState = 1; // less than 0 means no active state
// Handle the Rotor coil behavior for different situations
if(mRotor>IsIdle()) {
if(throttlePercent > 5) {
// startup state
throttlePercent = 100; // simulate 100 percent throttle for startup
mModulateCoil = false;
} else {
// idle state
throttlePercent = 0;
mModulateCoil = false;
}
} else {
// run or regen states
mModulateCoil = true;
}
// figure out which states (if any) need to be on.
// at the same time, deactivate states which can't handle the current angle.
for(int i = 0; i < 6; i++) {
if(mStates[i]>CanHandleAngle(effectiveAngle, throttlePercent)) {
activeState = i;
} else {
mStates[i]>Deactivate();
}
}
// activate the single active state (if any)
if(activeState >= 0) {
mStates[activeState]>Activate();
mRotor>ActivateCoil(mModulateCoil); // the coil should only be on when a state is on too.
} else {
mRotor>DeactivateCoil();
}
}
/*
* StatorManager.h
*
* Created on: Oct 29, 2015
* Author: Joshua, Stephen
*/
#ifndef STATORMANAGER_H_
#define STATORMANAGER_H_
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "State.h"
#include "GeneralUtil.h"
Page 98
of 103
#include "RotorManager.h"
#include "ThrottleManager.h"
#define STATOR_TIMING 5 // ** THIS IS THE QUADRATURE ANGLE FOR ALL STATES **
class StatorManager {
private:
// access to the rotor and throttle
RotorManager* mRotor;
ThrottleManager* mThrottle;
// all 6 discrete states needed to make a complete rotation.
// these states are repeated 6 times every 60 degrees to make a full 360.
State* mStates[6];
// depending on the situation, we may want to modulate the rotor coil
// in order to increase efficency, reduce back emf, and increase speed.
bool mModulateCoil;
public:
StatorManager(
RotorManager* rotor, ThrottleManager* throttle,
uint32_t portC, uint8_t pinC4, uint8_t pinC5, uint8_t pinC6, uint8_t pinC7,
uint32_t portF, uint8_t pinF1, uint8_t pinF2, uint8_t pinF3, uint8_t pinF4);
// Runs the logic to turn the coils on and off.
void Update();
};
#endif /* STATORMANAGER_H_ */
/*
* ThrottleManager.cpp
*
* Created on: Nov 3, 2015
* Author: Stephen
*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "ThrottleManager.h"
#include "math.h"
// min and max numerical readings from the ADC
#define THROTTLE_MIN 700
#define THROTTLE_MAX 3600
ThrottleManager::ThrottleManager(uint32_t port, uint8_t pinVin) {
// enable analog function on the pin
ROM_GPIOPinTypeADC(port, pinVin);
Page 99
of 103
ROM_ADCReferenceSet(ADC0_BASE, ADC_REF_INT); // uses the internal 3V reference
// disable sequencer 3 before configuration
ROM_ADCSequenceDisable(ADC0_BASE, 3);
// Use sequencer 3 on ADC0, triggered manually by the processor, with the higest priority (0).
ROM_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_IE | ADC_CTL_END | ADC_CTL_CH0);
// enable sequencer 3
ROM_ADCSequenceEnable(ADC0_BASE, 3);
// trigger a sequence so the value is ready for the first update.
ROM_ADCProcessorTrigger(ADC0_BASE, 3);
}
int32_t ThrottleManager::GetPercent() {
return mPercent;
}
void ThrottleManager::Update() {
uint32_t rawReading;
// Wait until the previous sample sequence has completed
// but dont wait forever lest we hang the microcontroller.
uint32_t tries = 0;
while(!ROM_ADCIntStatus(ADC0_BASE, 3, false)) {
tries++;
if(tries > 10) return;
}
// Read the value from the ADC.
ROM_ADCSequenceDataGet(ADC0_BASE, 3, &rawReading);
// convert to a percent using known min and max numerical values from the ADC
// these were determined expirementally and contain a small amount of slack
// on the high and low ends.
mPercent = ((int32_t)rawReading THROTTLE_MIN) / ((THROTTLE_MAX THROTTLE_MIN) / 100);
// clamp to 0 and 80 percent for reliability reasons.
if(mPercent < 0) mPercent = 0;
if(mPercent > 80) mPercent = 80;
// finally, trigger the sequencing so the value is ready for next time
ROM_ADCProcessorTrigger(ADC0_BASE, 3);
}
/*
* ThrottleManager.h
*
* Created on: Nov 3, 2015
* Author: Stephen
*/
#ifndef THROTTLEMANAGER_H_
#define THROTTLEMANAGER_H_
class ThrottleManager {
public:
ThrottleManager(uint32_t port, uint8_t pinVin);
Page 100
of 103
// grabs the throttle information from the hardware
void Update();
// returns the last read throttle percent
int32_t GetPercent();
private:
// the last read throttle percent
int32_t mPercent;
};
#endif /* THROTTLEMANAGER_H_ */
/*
* Timer.cpp
*
* Created on: Oct 27, 2015
* Author: Stephen
*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_nvic.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/ssi.h"
#include "driverlib/systick.h"
#include "Timer.h"
#include "GeneralUtil.h"
#define SYS_TICK_PERIOD_MAX 0xFFFFFF
void Timer::ResetAndStart() {
ROM_SysTickDisable(); // stop the timer tick
ROM_SysTickPeriodSet(SYS_TICK_PERIOD_MAX);
*((uint32_t*)NVIC_ST_CURRENT) = 0x01;// writing any value triggers immediate reset of counter value
ROM_SysTickEnable(); // start the timer tick
}
void Timer::Stop() {
ROM_SysTickDisable();
}
// Elapsed since last reset
uint32_t Timer::GetElapsedMicro() {
// get the counter value
uint32_t sysTickValue = ROM_SysTickValueGet();
// assumed 80MHz clock for speed of operation
float nanosPerClock = 12.5; // The actual calculation: (1000000000.0 / (float)GeneralUtil::GetSysClock());
// calculate the elapsed clock cycles and convert to microseconds.
uint32_t elapsedClocks = SYS_TICK_PERIOD_MAX sysTickValue;
uint32_t elapsedMicros = (elapsedClocks * nanosPerClock) / 1000;
return elapsedMicros;
}
Page 101
of 103
/*
* Timer.h
*
* Created on: Oct 27, 2015
* Author: Stephen
*/
#ifndef TIMER_H_
#define TIMER_H_
/*
* General purpose timer for measuing the time between events
*/
class Timer {
public:
// resets the timer to zero, and starts it again.
static void ResetAndStart();
// stops the timer alltogether
static void Stop();
// returns the number of microsenconds since the timer was started
static uint32_t GetElapsedMicro();
};
#endif /* TIMER_H_ */
Page 102
of 103