<<

Resonant Power Transfer with Embedded Communication for More Versatile and Efficient Applications by Erik Johnson Submitted to the Department of Electrical Engineering and Computer Science in partial fulfillment of the requirements for the degree of Master of Engineering in Electrical Engineering and Computer Science at the MASSACHUSETTS INSTITUTE OF TECHNOLOGY June 2016 ○c Erik Johnson, MMXVI. All rights reserved. The author hereby grants to MIT permission to reproduce and to distribute publicly paper and electronic copies of this thesis document in whole or in part in any medium now known or hereafter created.

Author...... Department of Electrical Engineering and Computer Science May 20, 2016 Certified by...... Eko Lisuwandi Senior Design Engineer, Linear Technology Thesis Supervisor Certified by...... David Perreault Professor of Electrical Engineering Thesis Supervisor Accepted by...... Dr. Christopher J. Terman Chairman, Masters of Engineering Thesis Committee 2 Resonant with Embedded Communication for More Versatile and Efficient Applications by Erik Johnson

Submitted to the Department of Electrical Engineering and Computer Science on May 20, 2016, in partial fulfillment of the requirements for the degree of Master of Engineering in Electrical Engineering and Computer Science

Abstract This thesis explores the feasibility of embedding communication within the power transfer channel of a near field wireless power transfer system in order to increase the versatility and efficiency of the system. The system was built around the LTC4125 auto-resonant wireless power IC. Both the transmitter and receiver were tuned to approximately 100kHz with a communication data bit rate of 1kHz. The thesis covers both resonant wireless power transfer theory, the details of the embedded communication and the results obtained.

Thesis Supervisor: Eko Lisuwandi Title: Senior Design Engineer, Linear Technology

Thesis Supervisor: David Perreault Title: Professor of Electrical Engineering

3 4 Acknowledgments

I would like to first thank my 6A advisor Eko Lisuwandi for his willingness towork with me and be my advisor. I am thankful for his guidance and patience throughout the project. I enjoyed discussing different obstacles with him and I appreciate that he was always available to help me think about any problem. I would like to thank Sam Nork at Linear for making this great opportunity possible. I would like to thank Ron Swinnich for his help in my moments of need and his unfailing company in the lab. I would also like to thank the other engineers at Linear for creating a very welcoming and enjoyable work environment. I especially am thankful for Erjon, Maziar and Chris and all of the fun we had playing soccer together. I would like to thank Professor David Perreault for his willingness to my on-campus advisor and for being a great mentor during my senior year UROP. I would like to thank my friends at MIT for the countless memories, their encour- agement and friendship throughout my time at MIT. I would like to thank my parents and my family for their enduring love and support. The sacrifices they have made and the love they have shown me has made it all possible. Finally I am thankful to God for the uncountable blessings I am given each day.

5 6 Contents

1 Near Field Resonant Wireless Power Transfer 19 1.1 Overview of Near Field Wireless Power ...... 19 1.1.1 Near Field Wireless Power Transfer ...... 19 1.1.2 Resonant Inductive Power Transfer ...... 20 1.2 Use Applications ...... 20 1.3 Optimization Methods ...... 21 1.3.1 Optimization without Adaptive Control ...... 21 1.3.2 Optimization with Adaptive Control ...... 23 1.4 Mathematical Modeling ...... 28 1.4.1 Basic Terminology ...... 28 1.4.2 Linear Models of Resonant Power Transfer ...... 31 1.4.3 Transfer Functions and Peak Splitting ...... 36 1.4.4 Linear Model Efficiency Derivation ...... 48 1.5 LTC Wireless Charging Options ...... 54 1.5.1 LTC 4120 ...... 54 1.5.2 LTC 4125 ...... 56

2 Modeling, Initial Data Measurements and Thesis Objec- tives 57 2.1 Rectifier Model ...... 57 2.1.1 Buck Converter ...... 60 2.1.2 Effective Load ...... 60 2.2 Initial Data Measurements ...... 61

7 2.2.1 Verifying the Linear Model with Data Measurements . . . . . 61 2.2.2 AC Load Efficiency ...... 62 2.2.3 Variable Rectified Voltage Measurements ...... 63 2.3 Identification of Thesis Objectives ...... 72

3 Communication 73 3.1 Communication overview ...... 73 3.2 Description of the Uplink Communication: Power Receiver to Power Transmitter ...... 74 3.2.1 Differential Manchester Encoding ...... 75 3.3 Description of the Downlink Communication: Power Transmitter to Power Receiver ...... 84 3.4 Signal Processing ...... 87 3.4.1 Analog Filtering ...... 87 3.4.2 Digital Filtering ...... 91

4 Feedback Control Theory and the Closed Loop System 93 4.1 Modeling a Continuous Time System as a Discrete Time System . . . 93 4.2 Modeling a Continuous Time Controller in Discrete Time ...... 96 4.2.1 Discrete Time Filters ...... 99 4.3 Open Loop System ...... 101 4.4 Smith Predictor Controller ...... 102 4.5 Closed Loop System ...... 106 4.5.1 Block Diagram and Calculations ...... 106 4.5.2 Measurements ...... 110

5 Battery Charging 113 5.1 Overview of Battery Charging ...... 113 5.2 Analog Controlled Battery Charging ...... 114 5.3 Digitally Controlled Battery Charging ...... 116

8 6 Communication and Max Efficiency Finding Algorithm 117 6.1 Efficiency Optimization Overview ...... 117 6.2 Power Transmitter Side Flow Chart ...... 118 6.3 Power Receiver Side Flow Chart ...... 120 6.4 Power Transmitter Efficiency Optimization Flow Chart . . . . . 124

7 Results and Future Considerations 127 7.1 Efficiency Comparisons ...... 127 7.2 Range Extension ...... 131 7.3 Future Considerations to Improve the System ...... 132

A Pictures of the System 135

B System Code 137 B.1 Power Transmitter Code ...... 137 B.2 Power Receiver Code ...... 202

9 10 List of Figures

1-1 Modulation Circuit ...... 24 1-2 Voltage waveforms on the primary of a load-impedance mod- ulated signal ...... 24 1-3 Standard Communication Diagram ...... 25 1-4 Response of a resonant LC circuit. The modulation side- bands are shown at the frequency of the carrier plus and minus half bandwidth ...... 26 1-5 A system with seperate inuctuve power and data links...... 27 1-6 Linear Model with a Parallel Receiver Tank ...... 32 1-7 Feedback Block Diagram for the Linear Model ...... 33 1-8 Linear Model with a Series Receiver Tank ...... 35 1-9 Parallel Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Factors ...... 37 1-10 Parallel Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors ...... 38 1-11 Parallel Resonant Voltage TF vs. Frequency for R = 100 Ohms and Various Coupling Factors ...... 38 1-12 Unloaded Root Locus for a Parallel Resonant Receiver ...... 39 1-13 Root Locus for a Parallel Resonant Receiver with R = 100 ...... 40 1-14 Series Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors ...... 41 1-15 Series Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors ...... 41

11 1-16 Series Resonant Voltage TF vs. Frequency for R = 100 Ohms and Various Coupling Factors ...... 42 1-17 Root Locus for a Series Resonant Receiver with R = 10 ...... 43 1-18 Parallel Off-Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors ...... 44 1-19 Parallel Off-Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors ...... 44 1-20 Parallel Off-Resonant Voltage TF vs. Frequency for R = 100 Ohms and Various Coupling Factors ...... 45 1-21 Series Off-Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors ...... 46 1-22 Series Off-Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors ...... 46 1-23 Series Off-Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors ...... 47 1-24 Parallal Resonant Efficiency ...... 51 1-25 Series Resonant Efficiency ...... 52 1-26 Parallel vs Series Resonant Efficiency ...... 53 1-27 Effective Resistance of Battery Charging for Various Rectified 53 1-28 LTC4120 Diagram ...... 55

2-1 Resonant DC-DC Converter ...... 58 2-2 Power Receiver Side with a Half Bridge Rectifier ...... 58 2-3 Wireless Power Circuit with a Rectified and Bucked Load . . . . 61 2-4 Linear Model Verification ...... 62 2-5 Predicted vs Measured Efficiencies for an AC Load ...... 63 2-6 Efficiency vs Output Power for Various Rectified Voltages with k=0.41 64 2-7 Efficiency vs Output Power for Various Rectified Voltages with k=0.13 65 2-8 Output Power vs Rect V for Various Input Duty Cycles and K = 0.13 66 2-9 Output Power vs Rect V for Various Input Duty Cycles and K = 0.188 66

12 2-10 Output Power vs Rect V for Various Input Duty Cycles and K = 0.41 67 2-11 Output Power vs Duty Cycle for Various Rect V and k = 0.188 . . . 68 2-12 Output Power vs Duty Cycle for Various Rect V and k = 0.41 . . . . 69 2-13 Efficiency vs Rect V for Various Input Duty Cycles and K =0.41. 70 2-14 Efficiency vs Rect V for Various Input Duty Cycles and K =0.28. 70 2-15 Efficiency vs Rect V for Various Input Duty Cycles and K = 0.188. 71 2-16 Efficiency vs Rect V for Various Input Duty Cycles and K =0.13. 71

3-1 Basic Communication Diagram ...... 74 3-2 Capacitor Modulation Circuit ...... 75 3-3 Differential Manchester Encoding ...... 75 3-4 Screenshot of Communication ...... 76 3-5 Screenshot of Decoding the Uplink Communication ...... 78 3-6 Decoding the Uplink Communication ...... 79 3-7 Missed Transition During Decoding ...... 80 3-8 Communication Frequency Precision Requirements ...... 82 3-9 Downlink Communication ...... 85 3-10 Downlink Communication Zoomed In ...... 86 3-11 Analog Filtering Circuit ...... 88 3-12 First Steps of Analog Filtering ...... 89 3-13 Second Steps of Analog Filtering ...... 90 3-14 Comparison Between Two Different Filter ...... 91

4-1 A Continuous Time Plant with a Digital Controller ...... 93 4-2 A DAC, Continuous Time Plant and ADC Replaced by a Discrete Time Equivalent ...... 94 4-3 DAC Zero Order Hold Output Waveform ...... 94 4-4 Zero Order Hold Pulse ...... 95 4-5 Discrete Time Equivalent Transformation of the Continuous Time Plant 95 4-6 Z and S Transform Pairs ...... 96 4-7 Discrete Time Integral Approximations ...... 97

13 4-8 Difference Equations and Corresponding Z Transforms for the Contin- uous Time Integrator ...... 97 4-9 S to Z Equivalents for Three Types of Difference Equations . . . . . 98 4-10 Mapping of Stable Continuous Time Transfer Functions (Shaded) to the Z Plane ...... 98 4-11 First Order Time Constant Measurements for Different Coupling Fac- tors and Rectified Voltages ...... 101 4-12 First Order Step Response for K = 0.16 ...... 102 4-13 First Order Step Response for K = 0.532 ...... 102 4-14 A Standard Feedback System with a Smith Predictor for Compensation103 4-15 Input Vpth to Output Current Gain For Different Coupling Factors and Loading Levels ...... 104 4-16 High Gain Situation with a Low Gain Prediction ...... 105 4-17 Low Gain Situation with a Low Gain Prediction ...... 105 4-18 High Gain Situation with a High Gain Prediction ...... 106 4-19 Low Gain Situation with a High Gain Prediction ...... 106 4-20 Closed Loop Feedback Block Diagram ...... 107 4-21 Bode Plot of the System’s Open Loop Transfer Function ...... 110 4-22 Matlab Step Response with a Conservative Controller: Kp = 0.04, Ki = 0.03 ...... 111 4-23 Measured Step Response with a Conservative Controller: Kp = 0.04, Ki = 0.03 ...... 111 4-24 Matlab Step Response with an Aggressive Controller: Kp = 0.1, Ki = 0.1...... 112 4-25 Measured Step Response with an Aggressive Controller: Kp = 0.1, Ki =0.1...... 112

5-1 Typical Analog Controlled Li-Ion/Polymer Battery Charging Curve . 114 5-2 Constant Current Constant Voltage Analog Error Gain Circuit . . . . 115 5-3 Digitally Controlled Battery Charging Cycle ...... 116

14 6-1 Establishing Communication and Power Transfer ...... 119 6-2 Beginning Communication and Power Transfer with a Chirp . . . . . 119 6-3 Power Transmitter Communication Flow Chart ...... 120 6-4 Power Receiver Side Communication Flow Chart ...... 122 6-5 Power Transmitter Communication ...... 123 6-6 Restored Communication ...... 123 6-7 Dynamic Response After a Change in the Rectified Voltage ...... 125 6-8 Power Control Flow Chart in the Power Transmitter ...... 126

7-1 Efficiency With and Without Communication for Various Rect Volt- ages with K = 0.532 ...... 129 7-2 Efficiency With and Without Communication for Various Rect Volt- ages with K = 0.283 ...... 130 7-3 Efficiency With and Without Communication for Various Rect Volt- ages with K = 0.16 ...... 131

A-1 Power Transmitter Board ...... 135 A-2 Power Transmitter Board ...... 136 A-3 Power Receiver Board ...... 136

15 16 List of Tables

1.1 Measurements of K for Known Distances between the Coils ...... 30 1.2 Resonant Circuit Values ...... 37

3.1 Analog Signal Filtering Values ...... 89

4.1 Numerical Values for the Closed Loop Feedback Block Diagram in Figure 4-20 ...... 109

17 18 Chapter 1

Near Field Resonant Wireless Power Transfer

1.1 Overview of Near Field Wireless Power

Large-scale wireless power transfer has been happening in for over 100 years. Though there were select high tech applications of wireless charging through- out the 20th century, due to the now proven efficiencies and range of resonant wireless power, there has recently been a surge in demand from consumers for relatively low power wireless power. This has driven competitive research among consumer compa- nies and universities to develop more efficient and versatile wireless charging solutions. The purpose of this first chapter will be to present an overview of the uses, related field work and mathematical theory of near field wireless power transfer.

1.1.1 Near Field Wireless Power Transfer

Compared to the of the AC frequency, near field wireless power trans- fer occurs over a relatively small distance via magnetically coupled windings. The magnetic coupling of the windings allows the transfer of power through their mutual . This is called inductive power transfer because an alternating created by the transmitter coil presents alternating to the receiver

19 coil, inducing an electrical potential, or voltage, in the receiver coil. This induced voltage can then cause current to flow in the receiver coil. Depending on the distance and the alignment between the transmit and receive coil, only a fraction of the magnetic flux generated by the transmitter coil reaches the receiver coil and therefore contributes to . The more magnetic flux that reaches the receiver coil, the better the coils are coupled. The fraction ofthe magnetic flux produced by the transmitter coil that reaches the receiver coil is called the coupling factor (k). (See Section 1.41) For a given amount of power transferred, a higher coupling factor means lower transmitted flux and therefore lower currents in the transmit coil. Lower currents reduce parasitic losses and heating in the coils. Applications with a coupling factor less that 0.6 [1] are generally called loosely coupled systems. The result is lower efficiencies, heating, and stray flux (electromagnetic interference, or EMI).

1.1.2 Resonant Inductive Power Transfer

In order to improve efficiency and increase power transfer levels, the transmit and receive coils in loosely coupled systems are operated at their resonant frequencies, creating a resonant inductive power transfer system. [1], [2], [3] Resonant inductive power transfer systems are created by designing each transmit and receive coil to resonate with a capacitor, forming a resonant tank. It is then critical to design the coils and tank capacitor to be very efficient, having high quality factors because of the large oscillating present in the resonant tank. (See Section 1.4.4)

1.2 Use Applications

Inductively coupled near-field wireless links have been extensively used in various im- planted medical devices. [3], [4], [5] , [6] , [7], [8] , [9] , [10] They are used for both diagnosis and treatment of a wide variety of conditions. Some examples are pace- makers for cardiac arrhythmia, retinal implants for the blind, cochlear implants for deafness, deep-brain stimulator’s for Parkinson’s disease, spinal-cord stimulator’s for

20 control of pain, and brain-machine interfaces for paralysis prosthetics. Such devices need to be small and operate with low power to make chronic and portable medical implants possible. [2] Even though the receiver should be relatively fixed in place, the implanted devices can have varying coupling factors and load levels. For instance, in [11] where a transcutaneous powering device for an artificial heart was designed, the coupling coefficient was estimated to vary between 0.108 and 0.320. For the retinal in [12], the coupling coefficient varied from 0.08 to 0.24. [13] Further, because ofthe battery charging application required by most wireless power links, the loading will not be constant because of the nature of the battery charging curves. (See Chapter 5).

1.3 Optimization Methods

1.3.1 Optimization without Adaptive Control

To combat the variable coupling or loading conditions, people have tried to optimize the design for a range of loading and coupling values to make the best of the situation without having any feedback or adaptive control. When trying to design for an unadaptive power transfer system, Donaldson in [14] explains that efficiency and displacement tolerance are opposing design trade-offs. Specifically, for a given coil’s Q and coupling coefficient, k, maximum coupling effi- ciency occurs at a point where the displacement tolerance is quite poor. [15] One common approach for a non-adaptive design is described by [4] and is called the geometric approach. Here both the transmitter and receiver coils are circular and planar, with the receiver coil smaller than the transmitter coil. Even if the coils are moved within parallel planes or rotated, so long as the receiver coil is within the perimeter of the transmitter coil, the coupling coefficient will remain fairly constant. This method therefore provides lateral displacement tolerance. The performance cost of such a semi-tolerant design is extra losses in the primary

21 coil. In order to obtain a desired receiver voltage, the transmitter coil must carry a larger current than it would if the coils were more equally sized. This is because it must generate more flux and therefore it will have more 퐼2푅 losses. Another disadvantage is that the size of the external circuit must be bigger than normal. Though such a geometric method provides tolerance in lateral displacements, the coupling coefficient drops-off proportional to the separation of the coils and therefore the geometric approach is not separation-tolerant.

Another unadaptive method described by [14] et al. is the “critical coupling,” k(crit), method in which the of the secondary impedance in the primary circuit is real for all values of coupling coefficient k. This approach minimizes the change in reactance of the primary coil for changes in the secondary load conditions, and tends to compromise between maximizing voltage transfer, and minimizing coil displacement effects.

As pointed out in both [14] and [16], maximum voltage transfer between two coils occurs when the receiver coil is tuned to the transmitter resonant frequency. By making note of this fact, Galbraith [4] describes a method of desensitizing the voltage transfer ratio by detuning both the transmitter and receiver circuits away from their resonant frequency, one above and one below. This method is called stagger tuning. This method provides displacement tolerance, efficiency, and wide bandwidth. Galbraith notes that the poles shift when the coupling coefficient varies. If the poles are properly placed, they shift in a manner that compensates the link gain for the change in coupling. This results in a variation of the reflected impedance for changes in coupling coefficient. The effect of increased coupling would be toincrease the link gain while the effect of increased reflected impedance would be to lower the generated magnetic field. These two effects cancel each other and produce alink gain that is fairly insensitive to the coupling coefficient and therefore displacement tolerant. Section 1.4.3 describes this pole splitting effect in more detail.

Unfortunately, both of these approaches provide little benefit for systems with unusually low values of k. Donaldson has shown that both coupling efficiency and voltage transfer ratio are extremely low if k(crit) is more than one order of magni-

22 tude larger than the application k. A high k(crit)/k ratio typically compromises the efficiency of the active output driver stage.

1.3.2 Optimization with Adaptive Control

Because of the unsatisfactory results for non-adaptive systems, research effects have been directed to actively compensating the loading/coupling variation. In [17], closed- loop control was proposed to estimate the coupling coefficient by detecting the pri- mary coil voltage and current. This method somewhat reduced the impact of any coupling change, but it was only applicable to systems with constant loading. Fur- thermore, without knowing the exact values of the received power at the secondary side, it could not achieve optimal compensation. In [18], the secondary side rectified voltage was sensed to maintain the rectified voltage at a desired level. However, a tethering wire instead of wireless back-telemetry was used to transmit the sensed voltage to the external unit. [15]

Wireless Communication Based Adaptive Control

If however the impedance of the secondary side can be changed based on the cou- pling coefficient it may be possible to obtain reasonable efficiency and power transfer levels across a wider range of coupling factors. A straightforward and reliable way to accomplish this is with added communication and data between the two coils. With an added communication channel, the operating conditions of the power receiver can be known by the power transmitter, allowing for proper adjustment on the power transmitter side.

Communication and Power over a Shared Channel

Wireless inductive power links which use a single carrier frequency for power and data are widely used in RFID systems and are a growing solution for medical implants. [19] [8] [20] [15] [21] [13] [22] [4] The typical method used is called impedance modulation, load modulation, absorption modulation or backscattering. [3] et al.

23 Data transfer is accomplished by modulating the resonant frequency of the receiver tank by adding and removing a capacitor to the receiver tank according to the drive state of the encoded signal. The result of the modulated capacitor is to modulate the Qs of the system and therefore modulate the energy stored in the resonant tanks. This has a direct modulation affect on the associated tank voltage peaks. The capacitor modulation circuit is shown in Figure 3-2.

Figure 1-1: Capacitor Modulation Circuit

The amplitude of the signal is dependent on the value of the modulated capacitor, the coupling factor and the power transmission level. The idealized result of load impedance modulation is shown in Figure 1-2. [19]

Figure 1-2: Voltage waveforms on the primary resonator of a load-impedance modu- lated signal

The power dissipated in the implanted system should be minimized. For medical applications, excess heat dissipated within the body results in tissue damage. In addition, the number of useful battery recharges is limited to typically about 1000. [3] In general the receiver has tighter space constraints than the transmitter and therefore

24 should burn less power for heat dissipation requirements. For implanted systems, sending the data from the implant to an external unit is called the uplink communication. For systems with high uplink bandwidth require- ments, for the reasons given above, it is even more critical to move as much of the power losses and complexity to the external unit because the high bandwidth costs power and that power should not usually be burned in the receiver device. [3] Usually a low bandwidth data link from the external unit to the implanted device is needed for control, programming, and feedback information. This is called the downlink communication. The distinction is shown in Figure 1-3.

Figure 1-3: Standard Communication Diagram

The coupling coefficient typically decreases as 푑−3 [3], where d is the separation between the coils. The strong dependence of coupling on distance therefore makes impedance modulation unsuitable for long-range links. For short-range links, however, it possesses the great advantage of dissipating almost no power on the transmitting (power receiver) side of the link. This advantage allows an implanted system to transmit data while keeping its power consumption to a minimum. [3] For such systems with communication embedded in the power transfer channel there is a trade-off between the communication bandwidth and the efficiency ofthe

25 system. As will be shown in Section 1.4.4, there is a strong relation between the quality factor of the and the efficiency of the power transfer. On the other hand the quality factor is inversely proportional to the bandwidth. [19]

푓0 푄 = Bandwidth

It is further noted in [19] that modulating the baseband signal results in sidebands as shown in Figure 1-4. In general and also shown in Figure 1-4, to make sure that the modulated signal is not too severely attenuated, the sidebands should be kept within the half power bandwidth of the resonator. For high communication needs, low quality factor resonators have to be used. For example with a carrier frequency of 1Mhz and a quality factor of 10, the resonator bandwidth is 100kHz. Using load modulation and assuming a binary encoding scheme where each bit is no more than 1 transition, this would limit the communication speed to 50kbps.

Figure 1-4: Frequency Response of a resonant LC circuit. The modulation sidebands are shown at the frequency of the carrier plus and minus half bandwidth

Separate Communication and Power Transfer Channels

For the bandwidth reasons given above, it is generally advantageous to separate the power and data transfer functions of a wireless link. [23] [8] [24] et al. Power signals carry no information and power transfer efficiency is maximized for narrow-band (high Q) links that usually operate at low frequencies. The low frequency requirement

26 is especially important in medical devices to minimize losses in body tissues. On the other hand, data signals need enough link bandwidth for their information and therefore need to be operated at higher frequencies. By separating the data and power channels it allows for better optimization. In [3] the efficiency of the data link is optimized and in [2] the power link is optimized. A diagram of the resulting setup is shown in Figure 1-5 [19].

Figure 1-5: A system with seperate inuctuve power and data links.

One downside of this approach is that there is cross coupling between the power and data coils. Even if the coils are placed perpendicular to each other there will still be some cross coupling due to non-idealities. In [25] and [26] the design equations are derived and analyzed to maximize the data communication rate. The results show that though the design is more complex, data can be transmitted without compro- mising the power transmission efficiency. Another disadvantage is the added space, complexity and associated cost of a dual band system. Although such a system would be a reasonable idea to investigate in the future, it was decided that there was enough merit in designing and building a system with a shared power and data transfer channel and investigating the potential gains in efficiency over the current Linear Technology setup.

27 1.4 Mathematical Modeling

1.4.1 Basic Terminology

Mutual Inductance

The mutual inductance (푀21) experienced by coil 2 is defined as the amount of flux

that cuts through the turns of coil 2 (휆2), divided by the amount of current in coil 1

(퐼1).

휆2 푀21 = 퐼1

휆 is specifically used to denote the linkage flux, which is the sum total of theflux experienced by all of the turns of coil 2. For most coils, in which the same amount of flux passes through each turn, the linkage flux is equal to the flux passing through

the coil (Φ) times the number of turns in the coil (푁2) so that 휆2 = 푁2Φ. In the case where the two coils are perfectly coupled, i.e. an ideal , the amount of flux passing through the second coil is equal to the flux generated by the first coil. The amount of flux produced in the first coil can be found viaAmpere’s Law:

푁1휇퐼1 Φ = 퐵1퐴1 = 퐴1 푙1

Where 푙1 is the length of the magnetic path, 퐴1 is the cross sectional area of the

coils and 휇 is the permeability of the medium. For a simple transformer, 푙1 is the length of the in the direction normal to the turns and 퐴1 is the cross sectional area. Substituting this value for the flux produced by coil 1 into the equation forthe mutual inductance we get:

푁2 푁1휇퐼1퐴1 푁1푁2휇퐴 푀21 = = 퐼1 푙1 푙 In the last equation on the right it is assumed that like in the ideal transformer case, the cross sectional area and magnetic path length are the same for each coil. From the elementary equation for an inductor, the voltage induced in coil 2 due to

coil 1 (푉푀21) can then be written:

28 푑퐼1 푉푀12 = 푀21 푑푡

Likewise, the voltage induced in coil 1 due to the current in coil 2 can be written:

푑퐼2 푉푀12 = 푀12 푑푡

Because of the symmetry of the situation, the two mutual inductance values are equal so that 푀12 = 푀21 = 푀. So far it has been assumed that all of the flux produced by each coil is coupled by the other coil. However, for near field wireless charging this is never the case. Instead, only a fraction of the flux makes it from one coil to the other. Another term called the coupling factor (푘) needs to be added to the equation.

Coupling Factor

The coupling factor accounts for the fraction of the flux of the transmitting coil that actually couples to the receiver coil. The modified mutual inductance equation is then:

푁1푁2휇퐴 푀21 = 푘 푙

Given that the self inductance of a coil is:

2 푁1 휇퐴 퐿11 = 푙

The Mutual Inductance can be generically written as the geometric mean of the two self inductance values multiplied by the coupling factor: √ 푀21 = 푘 퐿1퐿2 = 푀12 = 푀

As stated above, for coupling factors less than 0.6, the system is said to be loosely coupled. As will be shown below in Section 1.4.4, when the system operates at the efficiency for loosely coupled systems can remain quite high.

29 # of Spacers Distance (mm) L Aided L Opposed M K 2 3.3 147.4 47.9 24.875 0.725 3 4.95 120 47 18.25 0.532 4 6.6 106 48.85 14.2875 0.417 5 8.25 98.7 51.67 11.7575 0.343 6 9.9 93.2 54.4 9.7 0.283 7 11.55 88.4 56.98 7.855 0.229 8 13.2 85.1 59.3 6.45 0.188 9 14.85 83 61 5.5 0.160 2 + Spacer 16.17 76.7 66.16 2.635 0.077 3 + Spacer 17.82 75.9 66.87 2.2575 0.066 4 + Spacer 19.47 75.2 67.45 1.9375 0.057 5 + Spacer 21.12 74.75 67.96 1.6975 0.050 6 + Spacer 22.77 75.28 68.38 1.725 0.050 7 + Spacer 24.42 73.94 68.737 1.30075 0.038 8 + Spacer 26.07 73.6 69.04 1.14 0.033 9 + Spacer 27.72 73.36 69.3 1.015 0.030 10 + Spacer 29.37 73.1 69.53 0.8925 0.026

Table 1.1: Measurements of K for Known Distances between the Coils

Coupling Factor Measurements

For the sake of understanding the measurements I would be taking, I needed to know the coupling factor for known distances of separation. I did this by following the method and derivation described in [27]. The mutual inductance can be found by measuring the inductance of two coils when they are aiding each other magnetically and when they are opposed to each other magnetically. The mutual inductance is then:

퐿푎푖푑푒푑−퐿표푝푝표푠푒푑 푀 = 4

Once the mutual inductance is known for two coils at a certain distance, the coupling coefficient can be computed. My measured data is shown in Table 1.1.The number of spacers represent the number of 1.65mm plastic washers. The extra spacer represents an additional spacer of height 12.87mm.

30 Quality Factor

The quality factor of an element or system formulates how much energy is stored vs how much energy is lost per oscillation cycle. Formally its equation is:

Energy Stored 푄 = 2휋 * Energy Dissipated per Cycle

Sometimes it is desirable to damp a system and therefore have a low quality factor. However for resonant near field wireless power transfer, a very high Qis desirable so that large amounts of current can be oscillating in the transmitter coil, thereby creating a lot of magnetic flux, without burning too much power in the parasitic resistances. Therefore the of each resonant tank should be very high. If the Q is sufficiently high, when low power is fed into the transmitter coil,a relatively intense oscillating magnetic field builds up over multiple cycles and creates a situation where the power stored in the oscillating magnetic field is much greater than the power being fed into the transmit coil. A resonantly tuned receiver coil then provides a low impedance path for the magnetic flux, driving power into the receiver circuit.[1]

Unloaded Quality Factors

The primary side quality factor is dependent on the transmitter coil’s parasitic resis- tance 푅1, the coil inductance 퐿1, and the drive oscillating frequency.

휔퐿1 푄1 = 푅1 On the secondary side the unloaded quality factor is also dependent on the para- sitic resistance of the coil, the coil inductance and oscillating frequency.

휔퐿2 푄2 = 푅2

1.4.2 Linear Models of Resonant Power Transfer

The following derivations are a combination of the ‘reflected load theory’ analysis and the ‘lumped circuit theory’ analysis. See [28] to understand how these two methods

31 along with the ‘coupled mode theory’ analysis are in agreement on the efficiency of a resonant inductive wireless system.

The Receiver has a Parallel Resonant Tank

Figure 1-6 below shows a linear model of a resonant inductive system with a parallel resonant tank for the receiver [2]. The rectifier and buck converter have been con- verted into an equivalent linear resistor so that a basic understanding of the system can be had. Without a fundamental understanding of the system impedances, it is not possible to design a suitable power transfer system. The dependent voltage sources,

푀12 and 푀21, represent the voltages produced in each coil due to the time varying flux from the other. Their values are accordingly: 푉12 = 푗푤퐼2푀 and 푉21 = 푗푤퐼1푀

Figure 1-6: Linear Model with a Parallel Receiver Tank

The current 푖2 in the receiver tank can be written as follows:

−푗푤푀푖1 −푗푤푀푖1 푖2 = = 1 푍2 푗푤퐿2+푅2+ ‖푅퐿푎푐 푗푤퐶2

The voltage 푉2 will then be:

1 푅퐿푎푐 푉2 = 푖2푍표푢푡 = 푖2( ‖ 푅퐿푎푐) = 푖2 푗푤퐶2 푗푤푅퐿푎푐퐶2+1

The dependent voltage source on the transmitter side can now be written as:

2 2 푤 푀 푖1 푉12 = 푗푤푀푖2 = 1 푗푤퐿2+푅2+ ‖푅퐿푎푐 푗푤퐶2 32 The impedance 푍1 on the primary side is the impedance seen by the dependent voltage source, equaling the sum of the passive elements.

1 . 푍1 = 푗푤퐿1 + 푅1 + 푗푤퐶1

The current 푖1 can then be written as:

푉1−푉12 푖1 = 1 푗푤퐿1+푅1+ 푗푤퐶1 The current gain across the gap is also worth noting:

푖2 = −푗푤푀 푖1 푍2

With these relations the input voltage 푉1 and output Voltage 푉2 can be related using a feedback block diagram such as shown in Figure 1-7 [2].

Figure 1-7: Feedback Block Diagram for the Linear Model

Looking into the primary resonator from 푉1, the input impedance will be the sum of the passive components and a reflected impedance due to the dependent source 푉12 with the reflected impedance being:

2 2 2 2 푉12 푗푤푀푖2 푗푤푀 −푗푤푀푖1 푤 푀 −푠 푀 푍푟푒푓푙 = = = ( ) = = 푖1 푖1 푖1 푍2 푍2 푍2

The input impedance can then be written as:

푤2푀 2 푍푖푛 = 푍1 + 푍푟푒푓푙 = 푍1 + 푍2

Noticing that the loop transfer function of the block diagram in Figure 1-7 is:

1 1 −푠2푀 2 푤2푀 2 퐿푠 = (푗푤푀) (−푗푤푀) = = 푍1 푍2 푍1푍2 푍1푍2 33 The input impedance can then be simplified to:

푍푖푛 = 푍1 + 푍1퐿푠

Because near field resonant wireless power systems are usually operated around

the resonant frequency 휔0 where both the source and load networks resonant, i.e. √ √ 휔0 = 1/ 퐿1퐶1 = 1/ 퐿2퐶2, the input impedance can be simplified. [3] Specifically

푍1 = 푅1 at resonance and 푍2 = 푅2. This makes the equation above reduce to:

2 2 2 푤 푀 푘 푤퐿1푤퐿2 2 푍푖푛 = 푅1(1 + ) = 푅1(1 + ) = 푅1(1 + 푘 푄1푄2) 푅1푅2 푅1푅2

2 The term 푚 = 푘 푄1푄2 is known as the modulation index. In impedance mod- ulation, the data to be transmitted changes the quality factor 푄2 of the network, thereby modulating the voltage across the source network via the change in reflected

impedance. The amount of modulation is maximized by making 푄2 zero in one state and and then maximized in the other state. [3] In a system, such as the one imple- mented in this paper, where the transmitter drive frequency adjusts to the changing

resonant point, both 푄1 and 푄2 will change with impedance modulation. The trans- mitter driver is described in Section 1.5.2.

Because the loop transfer function 퐿푠 is proportional to the square of the coupling

factor, it can be seen now that the input impedance is dominated by 푍1 for low

coupling factors and then it is dominated by the reflected impedance, 푍푟푒푓푙, for high coupling factors.

Finally, the current in the secondary circuit, 푖2, and the output voltage 푉2, can be written by using either the feedback block diagram or by combining the equations expressed above:

푠푀 푗푤푀 푍1푍2 푍1푍2 푗푤푀 푠푀 푠푀 푉1 −푖2 = 푉1 = 2 푉1 = 2 2 푉1 = 2 2 푉1 = 퐿푠+1 푤2푀 +1 푤 푀 +푍1푍2 −푠 푀 +푍1푍2 푍2 푍퐼푁 +푍푟푒푓푙 푍1푍2

푠푀 푅퐿푎푐 푉2 = −푖2푍표푢푡 = 2 2 푉1 −푠 푀 +푍1푍2 푠푅퐿푎푐퐶2+1 34 Critical Coupling: Maximum Power Transfer

For a given load resistance, the optimal or critical coupling can be found for which the current or voltage transfer function and thus power received is maximized. As shown in [2], the optimal k is found by differentiating the equation above with respect to k and finding its zeros. The result is that the maximum power will be transferred when the loop transfer function equals 1. This is also when the reflected impedance,

푍푟푒푓푙, is equal to the impedance 푍1, so that the total input impedance 푍퐼푁 is equal to 2 · 푍1. This result agrees with the general maximum power transfer theorem that states that for maximum power transfer the source impedance should match the load impedance. This can be understood by considering that when k is small, the voltage transfer function is small because there is little coupling of the current in the primary to the dependent voltage source in the secondary; when k is large, the input impedance seen in the primary increases as k increases such that the current in the primary reduces, decreasing the dependent voltage source 푉21 and thus the voltage transfer function. However, the drawback is that the maximum efficiency at the critical coupling point is only 50%, and in practice is usually much lower. [2]

The Receiver has a Series Resonant Tank

The linear circuit in Figure 1-8 shows the same circuit as Figure 1-6 except with a series resonant tank on the receiver side instead of a parallel resonant tank. The derivation would follow in a similar way.

Figure 1-8: Linear Model with a Series Receiver Tank

35 The difference in this case is that the impedance 푍2 seen by the dependent voltage 1 source 푉21 has changed with 푍2 = 푗푤퐿2 + 푅2 + + 푅퐿푎푐. However, the derived 푗푤퐶2 equations will have the same form so that again the receiver tank current 푖2 and output voltage 푉2 can be stated:

푗푤푀 푠푀 푠푀 푉1 −푖2 = 2 2 푉1 = 2 2 푉1 = 푤 푀 +푍1푍2 −푠 푀 +푍1푍2 푍2 푍퐼푁 +푍푟푒푓푙 푠푀 푉2 = −푖2푍표푢푡 = 2 2 푉1푅퐿푎푐 푠 푀 +푍1푍2

Typical Load and Coupling Values

So far the load has been modeled as an effective resistance load. In reality, the load includes a rectifier with a buck converter. Deriving a linear model of the loadis detailed in Section 2.1. For now, suffice it to say that the effective load can take a value in the range of about 10Ω푠 to 100Ω푠. In order to compare the system to the stated range of the LTC4125, the majority of the measurements in this paper were taken for coupling factors k = 0.1 to k = 0.6. See Section 2.2.3 and Chapter 7 (Results) for discussion on farther distances.

1.4.3 Voltage Transfer Functions and Peak Splitting

The fundamental equations derived above can give some interesting results when plotted for varying loads and coupling factors. Because the reflected impedance is affected by both the coupling factor and load value, the system transfer functions are heavily affected by the coupling factor and load value. Of critical importance is that for a constant load, as the coupling factor increases there is a point at which the resonant frequency of the system splits into two resonant frequencies that then continue to move further apart. The system will then have its peak power transfer and peak efficiency at frequencies other than the original natural resonant frequency. This effect is shown in the following graphs below for the range of load and coupling factors experienced by the system. The values used in the near resonant simulations correspond to those used in the system and given in Table 1.2:

36 Power Transmitter Side Power Receiver Side

퐿1 25.2휇퐻 퐿2 44.30휇퐻

푅1 0.1342 Ω 푅2 1.2707 Ω

퐶1 100.95nF 퐶2 49.905nF

퐶1퐸푆푅 0.0536 Ω 퐶2퐸푆푅 0.1435Ω

푓0 99.78 kHz 푓0 107.04 kHz

푄1 84.13 푄2 21.07 Table 1.2: Resonant Circuit Values

Parallel Resonant Receiver Tank

Figure 1-9: Parallel Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors

As can be seen for the parallel resonant case, separate peaks are present for high coupling and loads.

37 Figure 1-10: Parallel Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors

Figure 1-11: Parallel Resonant Voltage TF vs. Frequency for R = 100 Ohms and Various Coupling Factors

Root Locus

Of further interest is the relative magnitude of the split peaks. As noted in [2], the peaks can be understood by looking at the root locus of the loop transfer function,

38 퐿푠. The root locus shows how the location of the poles move under positive feedback as the gain parameter 푘2 is increased from zero to infinity. Because of the difference in parasitics and therefore , the primary and secondary poles are separated even for the unloaded case. The unloaded case is shown first in Figure 1-12. Now if a sizable load is added to the secondary as in Figure 1-13, the secondary poles are damped further and the poles start farther apart. As the gain factor, or coupling, is increased the poles start to move towards each other before moving farther apart. It is interesting to note that the relative magnitude of the peaks can be inferred by observing how the poles move in relation to the imaginary axis. Whichever of the poles has a smaller angle relative to the imaginary axis will have less damping and therefore a higher peak. As can be seen and as noted in [2], the lower frequency pole is usually less damped and is associated with the higher peak.

Figure 1-12: Unloaded Root Locus for a Parallel Resonant Receiver

39 Figure 1-13: Root Locus for a Parallel Resonant Receiver with R = 100

Series Resonant Receiver tank

As can be seen in the graphs below for the series resonant receiver case, separate peaks are present for high coupling and large loads. (Compare the parallel case where they separate for high coupling and light loads).

40 Figure 1-14: Series Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors

Figure 1-15: Series Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors

41 Figure 1-16: Series Resonant Voltage TF vs. Frequency for R = 100 Ohms and Various Coupling Factors

42 Root Locus

Figure 1-17: Root Locus for a Series Resonant Receiver with R = 10

Off Resonant Voltage Transfer Functions

The above graphs in which the receiver and transmitter are tuned to resonance will be compared to the graphs below where the transmitter and receiver are not tuned to the same resonant frequency. When the transmitter and receiver are not tuned to resonance, the LTC4125 (See Section 1.5.2) should still find the effective resonant frequency - the frequency at which the input impedance is purely real. This frequency will depend on both the coupling factor and load level.

Parallel Off-Resonant Receiver tank

43 Figure 1-18: Parallel Off-Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors

Figure 1-19: Parallel Off-Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors

44 Figure 1-20: Parallel Off-Resonant Voltage TF vs. Frequency for R = 100 Ohmsand Various Coupling Factors

45 Series Off-Resonant Receiver Tank

Figure 1-21: Series Off-Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors

Figure 1-22: Series Off-Resonant Voltage TF vs. Frequency for R = 50 Ohms and Various Coupling Factors

46 Figure 1-23: Series Off-Resonant Voltage TF vs. Frequency for R = 10 Ohms and Various Coupling Factors

Comparing Resonant vs. Off-Resonant Voltage Transfer Functions

Based off of the graphs above for both resonant and off-resonant models, the following points should be noted. In general the resonant model has its peak gain at lower couplings compared to the off-resonant model. Secondly, the peaks start to split for slightly weaker coupling factors in the resonant case than the off-resonant case. However both of these differences seem to be relatively small. Notice also thatat certain coupling factors and load values, the transfer function becomes very flat. As will be discussed in Chapter 3 (Communication) it is at these places where the communication based on modulated can have a seriously attenuated SNR. Finally the most important take away is that as the coupling changes the impedance of the circuit changes dramatically and thus the optimal load resistance changes as well. Therefore, as will be detailed in Chapter 2, what is critical for a versatile wire- less power transfer system is to have control over the size of the load resistance in order to maintain high efficiency and/or power transfer for a variable coupling level.

47 1.4.4 Linear Model Efficiency Derivation

The energy of the power transmitter can be dissipated in one of three locations: the power transmitter parasitic loss elements, the power receiver parasitic loss elements, or the load. The efficiency of the system can more generally be broken down intotwo parts. [2], [19] et al. The input power will first be divided between the power coupled to the secondary side and the power dissipated in the primary side parasitics. The coupled secondary power will then be dissipated in the secondary side parasitics or be consumed in the load. These two efficiency factors are commonly referred toas 휂푘 and 휂2.

Transmitter Side Efficiency: 휂푘

On the primary side the power is split between either coupling to the load or being dissipated as parasitic losses in the passive components. This can be written as follows:

푃 퐼2푍 푍 푐표푢푝푙푒푑 1 푟푒푓푙 푟푒푓푙 푍1퐿푠 퐿푠 . 휂푘 = = 2 2 = = = 푃퐼푁 퐼1 푍푟푒푓푙+퐼1 푍1 푍푟푒푓푙+푍1 푍1퐿푠+푍1 퐿푠+1 As can be seen, the primary side efficiency is increased as the loop transmission

퐿푠 is increased. If both the transmitter and receiver circuits are operating at the resonant frequency then the loop transmission term can be simplified. Specifically, the impedances 푍1 and 푍2 will be purely real. On the transmitter side, 푍1 will reduce to 푅1 and on the receiver side 푍2 will reduce to 푅2 + 푅퐿푎푐,푠푒푟푖푒푠. For the parallel receiver tank, 푅퐿푎푐,푠푒푟푖푒푠 will be the equivalent series load resistance found by doing 2 푍0,2 a parallel to series transformation of 푅퐿푎푐. The resulting value will be , where 푅퐿푎푐 √︀ 푍0,2 = 퐿2/퐶2. For the series receiver tank, 푅퐿푎푐,푠푒푟푖푒푠 will simply be 푅퐿푎푐. [2], [19] Therefore at resonance, the loop transmission can be rewritten as:

2 2 −푠 푀 2 휔퐿1 휔퐿2 퐿푠 = = 푘 ( )( ) 푍1푍2 푅1 푅2+푅퐿푎푐,푠푒푟푖푒푠 The secondary side loaded quality factor should now be defined. The total Qon the receiver side will be the parallel combination of the undamped quality factor 푄2 and the loading quality factor 푄퐿표푎푑:

48 푄′ = 휔퐿2 2 푅2+푅퐿푎푐,푠푒푟푖푒푠

Now the loop transmission can be reduced to:

2 휔퐿1 휔퐿2 2 ′ 퐿푠 = 푘 ( )( ) = 푘 푄1푄 푅1 푅2+푅퐿푎푐,푠푒푟푖푒푠 2

Finally the coupling efficiency at resonance can be reduced to:

푘2푄 푄′ 1 2 . 휂푘 = 2 ′ 1+푘 푄1푄2

However, when the system is not at resonance then the absolute value of the loop transmission should be used because it is the magnitude of the impedance that will determine how much current, in magnitude, is oscillating in the primary circuit and therefore the magnitude of voltage that is dropped across the reflected impedance determines the amount of power that is coupled to the secondary side. An important note is that when the efficiency is actually calculated, the specific operating frequency is needed. Away from resonance the coupling efficiency should thus be:

휂 = |퐿푠| . 푘 1+|퐿푠|

If the operating system frequency is near the resonant frequency of the tanks then

푍1, and 푍2 should be approximately real and have magnitudes approximately equal to their resistive components.

Receiver Side Efficiency: 휂2

On the Secondary Side, the power is split between the intrinsic parasitic losses and the power going to the load. The energy efficiency for each cycle is then the fraction of energy going to the load divided by the total energy being consumed in both the load and the parasitic resistances. This portion of the efficiency calculation is the same for the resonant and non-resonant cases.

퐸퐿표푎푑 휂2 = 퐸퐿표푎푑+퐸퐿표푠푠

which can be rearranged to:

49 1 휂 = 퐸퐿표푠푠 2 1 + 1 퐸퐿표푠푠 퐸퐿표푎푑 Because the energy stored in the secondary side resonant system is constant during steady state, the efficiency can be re written as:

Energy Stored 퐸퐿표푠푠 푄2 휂2 = Energy Stored Energy Stored = + 푄2+푄퐿표푎푑 퐸퐿표푠푠 퐸퐿표푎푑

휔퐿2 Where 푄퐿표푎푑 = . Or for the parallel tank case without the parallel to 푅퐿푎푐,푠푒푟푖푒푠 series transformation: 푄퐿표푎푑 = 휔푅퐿푎푐퐶2.

Total Efficiency

This gives a total efficiency at resonance for this basic model of: [2], [19]

2 ′ 푘 푄1푄2 푄2 휂 = 휂푘휂2 = 2 ′ · 1+푘 푄1푄2 푄2+푄퐿표푎푑 Away from resonance the total efficiency is:

휂 = |퐿푠| · 푄2 1+|퐿푠| 푄2+푄퐿표푎푑 The total efficiency equation shows that it is important to have high unloaded

quality factors 푄1 and 푄2. What is remarkable about resonant wireless power transfer

is that so long as the quality factors 푄1 and 푄2 are high and 푄퐿표푎푑 is a reasonable value, the efficiency can remain quite high for very low coupling factors. Thereis

however a trade-off in the two efficiency terms regarding the valueof 푄퐿표푎푑. The

coupling efficiency is increased as 푄퐿표푎푑 is increased but the secondary efficiency is

increased as 푄퐿표푎푑 is decreased. Remember that the parallel resonant tank has a high

푄퐿표푎푑 for small loads (big 푅퐿,푎푐) and the series resonant tank has a high 푄퐿표푎푑 for

large loads (small 푅퐿,푎푐). Figure 1-24 and Figure 1-25 show simulated efficiencies for both the parallel and series receiver case when operating at resonance. The graphs vary over the system

coupling range (푘 = 0.1 − 0.6) and effective load resistance range (10Ω푠 to 100Ω푠) mentioned above. The most efficient operating point is with a relatively small load resistance.

50 The parallel resonant case suffers from low efficiency at large loads but has aflatter efficiency curve for lighter loads. The reason being that a large load severely damps the Q of the receiver. (Q2L) On the other hand, the series resonant case reaches its peak efficiency at larger loads and suffers at lighter loads. It should benoted that because of the pole splitting, the system will not operate at resonance for all loads and coupling factors and so therefore these models are not perfectly accurate. Better models could and should be made that actively adjust the drive frequency in the computations based on the input impedance seen by the source for the various coupling and loading conditions.

Figure 1-24: Parallal Resonant Efficiency

51 Figure 1-25: Series Resonant Efficiency

Efficiency: Parallel vs Series Resonance

Figure 1-26 illustrates that there is a load resistance for which the efficiencies are equal. Below this value the series resonant tank is more efficient and above this value the parallel resonant tank is more efficient. What is interesting is that this cross over point is independent of coupling. Based on our circuit values the cross over point is 30 Ohms. Importantly, this effective resistance is greater than the effective resistance of the normal operating range for battery charging. Figure 1-27 shows the effective resistance vs battery power based on the derivation in section 2.1.2. Consider that for a charging current of 400mA and a battery voltage of 3.5V, the battery power is 1.4 Watts. Further, it is most desirable to be efficient during the high current charging times when the effective load resistance is lowest. Therefore it was decided thata series resonant receiver tank should be used for this implementation.

52 Figure 1-26: Parallel vs Series Resonant Efficiency

Figure 1-27: Effective Resistance of Battery Charging for Various Rectified Voltages

53 Efficiency: Off-Resonance vs Resonance

The decision was made to operate the system near resonance as opposed to purposely away from resonance. Although this decision could have been given more thought and measurements it is generally accepted in academia that the secondary circuit is most efficient when operated at resonance. [3] When the system is operated at resonance the lowest impedance path is provided for the flux to couple to the secondary side load. As was shown in the efficiency graphs above, there is an ideal load value for optimal efficiency. Therefore it may be that for a fixed load on the secondary side and a fixed coupling factor between the coils, operating off-resonance would bemore efficient. This would be because the effective impedance seen by the inputwould be more efficient for an off-resonant circuit. However, as will be detailed inChapter 2, the purpose of this thesis was to add feedback communication to the system in order for it to actively adapt to the most efficient operating point by changing the effective load impedance on the secondary side. With this capability it shouldbe more efficient to operate at resonance, but as stated above this could be investigated further. Although I did do some measurements comparing the efficiency of resonance vs non-resonance to verify this decision, more measurements could be done.

1.5 LTC Wireless Charging Options

1.5.1 LTC 4120

The initial setup was built around the LTC4120 which is a wireless power receiver and 400mA buck battery charger. Figure 1-28 from the online datasheet shows the typical application circuit. The current version of the LTC4120 uses a Dynamic Harmonization Control (DHC) technique which modulates the resonant frequency of the receiver tank to automatically adjust both the power transmitted and received in order to provide an efficient solution for wireless charging battery-powered devices. DHC modulates the impedance of the resonant receiver to regulate the voltage at the input to the LTC4120. When the input voltage to the LTC4120 is below a set

54 point, the LTC4120 allows more power to appear at the receiver by tuning the receiver resonance closer to the transmitter resonance. If the rectified input voltage exceeds the set-point, the LTC4120 tunes the receiver resonance away from the transmitter, which reduces the power available at the receiver. The amount that the input power increases or decreases is a function of the coupling, the tuning capacitor the receiver coil and the operating frequency. [29]

Figure 1-28: LTC4120 Diagram

In the current version of the LTC4120, the DHCP receiver resonance shift is the only way to change the capacity of the transmitted power directly, and therefore the amplitude and impedance of the resonant tank is solely dependent on the physical coupling, battery power draw and the selection of the two possible tuning positions of the receiver tank.

Adding a communication channel between the transmitter and receiver should improve the efficiency and versatility of the system. By knowing the LTC4120 input rectified voltage, battery voltage and battery charging current, the transmitter power capacity can be controlled directly. This should both improve efficiency and make the system more adaptive to variable and increasing distances between the transmitter and receiver. Specifically this should allow the range of the transmitted power tobe increased beyond the current specifications.

55 1.5.2 LTC 4125

The LTC4125 is a new Linear auto-resonant driver for a wireless power transmitter that was used in this thesis to drive the transmitter coil. Its output follows the resonant frequency by ensuring that the drive current is in phase with the drive voltage, thus operating at the frequency when the input impedance is purely real. Its output drive level can be easily adjusted and controlled by driving the pth1 and pth2 pins (pulse width pins). The pulse width or duty cycle extends from 0 to 50% with a linear input mapping of 0 to 2.5 Volts. A noteworthy point is that for the situation shown above in section 1.4.3, when the transfer function peaks are splitting, the LTC4125 appears to drive the system at the frequency of the higher peak. When the peaks split there are two frequencies for which the input impedance seen by the driver is purely real and because of the way in which the driver finds the frequency of purely real impedance, it seems to lock onto the higher frequency. However, at high couplings or high loading when the peaks are most distinct and the lower frequency peak is much higher, it appeared that the driver would jump frequencies to the lower frequency at some point. This behavior is something that I did not have time to investigate further.

56 Chapter 2

Rectifier Modeling, Initial Data Measurements and Thesis Objectives

This chapter will build off of the resonant wireless power models from Chapter 1.A linearized model of the rectifier will be developed along with the effective impedance transformation of the buck converter. A full system model will then be presented followed by initial data measurements and identification of the thesis objectives. The measurements were used to both verify the linear model and establish thesis objec- tives.

2.1 Rectifier Model

The need for a rectifier makes the charging circuit nonlinear. However, developing an equivalent linear model for the rectifier is helpful in understanding how the rectifier affects the linear circuit developed so far. I discovered that a resonant dc-dc converter is very similar in topology to the series resonant wireless converter. In Figure 2-1, the resonant dc-dc converter has a AC driving a resonant tank network that is then rectified to power a DC load. Because the AC square wave input isfiltered by the resonant tank, the circuit is approximately the same as the secondary side of the series resonant wireless power circuit. Of particular relevance was the use of a rectifier connected to a resonant tank in both circuits.

57 Figure 2-1: Resonant DC-DC Converter

The effective resistance of the full bridge rectifier is derived in [30], [31], [32]. Neglecting the voltage drops across the diode they get 8 . However 푅푒푓푓 = 휋2 푅퐿표푎푑 a half bridge rectifier was used in this thesis because it more suitably transforms the battery charging load to an efficient effective resistance for the series resonant receiver case. As will be shown, the impedance it presents to the resonant tank is about 1 of what a full bridge rectifier would present. The effective resistance ofa 4 half bridge rectifier can be derived in a similar way to that of a full bridge rectifier.

The secondary side is shown in Figure 2-2 with 푅퐿표푎푑 designating the effective input resistance of the buck converter.

Figure 2-2: Power Receiver Side with a Half Bridge Rectifier

At steady state, it must be that the time average of the current 푖푅 going into the rectifier is equal to the DC load current, 퐼퐿표푎푑 so that the average current of the

58 capacitor 퐶퐿표푎푑 is 0. Assuming that the current 푖푅 is approximately sinusoidal, then the following equation can be written:

¯ 1 ∫︀ 푇/2 퐼푅푝푒푎푘 퐼퐿표푎푑 =< 퐼푅(푡) >= 푇 0 퐼푅푝푒푎푘푠푖푛(푤푡)푑푡 = 휋

The voltage 푉푅(푡) will approximate a square wave with a voltage of a diode drop higher than the output voltage when D1 is conducting and a voltage of minus a diode drop when D2 is conducting. With the assumption that the current is approximately a single sinusoid due to the resonant tank filtering, the fundamental component of

푉푅(푡) will be the only component that contributes to the output power. During the positive cycle when D1 is conducting, the effective voltage before the rectifier will be:

4 푉푅1+ = 휋 (푉퐿표푎푑 + 푉퐷1)

With 휋퐼퐿표푎푑 , the effective resistance looking into the rectifier during the 퐼푅푝푒푎푘 = 2 positive half cycle while D1 is conducting is:

푉푅1+ 4(푉퐿표푎푑+푉퐷2) 4 (푉퐿표푎푑+푉퐷2) 4 (푉퐿표푎푑+푉퐷2) 푅푒푓푓+ = = 2 = 2 = 2 푅퐿표푎푑 퐼푅푝푒푎푘 휋 퐼퐿표푎푑 휋 퐼퐿표푎푑 휋 푉퐿표푎푑

During the negative half cycle diode D2 conducts and the rectifier voltage is ap- proximately a square wave with amplitude equal to minus the diode drop of D2. The effective resistance during the negative half cycle will therefore be:

4 (푉 ) 푉푅1− 푝푖 퐷2 4 푉퐷2 4 푉퐷2 푅푒푓푓− = = = 2 = 2 푅퐿표푎푑 퐼푅푝푒푎푘 휋퐼퐿표푎푑 휋 퐼퐿표푎푑 휋 푉퐿표푎푑

The resonant tank will be loaded by the average of the two effective resistance values. It should be noted that for any duty cycle drive of the LTC4125, a sinusoid is produced in the transmitter tank, and therefore the on time of the two diodes in the rectifier should be equal. Assuming an equal voltage drops across the diodes, the total effective resistance will be given by the equation below.

푅푒푓푓++푅푒푓푓− 1 4 (푉퐿표푎푑+푉퐷1) 4 푉퐷2 푅푒푓푓 = = ( 2 푅퐿표푎푑 + 2 푅퐿표푎푑) 2 2 휋 푉퐿표푎푑 휋 푉퐿표푎푑 59 2 푉퐿표푎푑+2푉퐷 푅푒푓푓 = 2 ( )푅퐿표푎푑 휋 푉퐿표푎푑

If the diode drops are neglected as they were in the derivation in [30], [31], [32], then the effective resistance of the half bridge rectifier is actually 1 that of a full 4 bridge rectifier. I was able to check this predication for the half bridge rectifier in LTspice and simulations showed that the prediction is correct for a load resistance of up to about 100 Ω푠. Above that point, the current waveform is too much of a distorted sinusoid for the assumptions made above to be valid.

2.1.1 Buck Converter

The impedance change due to the buck converter has to also be considered. The effective input impedance to the buck converter is the following:

푉푏푎푡푡퐼푏푎푡푡 = 퐼푏푢푐푘푉푏푢푐푘 * Efficiencybuck

푉푏푎푡푡퐼푏푎푡푡 퐼푏푢푐푘 = 푉푏푢푐푘*Efficiencybuck

2 푉푏푢푐푘 푉푏푢푐푘 푅퐵푢푐푘 = = * Efficiencybuck 퐼푏푢푐푘 푉푏푎푡푡퐼푏푎푡푡

2.1.2 Effective Load

The total effective load can now be found by combining the previous two derivations:

푉 2 2 푉푏푢푐푘+2푉퐷 푏푢푐푘 Efficiency 푅푒푓푓 = 2 ( ) * buck 휋 푉푏푢푐푘 푉푏푎푡푡퐼푏푎푡푡

The important takeaway is that the effective load resistance is both scaled upby the buck converter and also scaled down by the rectifier. But it should be noted that if the rectified voltage is greater than about 2 volts then the effective load resistance is greater than the battery charging resistance. Figure 2-3 shows the equivalent circuit model now with a rectifier and buck converter.

60 Figure 2-3: Wireless Power Circuit with a Rectified and Bucked Load

2.2 Initial Data Measurements

2.2.1 Verifying the Linear Model with Data Measurements

I wanted to first verify the linear model developed in Section 1.4 by comparing mea- sured values to predicted values. The graphs below show the predicted primary tank voltage compared to the measured primary tank voltage for various AC loads and input drives. The predictions and measurements were made for the series resonant receiver tank because this was the topology used in the system. The predictions of the primary tank voltage were made by measuring the AC voltage across the load resistor, knowing the circuit parameters, and then using the model to predict the pri- mary side tank current and then voltage. From Section 1.4.2, the equation relating the secondary current to the primary current is given below along with the primary tank voltage as a function of the primary tank current. If the relation between the currents is verified then then the rest of the model follows from elementary circuit equations. As can be seen in Figure 2-4, the predictions are a good match to the measurements.

푖1 = 푍2 푖2 −푗푤푀

푍0 √︀ 푉Primary Tank = = 퐿/퐶푖1 푖1

61 Figure 2-4: Linear Model Verification

2.2.2 AC Load Efficiency

Figure 2-5 is a plot of the efficiency vs output power for three different coupling factors. Plotted is both the predicted efficiency for a series resonant tank basedon the equations from Section 1.4.4 and the measured efficiency for a series resonant tank. The measured efficiency, although having the same shape as the predicted efficiency, is quite a bit lower. Possible sources of error in the prediction are thelosses in the power transmitter switches, the mismatch in resonant frequencies between the transmit and receive tanks and unaccounted parasitic losses. Understanding the gap between the predicted and measured efficiency would be something to investigate further.

62 Figure 2-5: Predicted vs Measured Efficiencies for an AC Load

2.2.3 Variable Rectified Voltage Measurements

As was noted in Section 1.4.4, the efficiency of the system is strongly dependent on both the coupling factor and load level of the secondary circuit. Although model- ing and simulations were done to understand the theory of resonant power transfer (Section 1.4) and the effects of a rectifier (Section 2.1), it was critical totakemea- surements of the actual system, with a rectified DC load, to understand the possible advantages of integrating feedback via a communication link.

Efficiency vs Output Power for Various Rectified Voltages

Using the series resonant tank of the LTC4120 and half bridge rectifier, I was able to externally regulate the rectified voltage. I then varied the input power tothe LTC4125 for various rectified voltages and coupling factors to generate the following graphs. These figures confirm the important theoretical results in Chapter 1,that the efficiency of the system is highly dependent on both the coupling and theloading of the secondary side. In particular, at high coupling levels, the loading should be large in order to obtain relatively high efficiency. With a rectified voltage load, it

63 is shown in Figure 2-6 that having a lower rectified voltage is more efficient when the coupling is high and the battery charging rate is low. This is because a lower rectified voltage transforms the battery charging impedance down to a lower effective resistance than that of a higher rectified voltage. The reverse situation is true andis shown in Figure 2-7. Namely, that at loose couplings and high battery charging rates it is more efficient to have a high rectified voltage.

Figure 2-6: Efficiency vs Output Power for Various Rectified Voltages with k=0.41

64 Figure 2-7: Efficiency vs Output Power for Various Rectified Voltages with k=0.13

Output Power vs Rectified Voltage for Various Input Duty Cycles

These next graphs show how for a given input duty cycle command to the LTC4125, the output power changes with the rectified voltage. The effects of these graphs will be noticed during the implementation of the max efficiency searching algorithm described in Chapter 6. As described in Chapter 6, the rectified voltage will be switched up and down, and thus according to these graphs, there will be a jump in the output power for a fixed coupling and input duty cycle command. What canalso be seen is that in general for higher rectified voltages, more power can be sent with a fixed input duty cycle command. This effect helps to extend the distance rangeof the system.

65 Figure 2-8: Output Power vs Rect V for Various Input Duty Cycles and K = 0.13

Figure 2-9: Output Power vs Rect V for Various Input Duty Cycles and K = 0.188

66 Figure 2-10: Output Power vs Rect V for Various Input Duty Cycles and K = 0.41

67 Output Power vs Duty Cycle for Various Rectified Voltages

The graphs below show how for a fixed rectified voltage and coupling factor, the output power changes as the input duty cycle is ramped up and down. These graphs therefore show the input to output transfer function between the LTC4125 duty cycle and the output power for a given coupling. For duty cycles around and above 80% of the max (Vpth = 2.0V) the output power is flat. Therefore the upper limit on output power vs coupling can be seen. As mentioned above and seen more clearly now, is that having a higher rectified voltage directly increases the amount of power that can be sent at a given coupling level. By being able to change the rectified voltage, the distance range is extended.

Figure 2-11: Output Power vs Duty Cycle for Various Rect V and k = 0.188

68 Figure 2-12: Output Power vs Duty Cycle for Various Rect V and k = 0.41

Efficiency vs Rectified Voltage for Various Input Duty Cycles

These graphs below show how for a given input duty cycle, the efficiency changes as the rectified voltage changes. Though not as telling as the efficiency vsoutput power graphs, they do help to understand how important the rectified voltage is for the efficiency when operating in different regions of duty cycle inputs. Atlowduty cycles, it is much more efficient to have a low rectified voltage but at high duty cycles it is much preferred to have a high rectified voltage.

69 Figure 2-13: Efficiency vs Rect V for Various Input Duty Cycles and K=0.41

Figure 2-14: Efficiency vs Rect V for Various Input Duty Cycles and K=0.28

70 Figure 2-15: Efficiency vs Rect V for Various Input Duty Cycles and K=0.188

Figure 2-16: Efficiency vs Rect V for Various Input Duty Cycles and K=0.13

71 2.3 Identification of Thesis Objectives

Based on the previous modeling in Chapter 1 and the measurements in here in Chapter 2, it was decided that it should be valuable to implement feedback control over the rectified voltage during a battery charging cycle. By having such control, itwill be possible to actively change the load impedance seen by the transmitter to the maximum efficient point for a given coupling and battery charging rate. In addition, the distance range of power transfer should also be extended. In order to both set the charging rates and find the optimal impedance point, it is necessary tohave some form of communication between the coils. The implemented communication is described in detail in Chapter 3. The experimental goal of this thesis was to therefore design and implement a working communication channel embedded within the power transfer channel in order to charge batteries efficiently over a versatile and extended range of operating conditions.

72 Chapter 3

Communication

3.1 Communication overview

There are a number of ways to set up a communication link for near field wireless charging, all of which can be categorized as either a separate communication link or one that shares the same channel as the transmitted power. See Section 1.3.2 This paper describes a means of communication via the power transmission chan- nel. This was decided in favor of a separate channel because of the minimal added components and the low communication bandwidth needed. It was determined that communication would be needed in both directions in order to facilitate the necessary control (see Chapter 6). As will be described in detail in Chapter 6, the majority of the data is sent from the power receiver to the power transmitter. This will be referred to as the uplink communication. Communication in the other direction, from the power transmitter to the power receiver will be referred to as downlink communication and needed considerably less bandwidth. The Figure 3-1 shows this designation. The uplink communication will be described first, followed by the downlink communica- tion. Although the same modulating protocol is used in both directions, the means by which it is implemented in circuitry, the decoding methods, and message headers is different.

73 Figure 3-1: Basic Communication Diagram

3.2 Description of the Uplink Communication: Power Receiver to Power Transmitter

The data that needs to be sent from the power receiver to the power transmitter is the following: battery voltage, battery current, and rectified voltage. Data will be modulated into the power transmission by modulating the resonant frequency of the receiver tank as initially presented in Section 1.3.2. This is done by adding and removing a capacitor to the receiver tank according to the drive state of the encoded signal. The result of the modulated capacitor is to modulate the Qs of the system and therefore modulate the energy stored in the resonant tanks and their associated voltage peaks. The capacitor modulation circuit is shown in Figure 3-2 The amplitude of the signal is dependent on the value of the modulated capacitor and the power transmission level. In order to encode and decode signals after some hardware based signal processing, an Atmel microprocessor was used.

74 Figure 3-2: Capacitor Modulation Circuit

3.2.1 Differential Manchester Encoding

Because the data transmission has only a single channel, the data clock has to be embedded within the data. Differential Manchester Encoding (DME) Protocol was used because its data and clock signals are combined to form a single 2-level self- synchronizing data stream. [33], [34] A short example of the protocol is shown below in Figure 3-3.

Figure 3-3: Differential Manchester Encoding

As a line code, DME has its data clock embedded within the data stream. Ac- cordingly, DME guarantees that there will be at least one signal transition every data

75 bit. There are two possible ways to do DME. The first is to have a transition in the encoded signal at every rising edge of the data clock. Then at the falling edge of the data clock, if the data bit to be sent is a 1, then the encoded signal transitions again. If the data to be sent is a 0, then there is no transition in the encoded signal. The other possibility is to switch the order of clock and data transitions. In this case the encoded signal has a transition at every falling edge of the data clock. Now at the rising edge of the data clock, if the bit to be sent is a 1, then the encoded signal has a transition. Otherwise, if the bit to be sent is a 0, then the encoded signal does not transition. [34],[33] The first option is the one used in Figure 3-3 and also theone used in the implemented system. Figure 3-4 shows actual waveforms of the sent signals. The top green waveform shows the data to be sent, either 1 = High, or 0 = Low. The middle blue waveform shows the encoded signal and the bottom pink waveform shows the clock.

Figure 3-4: Screenshot of Communication

As described above, DME is a transition based communication protocol instead of being level based. This has the advantage that for any conceivable string of data, the average voltage level will be 0 and therefore the data can be put through a high pass

76 filter to change the bias points in either the sending or receiving analog circuitry. Another advantage of DME is that detecting transitions is often less error-prone than comparing against a threshold in a noisy environment. [35] The downside to DME is that the possible transition rate (for all 1s in our case) is twice that of the data rate, thereby needing 2x the bandwidth in the analog circuitry compared to the communication rate. Although the transition efficiency is therefore 50 , or 1 bit per % 2 transition, the benefit of sending the clock and having a DC value of 0 justifies its use. [33] Finally, DME was used instead of the more ubiquitous Manchester Encoding scheme, known for its use in Ethernet [36], [35], because it is necessary that the direction of the transitions be irrelevant to the data bit. In Manchester Encoding the polarity of the transition determines the data bit. However with DME, only the presence of a transition is important, not the polarity. Differential coding schemes such as DME will therefore work exactly the same if the signal is inverted (wires swapped). This detail is particularly important in this case because the modulated capacitance may increase or decrease the Qs of the circuit, depending on the coupling and power levels and therefore the transition may be rising or falling. Another advan- tage of DME over Manchester Encoding is that unlike the latter, it does not require a preamble in order for clock synchronization to take place because any data stream has sufficient clock information. Because of this, DME is used in Fast Ethernet. [36]

Clock Recovery and Reading the Data

In order for the power transmitter (in this case the uplink communication receiver) to accurately decode the data it has to be able to distinguish between clock transitions and data transitions in the incoming encoded signal. I was able to do this in the code by starting an internal clock on the receiver end at the first detected transition. It is then assumed that this first detected transition corresponds to a rising edge ofthe transmitter side clock. This clock then runs at four times the expected transmitter clock frequency so that it could detect the transitions (level changes) by sampling in between the transitions. Figure 3-6 shows this.

77 The top waveform in Figure 3-6 is the transmit clock. Notice that on every rising edge of the data clock the encoded signal has a transition. On every falling edge of the data clock is when the encoded signal has a transition if the data bit to be sent is a 1 and does not have a transition if the data bit to be sent is a 0. The 4x clock is started at the first detected edge of the encoded signal. After the end of the firstand third periods the encoded signal is level sampled. By comparing these two readings the value of the data bit can be inferred. The end of the second period the 4x clock corresponds to the falling edge of the transmit data clock. After the end of the third period the 4x clock is stopped and is not started again until the next transition of the encoded signal. Therefore, this recovery method re-syncs with the rising edge of the transmitter clock every data bit. Finally the recovered clock is shown at the bottom and it is in phase with the transmitter clock. Figure 3-5 shows a screen shot of the data decoding happening. The bottom green waveform is the recovered clock. The blue waveform is the transmitter encoded signal and the pink signal shows the sampling.

Figure 3-5: Screenshot of Decoding the Uplink Communication

78 Figure 3-6: Decoding the Uplink Communication

Missed Clock Edges

If the recovery circuitry misses or falsely detects a transition, it should correct itself the next time a 0 bit is sent. This is because the absence of a transition in the encoded signal for a 0 bit at the falling edge of the data clock provides the opportunity for the receiver side detection to detect the next transition accurately as being the true rising edge of the transmitter clock. However, during the correction, one of the bits will be missed causing an error in the reading. This is illustrated in Figure 3-7. In the

79 example of Figure 3-7 the sent data is 11001 but the received data is 1101, missing the second 0 during the correction sequence. Though this will result in the corruption of the data stream, the communication should recover within 67 bits or 67ms in the worst case as the power receiver actively sends the necessary data to reestablish the communication channel. See section 6.3 for more details about corruption of the communication channel and restoring communication.

Figure 3-7: Missed Transition During Decoding

80 Necessary Communication Frequency Precision

In this decoding method, it is required that the frequency of communication is ap- proximately agreed upon. Assuming no time delays due to filtering, so long as the actual frequency of transmission is no less than 2 that of the assumed frequency and 3 not greater than 4 of the assumed frequency then the receiver can correctly read the 3 data. Further, after reading a few bits, the receiver could update its knowledge of the transmitter side frequency based on the length of time between consecutive transmit- ter clock rising edge transition detections. This concept is shown in Figure 3-8 . Note that the extra vertical lines in the encoded signal are to mark the end of the internal 4x clock periods in the receiver decoding algorithm. Further supposing that the assumed frequency is very different than the actual frequency, it would be possible to detect the time 푇푠 between consecutive encoded signal transitions. Because it would not be known if the encoded signal had repre- sented a 1 or a 0, the possible actual frequency could be 1 if the bit was a 1, or 2 푇푠 푇푠 if the bit was a 0. It would thus be possible to eventually assume the correct actual clock frequency. Actively updating the value of the assumed frequency is possible up to the limits of the analog filtering circuitry. Therefore the frequency compliance, or the “lock” range, between the transmitter and receiver is only limited by the analog filtering techniques.

81 Figure 3-8: Communication Frequency Precision Requirements

Data Headers and Error Detection

Although in theory, assuming the transmitter and receiver are in agreement about the communication frequency, the communication should be flawless, this will of course not be in the case. Instead there will be errors in the bits due mainly to changing coupling and power levels. When the coupling and power levels change the effect of capacitor modulation will change, possibly corrupting the data. Accordingly it is not possible to run everything in a deterministic manner but it is necessary to add header bits to the messages. The following criteria is what I found to be necessary for proper control and stability:

1. Error Detection: Detect bit errors so that there are minimum errors in reading the data

2. Versatility: Ability to quickly re-sync communication in the event of corrupted data

82 3. Speed: Sufficiently fast for closed loop control

Although the following scheme could be improved for a higher efficiency, I found it sufficient for the purposes of this paper.

1) Error Detection

As stated above, the necessary data to be sent from the power receiver to the power transmitter is the battery voltage, battery current and the rectified voltage. In addi- tion to these 3 data messages is the data syncing message which is discussed below in the Versatility section. Each of the numerical values is measured with a 12bit ADC on the power receiver side. In order to have a hamming distance of 2 between the 4 message types, I added 4 header bits to each value. These 4 data bits would ensure that messages would be appropriately recognized as either the battery voltage, battery current, rectified voltage or data syncing. To hedge against data corruption within the message I added a single parity bit to detect a single bit error. In addition to the parity bit, digital filtering was used to low pass errors in data readings as much as possible. See section 4.4.2 below on the digital filtering. The parity bit combined with the 4 header bits and the 12 databits made each message 17 bits long.

2) Versatility

As the coupling and power transmission levels change, the communication can become corrupted. Is is therefore necessary to be constantly re-syncing the communication in order to make the system versatile to changes in operating conditions. This is done by sending a data syncing message periodically with the rest of the data. This meant that every 4th message was a message with the sole effect of re-syncing the communication in the event that the communication stream had been broken. As a result, the periodic uplink messaging from the power receiver to the power transmitter was: Data syncing (16 bits - no parity bit), Battery Voltage (17 bits), Battery Current (17 bits), Rectified Voltage (17 bits), repeat. Therefore a total round of data is67

83 bits, corresponding to about 67ms.

3) Speed

The data bit rate was initially set to 1kHz. The modulation scheme is a type of amplitude modulation of the power transmission frequency. With the power trans- mission frequency at approximately 100kHz, a data bit rate of 1kHz is lower than the maximum data rate. Although the data rate could have been increased, it was not a priority for the purpose of this thesis. In addition, the speed of the communication could be increased by making the data communication more efficient. Some ways of doing this would be to only send the changes in the values instead of all 12 bits of data each time. The frequency of re-syncing the data could also be lowered. These changes should be considered in the next design iteration. Please see the final chapter for further discussion on this and other possible changes.

3.3 Description of the Downlink Communication: Power Transmitter to Power Receiver

It is required to be able to send data from the power transmitter to the power receiver. The reasoning for which will be detailed in chapter 6. However, the needed data bandwidth is much lower. It is only necessary to send a message every half second or so. Accordingly, there can be about 10 rounds of the uplink communication cycle before sending a downlink message back from the power transmitter to the power receiver. As stated above, Differential Manchester Encoding was used to encode the mes- sages. However only a single message is sent every time the downlink communication sends anything. The downlink communication receives its turn to send data when the power transmitter receives a handshaking message from the power receiver. This handshaking message is sent by the power receiver approximately every half second, which is about every 10 rounds of the uplink communication messages.

84 Instead of using modulated capacitance, amplitude modulation was implemented by directly adjusting the power sent by the power transmitter. This was effectively done by modulating the value written to the DAC which then drove the pth1 and pth2 (pulse-width pins) on the LTC4125. Figure 3-9 shows a downlink communication message interspersed between the uplink messages. The top dark blue waveform is the power transmitter communication clock. The light blue waveform is the modulated power transfer signal that drives the LTC4125 pulse-width pins. The pink waveform is the recovered signal on the power receiver side after the analog filtering. The green waveform is the uplink communication bits. Notice how the uplink communication pauses so that the downlink communication can begin.

Figure 3-9: Downlink Communication

Clock Recovery and Reading the Data

Instead of waiting for a transition to start data recovery as in the uplink communi- cation case, the downlink communication data recovery happens directly. This was necessary because of the nature of the analog signal processing circuitry. It was not guaranteed that there would be a transition in the recovered signal at the first tran-

85 sition of the sent signal. This is because although every sent signal starts with a rising edge, if the recovered signal starts high then there will be no transition in the recovered signal until the sent signal has a falling edge. This is shown in Figure 3-9 and in the zoomed Figure 3-10. Note how though the sent signal (light blue) has a rising edge, the received signal (pink) does not have a rising edge because its state was high before the downlink communication started. This problem could be fixed by making it so that the recovered signal had a default value of low. However, this is difficult because when no data is being sent, the noise in the system cancause random transitions in the received signal. This will be explained in detail below in the analog filtering section. It is true that a header message to establish thedata synchronization could have been used in the downlink communication in a similar way as the uplink communication, however because the downlink communication is only a single message this would be an inefficient use of bandwidth and was not necessary.

Figure 3-10: Downlink Communication Zoomed In

Therefore, once the power receiver finishes sending the handshake message to the power transmitter, it immediately expects to receive back a message in reply. The power receiver will therefore start sampling its data input line after a short

86 preprogrammed delay. The clocking of the data recovery is all done with a fixed clock so that the actual communication speed and the assumed communication speed need to be very close in order to have reliable communication. Specifically because the receiver clock is run open loop it needs to maintain proper synchronization for 17 bits. Therefore by the 17th bit the difference between the clocks must be less than 1 of the actual period in order for the readings to remain correct. With one 4 clock regarded as the correct one and the other clock regarded as wrong this may be mathematically expressed as:

⃒ ⃒ 푇푎푐푡푢푎푙 17 ⃒푇wrong − 푇actual⃒ < 4

Solving the inequality the expression becomes:

67 69 68 푇actual < 푇wrong < 68 푇actual

68 68 69 푓actual < 푓wrong < 67 푓actual

These precision requirements are easy to meet in the current implementation.

3.4 Signal Processing

Before the the modulated data can be read it has to be recovered from the modulated tank voltages. The transmitted signals first go through analog filtering and then through digital filtering in the microcontrollers.

3.4.1 Analog Filtering

Because the uplink and downlink communication are both implemented with am- plitude modulation at the same frequency, they were able to have the same analog filtering. The analog filtering circuit is shown in Figure 3-11 with the valuesofthe components in Table 3.1 . The first step is to envelope detect the modulated tank voltage without losing very much of the signal. This is accomplished by choosing R1 much greater than R2. The filter formed by R1, R2 and C2 has a cutoff frequency

87 of about 30kHz, sufficient for eliminating most of the carrier signal while keeping the modulated signal. The signal the goes through a high pass filter in order to retain the majority of the signal while also properly re-biasing the signal to 5V. The high pass filter corner frequency is about 70Hz. The signal is then buffered and amplified bya LTC1167 instrumentation with a gain of about 50 before going through a 2nd order Sallen Key low pass filter with a cutoff frequency of 28.5kHz and adamp- ing ratio of 1. [37] The signal is then buffered and sent to a LTC1440 comparator to be compared against the half the dc bias value. It is here that any noise in the tank voltage can cause unwanted transitions in the received signal. Some of the noise can be rejected because the LTC1440 has a hysteresis option, programmable up to 100mV.

Figure 3-11: Analog Filtering Circuit

Figure 3-12 and Figure 3-13 show the scope images of the filtering steps. Figure 3-

88 C1 R1 R2 C2 C3 R3 R4 C4 C5 R5 R6 0.1nF 300kΩ 10kΩ 0.56nF 47nF 100kΩ 100kΩ 1nF 100nF 40kΩ 40kΩ R7 R8 R9 R10 C6 C7 R11 R12 R13 R14 250kΩ 100kΩ 15kΩ 15kΩ 25pF 50pF 100kΩ 100kΩ 100kΩ 100kΩ Table 3.1: Analog Signal Filtering Values

12 shows the first filtering steps. The pink waveform is the encoded signal. TheDark blue waveform is the modulated tank voltage. The green waveform is the envelope voltage and the light blue waveform is the high passed signal that is the input to the instrumentation amplifier.

Figure 3-12: First Steps of Analog Filtering

Figure 3-13 shows the next steps of the analog filtering. The pink filter again shows the encoded signal. The dark blue waveform is the output of the instrumentation amplifier. The green waveform is the output of the 2nd order filter and the lightblue waveform is the output of the comparator. Two things can be noticed. First the dark blue signal does not need very much filtering and therefore the filter frequency could be raised, secondly the output signal is delayed relative to the transmitted signal.

89 Figure 3-13: Second Steps of Analog Filtering

I did not fully optimize the 2nd order low pass filter frequency because it was not necessary. It would however be necessary if I would have tried to increase the communication speed. Then I would certainly need to increase the filter frequency. However, I did try two different filter frequencies to observe the effects on thedelay between the transmitted and received signals. Figure 3-14 compares a filter on the left with a corner frequency of 14kHz and the filter on the right with a corner frequency of 28kHz.

90 Figure 3-14: Comparison Between Two Different Filter Frequencies

3.4.2 Digital Filtering

After the comparator, the signal goes to a digital input of the microcontroller to be read. After the signal is decoded and read according to the details given above in section 3.2, the values go through some digital filtering. The digital filtering is needed to filter out any errors in the readings due to double bit corruption, an error thatthe parity bit cannot detect. See chapter 4 for an explanation of the digital filters and digital signal processing used in this project.

91 92 Chapter 4

Feedback Control Theory and the Closed Loop System

4.1 Modeling a Continuous Time System as a Dis- crete Time System

Often times it is advantageous to use a digital controller to control a digital plant. Such a setup is shown in Figure 4-1.

Figure 4-1: A Continuous Time Plant with a Digital Controller

One way to create a suitable controller for a continuous time plant using a discrete time controller is to model the plant as a discrete time system. [38], [39] Figure 4-2

93 shows how the discrete time equivalent, 퐻푧표ℎ(푧), of the plant gives the same output 푦(푘) as the combination of the continuous time system, DAC, and ADC.

Figure 4-2: A DAC, Continuous Time Plant and ADC Replaced by a Discrete Time Equivalent

The discrete time model must consider how the continuous time plant will react to the controller DAC output, 푢ˆ(푡) in Figure 4-2. Typically the DAC output will be of the "Zero Order Hold" type in which each calculated discrete time output 푢(푘) is held during the sample period. This DAC output is then directly fed into the continuous time plant. For higher accuracy approximations, a higher (nth) order hold could be used. For example a first order hold would consist of an output thatis linear between the previous two samples and a nth degree hold would produce an nth degree polynomial that passes through the most recent n+1 samples. [39]This DAC output or Zero Order Hold approximation is shown in Figure 4-3.

Figure 4-3: DAC Zero Order Hold Output Waveform

To find how the continuous time plant responds to the DAC output, it mustbe

94 found how the continuous time plant responds to a square wave input such as a single pulse like that shown in Figure 4-4. This will then be the effective impulse response or pulse response that is needed in order to find the DT equivalent. [39]

Figure 4-4: Zero Order Hold Pulse

The single pulse is given in the time domain as 푢(푡) − 푢(푡 − 푇 ) where T is the duration of the pulse. Taking the Laplace transform of this results in 1−푒−푠푇 . Now 푠 the plant can be discretized by combing that result with the plant transfer function and converting it from the s domain to the Z domain as shown in Figure 4-5.

Figure 4-5: Discrete Time Equivalent Transformation of the Continuous Time Plant

This can be done most accurately by taking the inverse Laplace of the new transfer function to get the time domain equivalent of the plant’s pulse response and then discretizing the time domain function and then taking the Z transform. Alternatively one can use a table of transform equivalents to convert between the s domain to the

95 Z domain using the formula below where z has replaced 푒푗푤푇 = 푒푗Ω [40].

−1 {︁ 퐻(푠) }︁ 퐻ℎ0(푧) = (1 − 푧 )푍 푠

The table in Figure 4-6 shows some common equivalent transforms. This method is the default method used by Matlab in its c2d function.

Figure 4-6: Z and S Transform Pairs

In order for the disrete time plant model to be accurate, the sampling frequency should be about 10-40 times higher than the crossover frequency of the plant or any frequency of interest. [38]

4.2 Modeling a Continuous Time Controller in Dis- crete Time

Modeling a continuous time controller in the discrete time domain using numerical methods is usually done in one of three ways. As an example a simple error integrator will be modeled in discrete time. In this case the error signal will be integrated ∫︀ 푡 according to the equation 푢(푡) = 푒(푡) + 푢(푡0). The Laplace transform of this is 푡0 then 푈(푠) 1 The conversion of the integral into discrete time with can be 퐸(푠) = 푠 푡 = 푘 * 푇 understood graphically in Figure 4-7. The three graphs in Figure 4-7 show three different ways to write a difference equation for an integral. [41] Starting from the left they are the forward difference

96 Figure 4-7: Discrete Time Integral Approximations equation, backwards difference equation and trapezoidal, Tustin or bilinear difference equation. Writing out the difference equations for the integration and then taking the Z transform gives the equations in Figure 4-8 for the different difference equation methods.

Figure 4-8: Difference Equations and Corresponding Z Transforms for the Continuous Time Integrator

Based on this finding it can be concluded that in modeling a continuous time controller with a particular discrete time difference equation, that the corresponding Z transform can be found with the substitutions in Figure 4-9. When the s to z substitution is used, it is important to consider how the stability is affected during the substitution. Figure 4-10 shows how the stable portion ofthe continuous time s plane is mapped into the z plane during this substitution. The

97 Figure 4-9: S to Z Equivalents for Three Types of Difference Equations

Forward Difference approximation maps the entire left-half of the s plane toZ<1. Therefore some stable continuous time controllers will map to unstable discrete time controllers. The Backwards Difference approximation maps the entire left half of the s plane to a stable circular region in the Z plane. Therefore it is possible to have a stable discrete time controller map to an unstable continuous time controller. Finally, the bilinear transformation maps the left half of the s plane into the unit disc. Hence, stable continuous controllers are always approximated by stable discrete controllers and vice versa with the bilinear transformation.

Figure 4-10: Mapping of Stable Continuous Time Transfer Functions (Shaded) to the Z Plane

98 4.2.1 Discrete Time Filters

Continuous time filters can be expressed in the z domain through the use ofcertain mathematical techniques such as the bilinear transform or trapezoidal approximation (described above), impulse invariance, nth order hold, or pole zero matching method. Thus digital infinite impulse response (IIR) filters can be based on well-known solu- tions for analog filters such as the Chebyshev filter, Butterworth filter, and Elliptic filter, inheriting, albeit with important differences, the characteristics of those solu- tions. [40], [42], [43]

Bilinear Transform

The Bilinear transform method relates a continuous time filter to a discrete time filter with the following relation derived above:

1+ 푠푇 2 푧−1 or 2 푠 = 푇 푧+1 푧 = 푠푇 1− 2

Out of the options mentioned above, the Tustin or bilinear approximation yields the best frequency-domain match between the continuous-time and discretized sys- tems. [42]. Even though the discrete time equivalent guarantees stability, there is distortion when the entire left half of the s plane is mapped to the unit circle. The distortion can be compensated by using Tustin’s rule or an approach called pre- warping. The idea is to ensure that at a particular frequency the DT equivalent has the exact same characteristics (gain and phase) as the corresponding CT transfer function. The transformation still uses the bilinear term 푧−1 but with a different 푠 = 푧+1 coefficient. The coefficient isnow 휔0 [40]. Instead of using the trapezoidal ap- 푡푎푛(휔0푇/2) proximation, one could also use the backwards or forward difference approximations. However the stability, as shown above, of such a substitution needs to be considered. [40] shows that all of the filter approximations for a third order Butterworth filter perform equally well for frequencies much less than the sampling frequency.

99 Impulse Invariance

This method finds the DT (Infinite Impulse Response) IIR equivalent filter bysam- pling the continuous time impulse response. If the continuous time filter is approxi- mately limited to a frequency less than the Nyquist frequency of the sampling, then the frequency response of the discrete-time system will be approximately equal to frequency response of the continuous time system for frequencies below the Nyquist frequency. The impulse-invariant mapping produces a discrete-time model with the same impulse response as the continuous time system. [42], [43]

Pole-Zero Matching

The pole-zero matching equivalent is done by replacing the poles and zeros according to the relation:

푧 = 푒푠푇

See [40] for more details. This method was not used in this paper. nth Order Hold

This is the method used above in Section 4.1 to find the exact discrete time equivalent of the continuous system for an nth order input. A zero order hold can be used to find the exact discretization of the time domain system for staircase inputs. Afirst order hold produces an exact discretization of the time domain system for piecewise linear inputs, etc.. [42] Although almost all analog electronic filters are IIR, digital filters may be either IIR or finite impulse response (FIR). The presence of feedback in the topology ofa discrete-time filter generally creates an IIR response. The z domain transfer function of an IIR filter contains a denominator, describing those feedback terms. Onthe other hand, the transfer function of a FIR filter has only a numerator and the filter has no finite poles. [43]

100 4.3 Open Loop System

In order to properly design a suitable amount of compensation for the feedback con- trol, it was necessary to quantify how the wireless charging link responds in open loop. This was done by applying a step of voltage to the input command of the LTC4125 and driving the input resonant tank at a certain duty cycle. The resulting battery charging current was approximately first order in response. After testing the step response of the wireless link over a range of coupling factors and rectified volt- ages, it was found that although the gain of the system changes from about 0.2 at small loading and high coupling to 0.8 at large loads and low coupling, its first order time constant is approximately constant at 3.8ms. These values of 0.2 and 0.8 were obtained from measurements of the system with an AC load. Figure 4-11 graphs the measurements that were taken.

Figure 4-11: First Order Time Constant Measurements for Different Coupling Factors and Rectified Voltages

Figure 4-12 and Figure 4-13 are two step response waveforms for two coupling factors on the opposite ends of the coupling range: 푘 = 0.16 and 푘 = 0.532. As shown in the measurements of Figure 4-11, the time constants are very similar but

101 the DC gain are not. These two graphs have approximately the same load level so the difference in their DC gain is mainly due to the difference in coupling.

Figure 4-12: First Order Step Response for K = 0.16

Figure 4-13: First Order Step Response for K = 0.532

4.4 Smith Predictor Controller

Because of the time delay in the feedback loop caused by the communication lag, I investigated the potential use of a Smith Predictor controller. Such a controller

102 is designed for systems with a pure time delay. The basic idea is to modify the controller to compensate for the delay in the plant. The resulting effect is to add an inner prediction loop to the feedback loop that is active while the regular outer loop is delayed as it waits for new information to arrive. The modified compensation relies on having a fairly accurate model of the plant so that while the controller waits for the new information, it uses stable feedfoward control. [44] Figure 4-14 shows the modified compensation for a standard feedback block dia- gram. The delay in the plant is the 푧−푘 block between the output of the plant and the error calculation. This delay suitably models the communication lag between the power receiver and the power transmitter. The smith predictor controller has the following transfer function:

∼ ∼ 풞 (푍) = 퐶(푍) or in CT: 풞 (푠) = 퐶(푠) 1+퐶(푍)퐺(푍)(1−푧−1) 1+퐶(푠)퐺(푠)(1−푒−푠푇푑 )

Figure 4-14: A Standard Feedback System with a Smith Predictor for Compensation

At first I thought that using a Smith Predictor would be a great way to increase the bandwidth of my closed loop control. All that is needed is a fairly accurate model of the plant. As shown above, the approximate time constant is fairly uniform across coupling factors and loading levels. However, as shown in Figure 4-15, the gain of the system changes from about 0.2 to 0.8 as the coupling factor and loading level changes.

103 Figure 4-15: Input Vpth to Output Current Gain For Different Coupling Factors and Loading Levels

Therefore, I would need to choose a conservative model for the smith predictor to account for all of the possible operating positions. The different simulated scenarios are shown below where I have assumed that the predicted first order time constant of the plant matches the actual first order time constant. Although in reality the gain would be actively changing during a step while the loading level changes, the step responses below are to show the range of performance of the Smith Predictor compared to a standard PID controller. Figure 4-16 and Figure 4-17 have a low prediction of the plant gain and Figure 4-18 and Figure 4-19 have a high (conservative) predication of the plant gain. Figure 4-16 shows the step response of the plant with and without a smith pre- dictor when the actual gain is 0.8 and the predicted gain is 0.2. Figure 4-17 shows the step response of the plant with and without a smith pre- dictor when the actual gain is 0.8 and the predicted gain is 0.8. Figure 4-18 shows the step response of the plant with and without a smith pre- dictor when the actual gain is 0.8 and the predicted gain is 0.8. Figure 4-19 shows the step response of the plant with and without a smith pre-

104 dictor when the actual gain is 0.2 and the predicted gain is 0.8.

Figure 4-16: High Gain Situation with a Low Gain Prediction

Figure 4-17: Low Gain Situation with a Low Gain Prediction

As can be seen, the predictive controller (yellow) does not offer significant im- provement. I would need to use the high (conservative) estimate of the gain to avoid the ringing shown in Figure 4-16. Therefore I decided to use a standard PID controller for simplicity.

105 Figure 4-18: High Gain Situation with a High Gain Prediction

Figure 4-19: Low Gain Situation with a High Gain Prediction

4.5 Closed Loop System

Now that an approximate understanding of the open loop step response of the wireless plant was found, it is possible to add an appropriate amount of compensation with a PID controller and close the feedback control loop.

4.5.1 Block Diagram and Calculations

The block diagram in Figure 4-20 represents the closed loop system from an input reference voltage which designates a particular charging current set-point, to the

106 output charging current. As can be seen, the system has many more blocks in addition to the wireless plant, PID controller and communication delay. The additional blocks represent the various filtering blocks and conversions in the system.

Figure 4-20: Closed Loop Feedback Block Diagram

I used basic first order filters everywhere and mapped them to the discrete timeby using the backwards difference equation. I chose to use the backwards difference equa- tion transform instead of a trapezoidal or bilinear transform because it was simpler, guaranteed stability according to Figure 4-10, and should have the same effect for the frequencies above the sampling frequency. Future work could investigate the merits and feasibility of implementing higher order filters. Using the backwards difference equation on a first order filter the transformation becomes:

퐻(푠) = 1 to 퐻(푧) = 푇푠푧 휏푠+1 푧(휏+푇푠)−휏

Where 푇푠 is the sampling period and 휏 is the first order time constant. The discrete time difference equation for this IIR first order filter isthus:

푦 [푛] = 푦[푛−1]휏+푥[푛]푇푠 휏+푇푠

PID Controller

Based on the closed loop feedback block diagram and the numerical values of the different blocks, I was able to design a suitable PID controller in Matlab. [45],[46], [47] A PID controller has the following Laplace transform:

퐾푖 퐶(푠) = 퐾푝 + 푠 + 퐾푑푠 107 However, it is often necessary to modify the derivative term as shown below and add a low pass filter so that high frequency noise does not couple into the command.

퐾푖 퐾푑푠 퐶(푠) = 퐾푝 + 푠 + 휏푠+1

A PID controller in the Z domain can be obtained by using the difference equa- tion substitutions derived above in Section 4.2. For the sake of stability, either the trapezoidal or backwards difference equation substitution should be used. I ended up only using a PI controller because the added computational complexity did not seem to justify the marginal bandwidth improvement. The PI controller in the Z domain with a trapezoidal approximation is given below where U is the Z transform of the output command and E is the Z transform of the error.

푈 푇 푧+1 퐸 (푧) = 퐾푝 + 퐾푖( 2 ) 푧−1

This can be expanded to yield:

푇푠 푇푠 −1 푈 (퐾푝+퐾푖( 2 ))+(퐾푖 2 −퐾푝)푧 퐸 (푧) = 1−푧−1

This can be transformed to the implementable difference equation:

푇푠 푇푠 푢 [푛] = 푢 [푛 − 1] + 푒 [푛](퐾푖 2 + 퐾푝) − 푒 [푛 − 1] (퐾푖 2 − 퐾푝)

Using the values for 퐾푝 = 0.1 and 퐾푖 = 0.1 from Table 4.1 with the sampling time 푇푠 equal to the communication delay, the PI controller is:

푢 [푛] = 푢 [푛 − 1] + 0.104 푒 [푛] − 0.096 푒 [푛 − 1]

Table 4.1 gives the numerical values of the individual blocks for the closed loop system. With the values in Table 4.1 the open loop bode plot was plotted in Figure 4-21. Because of the communication delay and filtering, the bandwidth of the system was relatively low at 1.46 rad/s or 0.23 Hz.

108 Block Type Value ADC Gain ADC Conversion 4096/2.527 (Power TX) Gain = 1,621 ADC Filter Digital Filter = 200ms (Power TX) 휏 Current Error Digital Gain 5 Gain (Power TX) Voltage Error Digital Gain 100 Gain (Power TX) Error Filter Digital Filter = 400ms (Power TX) 휏 PID Compensation Kp = 0.1 Digital PI Filter (Power TX) Ki = 0.1 DAC Gain DAC Conversion 3.262/4096 = (Power TX) Gain 7.9639e-4 = 3.8ms LTC4125 to Battery 휏 First Order Plant 0.5 Chargin 퐺푎푖푛퐷퐶 ∼ Range ∼ (0.2-0.8) Current Sense Amplifier Analog Gain 2.71714 (Power RX) ADC Gain ADC Conversion 4096/1.985 = (Power RX) Gain 2,064 ADC Filter Digital Filter = 200ms (Power RX) 휏 Communication Time Delay =80ms Delay 푇푠 Data Recovery Filter Digital Filter 휏 = 400ms (Power TX)

Table 4.1: Numerical Values for the Closed Loop Feedback Block Diagram in Figure 4- 20

109 Figure 4-21: Bode Plot of the System’s Open Loop Transfer Function

4.5.2 Measurements

I then compared the theoretical closed loop step response to the measured closed loop step response with the results shown in Figure 4-22 - Figure 4-20. The predicted and experimental results of a more conservative PI controller are

shown in Figure 4-22 and Figure 4-23. The compensation values being 퐾푝 = 0.04

and 퐾푖 = 0.03. According to Matlab the phase margin of the open loop system is 92 degrees and the step response has approximately a 13 second rise time. Compare this with the waveforms in Figure 4-23 that show a similar 13 second rise time also without any ringing. The predicted and experimental results of a more aggressive PI controller are shown in Figure 4-24 and Figure 4-25. The compensation values being 퐾푝 = 0.1 and 퐾푖 = 0.1. According to Matlab the phase margin of the open loop system is 57 degrees and the step response has approximately a 6 second rise time. Compare this with the waveforms in Figure 4-25 that show a similar 6 second rise time with similar and frequency in the ringing. The measured rise in Figure 4-25 has a break in the rise because of a break in the communication. See Section 6.3 for details on communication breaks and recovery.

110 Figure 4-22: Matlab Step Response with a Conservative Controller: Kp = 0.04, Ki = 0.03

Figure 4-23: Measured Step Response with a Conservative Controller: Kp = 0.04, Ki = 0.03

111 Figure 4-24: Matlab Step Response with an Aggressive Controller: Kp = 0.1, Ki = 0.1

Figure 4-25: Measured Step Response with an Aggressive Controller: Kp = 0.1, Ki = 0.1

112 Chapter 5

Battery Charging

5.1 Overview of Battery Charging

Every type of battery needs to be charged in a particular way depending on its cell chemistry. This thesis was concerned primarily with charging Li-Ion/Polymer batteries. The charging curve for such batteries consists of three regions.[48] When the battery voltage is less than a certain threshold value the battery must be charged with a small amount of current known as trickle charge. This is a constant current region. Once the battery voltage has surpassed the trickle charge threshold voltage, the charging current can be raised to the maximum charging rate. This is also a constant current region. As the battery voltage nears the full charge voltage the current should be decreased so that the voltage drop due to the internal battery resistance decreases and an accurate measurement of the battery voltage can be made. This is a constant voltage region. While the battery voltage only changes a little, the current will continue to decrease in this region until both the charging current is less than a threshold, usually 1 of the max charging current, and the battery 10 푡ℎ voltage is greater than a certain threshold. From the battery chargers point of view, the battery should be regarded as charged unti the battery voltage drops by about

2% from the fully charged state. Figure 5-1 shows these regions.

113 5.2 Analog Controlled Battery Charging

Figure 5-1: Typical Analog Controlled Li-Ion/Polymer Battery Charging Curve

The third region in Figure 5-1 is called the Knee region, when there is crossover between the current and voltage error controllers. This can be understand better by looking at a typical constant current, constant voltage analog error amplifier circuit shown in Figure 5-2. The combined error voltage in the center is the signal that is passed to the compensation loop. This error signal is influenced by both the charging current error and the battery voltage error. Each individual error term ultimately controls the current through the transistors M1 and M8. These currents then fight with the center current source to determine the voltage on the error capacitor C1. The difference between the set-point and the actual value of either the charging current or battery voltage determines how much of the 2퐼 source currents of the

114 differential is reflected through to the transistors M1 and M8.During the constant current charging regions, the battery voltage is far enough below the set-point voltage that the voltage error has saturated and the current error solely determines the combined error and therefore the charging rate. During the Knee region, or constant voltage region, the voltage error is no longer saturated and the voltage and current errors are fighting over the control of the combined error voltage. The transconductances (gm) of the transistors determine how a difference between value and set-point translates to the pull-down currents in M1 and M8. Therefore because of a finite value of gm attainable in the transistors, the gain of the error amplification is limited. The result being that the battery charging curve canhave a slow and gradual constant voltage region. This portion of the charging cycle can be greater than half of the total charging cycle duration even though the amount of energy stored in the battery during this time is proportionately far less.

Figure 5-2: Constant Current Constant Voltage Analog Error Gain Circuit

115 5.3 Digitally Controlled Battery Charging

By making the controller digital the error amplification is no longer limited bya transconductance gm but by the system stability of the feedback loop. Ideally the knee region in Figure 5-1 above can be shortened to almost nothing as shown in Figure 5-3. The limiting factor to the error gain in my case was the stability of the system. The digital equivalent equation of the analog error circuit is:

Combined Error =

[︀ ]︀ Min (퐺1(Battery Voltage Set-point - Battery Voltage)), Max Error)

[︀ ]︀ + Min (퐺2(Battery Current Set-point - Battery Current)), Max Error)

− Max Error (5.1) The digital battery charge curve will now look something like the diagram shown below.

Figure 5-3: Digitally Controlled Battery Charging Cycle

116 Chapter 6

Communication and Max Efficiency Finding Algorithm

6.1 Efficiency Optimization Overview

As stated in the end of Chapter 2, the goal of the thesis was to design and implement a working communication channel embedded within the power transfer channel in order to charge batteries efficiently over a versatile range of operating conditions. This would be accomplished by dynamically changing the rectified voltage of the receiver in order to best impedance match the transmitter and receiver for the greatest possible efficiency. Because it was not possible to change the rectified voltage regulation point on the LTC4120, I ended up using the LTC3652 IC, which is a battery charging IC. [49] However, because I was doing the battery charging control from the power transmitter side, the only functionality of the LTC3652 that was used was the buck converter and the input regulation. As described below, the input regulation set-point (pin 2) was dynamically changed based on the desired rectified voltage. The half duplex communication described in chapter 3 provided the means to fully control the power receiver side battery charging from the power transmitter side. The idea being that as the system proceeds through a charging cycle, it actively searches for the most efficient operating point by changing the rectified voltage and then measuring and comparing the total efficiency.

117 Both the power transmitter and power receiver had microcontrollers for handling the communication and their respective control flow charts. The individual logic flow charts are represented and described below.

6.2 Power Transmitter Side Flow Chart

When no communication has yet been established, the first thing that must happen is for the power transmitter to send a chirp in power. The chirp linearly ramps up to a digital value of 2500, corresponding to a voltage of 2V based on the DAC Gain given in Table 4.1. Based on the LTC4125 linear mapping between the pulse-width pin voltage and the pulse width (duty cycle) this to about 40% duty cycle. (2.5V = 50%). The chirp ramping rate is about 75mV/second which corresponds to roughly an increase of 1.5% in the duty cycle/second. The chirping will continue periodically until the power receiver adequately responds. This is accomplished when the power transmitter receives back 10 new battery charging current messages or about 40 total messages from the power receiver. The threshold of 40 messages was set such that the communication was properly established before continuing. Upon receiving the 10th battery charging current message, the power transmitter enters into the main control loop to properly regulate the battery charging cycle. This portion of the power transmitter flow chart is shown in Figure A-3. Waveforms showing the chirp taking place are shown in Figure 6-2. The command starts off with a linear rise during the chirp. Communication is established after10 transitions of the top blue waveform which depicts a new battery current reading was received. Then closed loop control takes over and the power transmitter command is no longer linear but rises according to the error and compensation. The battery current follows accordingly. The power transmitter is spending most of the communication bandwidth reading data sent by the power receiver. As the power receiver sends data, the power trans- mitter is continuously shifting the incoming bits into its data received shift register. Once data synchronization has been established, meaning that the power transmit-

118 Figure 6-1: Establishing Communication and Power Transfer

Figure 6-2: Beginning Communication and Power Transfer with a Chirp ter has recognized the preamble sent by the power receiver, the data received shift register is periodically read to determine both the type and numerical value of the information being received. In particular the power transmitter is looking for five

119 distinctive header bit combinations. Three of which correspond to a new battery voltage value, battery current value, or rectified voltage value. A fourth used for sim- ply re-syncing communication for the sake of recovering communication in the event that it becomes corrupted and/or lost. And a final header distinguisher that tells the power transmitter that it is its turn to send a message to the power receiver. This flow chart machine is illustrated in Figure 6-3 below.

Figure 6-3: Power Transmitter Communication Flow Chart

6.3 Power Receiver Side Flow Chart

The power receiver spends most of the communication bandwidth sending data to the power transmitter. Once the power receiver has sufficient power for its micro- controller, it starts to send messages via the capacitor modulation of its tank circuit. The messages continually cycle through a periodic progression of sending data, at-

120 tempting to re-sync communication and sending a handshaking message to tell the power transmitter it should send a message next. In particular, the flow chart cycles through sending the three data messages and one re-sync message: battery voltage, battery current, rectified voltage and re-sync a total of 10 times each before sending the handshake message to allow the power transmitter to send a message. After the handshake message is sent, the power receiver is expecting a message to be sent by the power transmitter. If no intelligible message is received then the power receiver takes note of this, suspecting that communication has been broken. If however within the next couple of handshaking attempts the power receiver does receive a message from the power transmitter, faith in the communication link is reestablished and the communication cycle continues. If however the power receiver does not receive a mes- sage after a certain number of handshake attempts, then it must try a new value for the modulated capacitance in order to have any hope at reestablishing communica- tion. As was shown in Section 1.4.3, the voltage transfer function can vary widely as the coupling factor and power transfer rate are changed. Of particular interest are the points at which the transfer curve are relatively flat as a function of frequency. It is in these regions that the communication is in danger of corruption because a modulated tank has only a minor affect on the tank voltage. In order to solve this problem it was necessary to have multiple possible values of modulated capacitance. Each modulated capacitor will have a different effect on the voltage transfer curve, thus making it possible to find a value that creates a suitable SNR for communica- tion to be reestablished. If the communication has been deemed broken by the power receiver then it cycles through its possible capacitance values until communication is restored. The order through which the possible are cycled is from the smallest to the largest because in general the smaller the modulated capacitance, the higher the overall efficiency. Figure 6-4 shows a flow chart diagram that depicts the power receiver communication logic flow.

Waveforms depicting this cyclic messing are shown in Figure 6-5. The top pink waveform shows a transition for every new battery current message. As can be seen, every 10th transition a downlink message is sent, shown by a pulse in the bottom blue

121 Figure 6-4: Power Receiver Side Communication Flow Chart waveform. During this time the power transmitter pulse width command is amplitude modulated as can be seen vaguely in the light blue waveform. At the same time the green waveform shows that there is a break in the normal uplink communication. The waveforms in Figure 6-6 show the communication being broken and then restored. A transition in the bottom blue waveform represents the reception of a new battery current message. When a message is not received, the power transmitter command does not change until a new message is received. After a period of time

122 the communication is reestablished and the charging control continues where it left off before losing communication.

Figure 6-5: Power Transmitter Communication

Figure 6-6: Restored Communication

123 6.4 Power Transmitter Efficiency Optimization Flow Chart

The power transmitter must determine which region of the charging cycle the battery is in and respond accordingly. Depending on the region, the power transmitter will set the charging current set-point and then send the necessary power to the receiver to meet the set-point. Once the system has reached steady state operation the power transmitter calculates the system efficiency. The steady state criteria can be easily adjusted in the code and was finally set to requiring that the current error was less than about 4mA. In the code the required current error variable had to be less than 100. The digital current error to actual current error calculation is shown below based on the values for the current error gain, power RX ADC gain and current sense amplifier gain given in Table 4.1.

1 1 1 퐼(푚퐴)steady state = 100(current error gain)(ADC Gain)(current sense amplifier gain)

1 1.985 1 = 100( )( )( ) ≈ 4푚퐴 5 4096 2.717 (6.1) After saving the calculated value, the power transmitter sends a command to the power receiver to change its rectified voltage in order to search for the best rectified voltage. Once the rectified voltage has been changed and the system has again reached stability, the power transmitter again calculates the system efficiency, saving and comparing the value to the other known rectified voltage efficiencies. If the current rectified voltage state has an efficiency that is less than either of the neighboring rectified voltage states then the power transmitter tells the power receiver to change the rectified voltage to the value that gives a higher efficiency. This search continues until the power transmitter finds the maximally efficient point for that coupling and power level. However, if the input power ever changes by a fixed amount, the power transmitter must begin a new search for the most efficient rectified voltage. This is for two reasons.

124 1) If the coupling changes then the input power will change because the output power will remain constant once equilibrium is reestablished. 2) The battery voltage has changed significantly enough that the charging power has changed beyond a certain amount from when the efficiency search finished last. In both cases it is necessary to search again for the most efficient rectified voltage. This is done by clearing the memory of the efficiencies for each rectified voltage state. This flow chart is illustrated in Figure 6-8.

Figure 6-7: Dynamic Response After a Change in the Rectified Voltage

The waveforms in Figure 6-7 show what happens when the rectified voltage changes. There is a jump in the battery charging current because of the change in impedance (see Section 2.2.3) Equilibrium is obtained within a few seconds when the battery charging current returns to the set-point level.

125 Figure 6-8: Power Control Flow Chart in the Power Transmitter

126 Chapter 7

Results and Future Considerations

7.1 Efficiency Comparisons

The goal of this thesis was to improve both the versatility and efficiency of a resonant wireless power transfer system by adding an embedded communication channel into the power transfer channel. After successfully implementing the half-duplex commu- nication channel (Chapter 3) and the max efficiency finding algorithm (Chapter 6), I was able to compare the efficiency curves of the stand alone LTC4120 with that of the new system. As noted before, the LTC4120 regulates the rectified voltage to 12V. Assuming a working max efficiency finding algorithm, I was able to compare the 12V rectified voltage efficiency without communication with the efficiencies ofother rectified voltages with the communication. It is necessary to have the communication running when comparing the efficiencies because the communication scheme incurs power losses. The communication power losses are the result of both burning power in the switches of the modulated capacitors, the parasitic resistances of the capacitors them- selves, and the extra parasitic losses due to potentially more oscillating energy in the transmitter and receiver tanks. Because the magnitude of the power losses are de- pendent on both the coupling and power level I did not systematically measure the efficiency effects of the modulation scheme. Instead, as shown below, Imeasured and compared the efficiency with and without different amounts of modulated capac-

127 itance. In this way I was able to directly compare the overall efficiency effects of the different modulated capacitor values. All of the graphs below display the total efficiency from a to the battery charging power. Each graph has the efficiency of the 12V rectified voltage case without communication in light blue representing the benchmark efficiency to which the new system should be compared. Each graph compares a different alternative rectified voltage with multiple curves of the efficiency at that rectified voltage,each with different amounts of modulated capacitance. In general it is the case thata higher value of modulated capacitance is less efficient than a smaller value. This creates a trade-off between communication efficiency and SNR. However, there are exceptions to this rule because in some cases a larger modulated capacitance moves the system to a more efficient operating point.

K = 0.532, Distance = 4.95mm

Figure 7-1 below displays measurements taken with a coupling of 푘 = 0.532. There is always a rectified voltage value and affiliated modulated capacitance value that provides at least an equal efficiency to the benchmark curve. At this coupling factor there appears to be efficiency gains only for output power levels of lessthan 3 Watt. 4 At this high coupling factor and low power level, as was predicted in Section 1.4.4, it is more efficient to have a lower rectified voltage, such as 8Volts.

128 Figure 7-1: Efficiency With and Without Communication for Various Rect Voltages with K = 0.532

K = 0.283, Distance = 9.9mm

Figure 7-2 displays measurements taken with a coupling of 푘 = 0.283. Once again there appears to always be a rectified voltage and affiliated modulated capacitance value that provides at least an equal efficiency to that of the benchmark curve. At this coupling factor there appears to be efficiency gains for power levels up to about 1.5 watts. In particular a rectified voltage of about 10 Volts provides higher efficiency.

129 Figure 7-2: Efficiency With and Without Communication for Various Rect Voltages with K = 0.283

K = 0.16, Distance = 14.8mm

Figure 7-3 below displays measurements taken with a coupling of 푘 = 0.16. At this coupling factor there appears to be rectified voltages with an affiliated modulated capacitance value for which the efficiency is better than the benchmark for the entire range of measurement. To summarize the efficiency comparison results, I believe it can be said thatthe added communication scheme provided some improvement to the overall system. The efficiency gains were not drastic but the added benefit of closed loop communication in addition to the moderate efficiency gains is reason enough to consider future de- velopment of this idea.

130 Figure 7-3: Efficiency With and Without Communication for Various Rect Voltages with K = 0.16

7.2 Range Extension

As shown in Section 2.2.3, by having a variable rectified voltage it is possible to send more power at a given coupling factor than if the rectified voltage is fixed at 12V. The effects are particular relevant for the smaller coupling factors. Alsoin Figure 7-3, for the farthest measured case of K = 0.16, it was more efficient to have communication and a variable rectified voltage. Taken together, these results show that range extension due to communication is achievable. Although I was not able to systematically measure the extension of the range beyond that of the 1.5cm parameter given in the LTC4125 datasheet, I was able to observe the communication and efficiency finding algorithm working beyond a distance of2cm.

131 7.3 Future Considerations to Improve the System

The following are a number of ways to possibly improve the system during any further development of the concept.

1. Move most of the control to the secondary or power receiver side: The receiver would then have the control to regulate both the rectified voltage and the charging current. In order to properly request the right amount of power from the power transmitter, the receiver should measure the current through a resistor in shunt with the receiver tank. The receiver should then actively send back this shunted current value to the power transmitter so that the power transmitter can send the right amount of power. Although the shunt current messages will take up the majority of the communication bandwidth, the transmitter will need to occasionally send a message containing the value of the input power so that the power receiver can calculate the system efficiency. Therefore the system will still need to be half-duplex and will still have the majority of its communication from the power receiver to the power transmitter.

2. Improve communication speed The current system has a power transfer frequency of about 100kHz. This frequency is also the carrier frequency for the amplitude modulation scheme implemented with the modulated capacitance. The bit rate of the current scheme is 1kHz. This bit rate could be increased about 10 times without making any significant changes to the system. The signal processing filter frequencies would have to be changed. Although it would have been of interest to increase the communication speed, it was not necessary for the objective of the thesis and I did not have time to make the necessary changes.

Without changing the bit rate, the communication speed could be effectively increased by only sending the necessary information. In the current system, the rectified voltage message is sent much more frequently than needed. This is even true for the battery voltage message when the charging cycle is in the

132 constant current portion. By making change number 1 above and moving the control to the secondary side, the communication will become more efficient because only one value will have to be sent by the receiver. The current system also sends the re-syncing message possibly more often than is needed. This re-syncing message could also possibly be shortened as it is currently 16 bits, only one less bit in length than the rest of the messages.

Finally the power receiver could send only the bits that reflect the change in a value. Instead of sending all twelve bits of the twelve bit measurement, only the few bits that represent the change from the previous message could be sent.

Combining these three strategies together could increase the communication speed by 10*3*2 = 60 times. This assumes a 10 times increase in the bit rate, a 3 times more efficient messaging cycle when only the shunt current value issent after implementing improvement number 1, and a 2 times bit saving by only sending on average half of the 12 bits in order to send the change in a value.

3. More Efficient Communication The capacitor modulation scheme could have its efficiency improved in three ways. The capacitors could have ahigher Q factor. The transistor switches used to turn on and off the modulation could be less lossy and the transmit and receive coils could have a higher Q factor. This last improvement is relevant because during the modulation, it is normally the case that more energy is oscillating in both the transmit and receive coils than compared to the case without communication. The current system has a relatively low quality factor for the secondary coil at Q = 21.07 compared to that of the primary coil having Q = 84.13 (Table 1.2). A higher quality factor for the secondary coil would therefore increase the efficiency of the communication scheme.

4. Scaling to Lower Power What is the minimum power level for which this scheme is effective? Can it be used to provide both power and data transmission for medical devices or should a separate communication method be used?

133 5. Scaling to Higher Power What is the maximum power level for which this scheme is effective?

6. Maximum Distance What is the minimum coupling for which modulated capacitance communication is not possible or too inefficient to be considered?

7. Resonance vs off-Resonance? More measurements could be done to prop- erly understand the advantages and disadvantages between using a resonant or off-resonant circuit combination. For low coupling it seems to be true that resonantly matched circuits are more efficient and capable. However for high coupling the answer is not so clear. Because the impedance changes so much with coupling, it does not seem to be trivial to select a resonant tank combi- nation that gives the best efficiency across different coupling factors and power levels. A possibility worth investigating would be to actively change the self resonant frequency of the transmitter or receiver to make the system even more versatile to changes in coupling and power levels.

134 Appendix A

Pictures of the System

Figure A-1 shows the LTC4125 evaluation board below and the LTC4120 evaluation board on top.

Figure A-1: Power Transmitter Board

135 Figure A-2: Power Transmitter Board

Figure A-3: Power Receiver Board

136 Appendix B

System Code

B.1 Power Transmitter Code

//______//main.c //______//This is the main routine that initializes theGPIO pins, the different interrupt driven routines and configures intial variable values.

#include//Atmel Software Framework #include"lcd_utils.h"//Various header files for source code #include"data_recovery.h" #include"dacc_utils.h" #include"adc_utils.h" #include"down_link_utils.h" #include"gpio_utils.h" #include"led_utils.h" #include"control.h" #include"efficiency_finder_utils.h"

void pin_setup(void); void pin_setup (void){ pmc_enable_periph_clk(ID_PIOA);//Enable the Peripheral clock

//______GPIOS used for debugging, accessible from the 13 pin female header______//______See gpio_utils.c and gpio_utils.h for the macro functions to turn them on and off easily.

137 //GPIO1 PIOC -> PIO_IDR |= PIO_PC0; PIOC -> PIO_PUER |= PIO_PC0; PIOC -> PIO_MDDR |= PIO_PC0; PIOC -> PIO_CODR |= PIO_PC0; PIOC -> PIO_PER |= PIO_PC0; PIOC -> PIO_OER |= PIO_PC0;

//GPIO2 PIOA -> PIO_IDR |= PIO_PA20; PIOA -> PIO_PUER |= PIO_PA20; PIOA -> PIO_MDDR |= PIO_PA20; PIOA -> PIO_CODR |= PIO_PA20; PIOA -> PIO_PER |= PIO_PA20; PIOA -> PIO_OER |= PIO_PA20;

//GPIO3 PIOC -> PIO_IDR |= PIO_PC12; PIOC -> PIO_PUER |= PIO_PC12; PIOC -> PIO_MDDR |= PIO_PC12; PIOC -> PIO_CODR |= PIO_PC12; PIOC -> PIO_PER |= PIO_PC12; PIOC -> PIO_OER |= PIO_PC12;

//GPIO4 PIOA -> PIO_IDR |= PIO_PA23; PIOA -> PIO_PUER |= PIO_PA23; PIOA -> PIO_MDDR |= PIO_PA23; PIOA -> PIO_CODR |= PIO_PA23; PIOA -> PIO_PER |= PIO_PA23; PIOA -> PIO_OER |= PIO_PA23;

//GPIO5 PIOC -> PIO_IDR |= PIO_PC13; PIOC -> PIO_PUER |= PIO_PC13; PIOC -> PIO_MDDR |= PIO_PC13; PIOC -> PIO_CODR |= PIO_PC13; PIOC -> PIO_PER |= PIO_PC13; PIOC -> PIO_OER |= PIO_PC13;

//GPIO6 PIOA -> PIO_IDR |= PIO_PA22; PIOA -> PIO_PUER |= PIO_PA22; PIOA -> PIO_MDDR |= PIO_PA22; PIOA -> PIO_CODR |= PIO_PA22;

138 PIOA -> PIO_PER |= PIO_PA22; PIOA -> PIO_OER |= PIO_PA22;

//GPIO7 PIOC -> PIO_IDR |= PIO_PC15; PIOC -> PIO_PUER |= PIO_PC15; PIOC -> PIO_MDDR |= PIO_PC15; PIOC -> PIO_CODR |= PIO_PC15; PIOC -> PIO_PER |= PIO_PC15; PIOC -> PIO_OER |= PIO_PC15;

//GPIO8 PIOA -> PIO_IDR |= PIO_PA19; PIOA -> PIO_PUER |= PIO_PA19; PIOA -> PIO_MDDR |= PIO_PA19; PIOA -> PIO_CODR |= PIO_PA19; PIOA -> PIO_PER |= PIO_PA19; PIOA -> PIO_OER |= PIO_PA19;

//GPIO9 PIOC -> PIO_IDR |= PIO_PC27; PIOC -> PIO_PUER |= PIO_PC27; PIOC -> PIO_MDDR |= PIO_PC27; PIOC -> PIO_CODR |= PIO_PC27; PIOC -> PIO_PER |= PIO_PC27; PIOC -> PIO_OER |= PIO_PC27;

//GPIO 10 PIOA -> PIO_IDR |= PIO_PA21; PIOA -> PIO_PUER |= PIO_PA21; PIOA -> PIO_MDDR |= PIO_PA21; PIOA -> PIO_CODR |= PIO_PA21; PIOA -> PIO_PER |= PIO_PA21; PIOA -> PIO_OER |= PIO_PA21;

//GPIO 11 PIOA -> PIO_IDR |= PIO_PA18; PIOA -> PIO_PUER |= PIO_PA18; PIOA -> PIO_MDDR |= PIO_PA18; PIOA -> PIO_CODR |= PIO_PA18; PIOA -> PIO_PER |= PIO_PA18; PIOA -> PIO_OER |= PIO_PA18;

//GPIO 12 PIOC -> PIO_IDR |= PIO_PC26;

139 PIOC -> PIO_PUER |= PIO_PC26; PIOC -> PIO_MDDR |= PIO_PC26; PIOC -> PIO_CODR |= PIO_PC26; PIOC -> PIO_PER |= PIO_PC26; PIOC -> PIO_OER |= PIO_PC26;

//GPIO 13 PIOA -> PIO_IDR |= PIO_PA17; PIOA -> PIO_PUER |= PIO_PA17; PIOA -> PIO_MDDR |= PIO_PA17; PIOA -> PIO_CODR |= PIO_PA17; PIOA -> PIO_PER |= PIO_PA17; PIOA -> PIO_OER |= PIO_PA17;

//______DACPINS______

//Communication Select PIOC -> PIO_IDR |= PIO_PC17; PIOC -> PIO_PUER |= PIO_PC17; PIOC -> PIO_MDDR |= PIO_PC17; PIOC -> PIO_CODR |= PIO_PC17; PIOC -> PIO_PER |= PIO_PC17; PIOC -> PIO_OER |= PIO_PC17;

//Clock PIOA -> PIO_IDR |= PIO_PA1; PIOA -> PIO_PUER |= PIO_PA1; PIOA -> PIO_MDDR |= PIO_PA1; PIOA -> PIO_CODR |= PIO_PA1; PIOA -> PIO_PER |= PIO_PA1; PIOA -> PIO_OER |= PIO_PA1;

//Serial Data In(to theDAC) PIOC -> PIO_IDR |= PIO_PC16; PIOC -> PIO_PUER |= PIO_PC16; PIOC -> PIO_MDDR |= PIO_PC16; PIOC -> PIO_CODR |= PIO_PC16; PIOC -> PIO_PER |= PIO_PC16; PIOC -> PIO_OER |= PIO_PC16;

//______LEDS______//____ See LED_utils.c for the macro functions to turn them on and off easily.

//LED1

140 PIOC -> PIO_IDR |= PIO_PC30; PIOC -> PIO_PUER |= PIO_PC30; PIOC -> PIO_MDDR |= PIO_PC30; PIOC -> PIO_CODR |= PIO_PC30; PIOC -> PIO_PER |= PIO_PC30; PIOC -> PIO_OER |= PIO_PC30;

//LED2 PIOB -> PIO_IDR |= PIO_PB2; PIOB -> PIO_PUER |= PIO_PB2; PIOB -> PIO_MDDR |= PIO_PB2; PIOB -> PIO_CODR |= PIO_PB2; PIOB -> PIO_PER |= PIO_PB2; PIOB -> PIO_OER |= PIO_PB2;

//LED3 PIOB -> PIO_IDR |= PIO_PB3; PIOB -> PIO_PUER |= PIO_PB3; PIOB -> PIO_MDDR |= PIO_PB3; PIOB -> PIO_CODR |= PIO_PB3; PIOB -> PIO_PER |= PIO_PB3; PIOB -> PIO_OER |= PIO_PB3;

//LED4 PIOC -> PIO_IDR |= PIO_PC31; PIOC -> PIO_PUER |= PIO_PC31; PIOC -> PIO_MDDR |= PIO_PC31; PIOC -> PIO_CODR |= PIO_PC31; PIOC -> PIO_PER |= PIO_PC31; PIOC -> PIO_OER |= PIO_PC31;

//Input Pin for the Encoded Signal PIOA -> PIO_PUER |= PIO_PA6;//Enable the pull_up on this pin or use: pio_pull_up(PIOA, PIO_PA24, 1); //PIOA ->PIO_IFDR= PIO_PA24;//Disable the input filter PIOA -> PIO_PER |= PIO_PA6;//SetPER to make itaGPIO pin instead ofa peripheral module PIOA -> PIO_ODR |= PIO_PA6;//make the pin input(default) PIOA-> PIO_ISR;//Clear the Interrupt Status Register First NVIC_DisableIRQ(PIOA_IRQn);//ThePIO must be configured as anNVIC interrupt source as well. NVIC_ClearPendingIRQ(PIOA_IRQn); NVIC_SetPriority(PIOA_IRQn ,0); NVIC_EnableIRQ(PIOA_IRQn); pio_handler_set(PIOA,ID_PIOA,PIO_PA6,PIO_IT_EDGE,pin_edge_handler); PIOA -> PIO_IER |= PIO_PA6;//Enable interrupt on this pin for any edge

141 } int main (void) { sysclk_init();//Initialize the System clock(Atmel Routine that was modifed to use an external crystal) pin_setup();//Setup the pins(function above) WDT->WDT_MR = WDT_MR_WDDIS;//Disable the watchdog timer delay_init(F_CPU);//Setup the Delay function(can be used for debugging) lcd_pin_setup();//Setup theLCD Pins lcd_init();//Initialize theLCD output data_recovery_setup();//Setup the Data Recovery Variables recovered_clock_02_init(4000);//Setup the Timer for the Data Recovery on Timer Module 0, Timer2 to4kHz (4x the Data rate) control_setup();//Setup the Vpth Pins Control Variables eff_calculations_setup();//Setup the Efficiency Calculation Variables dacc_setup();//Setup theDAC variables dacc_clock_00_init(800000);//Setup the Timer for theDAC on Timer Module 0, Timer0 to 800 ,000kHz adc_setup();//Setup theADC variables adc_timer_11_init(200);//Setup the Timer for theADC on Timer Module 1, Timer1 to starta new round of sampling at 200Hz. down_link_clock_10_init(2000);//Setup the Timer for the down link communication clock on Timer Module 1, Timer0 to2kHz(Data rate is1kHz)

while (1) { //delay_ms(1000);//Little Test code //toggle_led_1(); }

}

//______//adc_utils.c //______//This code is responsible for running theADC to determine the input current, voltage and variable battery current setpoint.

#include"adc_utils.h" #include"lcd_utils.h" #include"efficiency_finder_utils.h" #include"data_recovery.h" #include"led_utils.h" #include"gpio_utils.h"

142 //______ADC Functions______void adc_timer_11_init(uint32_t frequ) { uint32_t ra, rc; pmc_enable_periph_clk(ID_TC4); tc_init(TC1, 1, (0 x3u << 0)// Waveform Clock Selection= Clock4=MCK/128(fromPMC) | (0x1u << 15)// Waveform mode is enabled,0 for capture mode | (0x1u << 16)//RA Compare Effect onTIOA: set | (0x2u << 18)//RC Compare Effect onTIOA: clear | (0x2u << 13)// Counter only countsUP with reset onRC Compare ); rc = 120000000/(128*(frequ)); tc_write_rc(TC1, 1, rc); ra = (50 * rc) / 100;//needRA forTIOA trigger ofADC tc_enable_interrupt(TC1,1,TC_IER_CPCS);// Enable interrupt onRC compare tc_write_ra(TC1, 1, ra); // ConfigureTC interrupts forDME //tc_enable_interrupt(TC0,1,TC_IER_CPCS);// Enable interrupt onRC compare NVIC_DisableIRQ(TC4_IRQn); NVIC_ClearPendingIRQ(TC4_IRQn); NVIC_SetPriority(TC4_IRQn,1); NVIC_EnableIRQ(TC4_IRQn); // EnableTCTC_CHANNEL_WAVEFORM. tc_start(TC1,1); } uint32_t int_value_2 = 0; uint32_t setpoint = 0;

void TC4_Handler(void){ uint32_t status2 = tc_get_status(TC1,1); adc_start(ADC);//Software trigger to start the next round ofADC calculations }

void adc_setup(void){ batt_v_reading = 0; batt_i_reading = 0; rect_v_reading = 0; lcd_next_state = 0; next_batt_v_message = 0; next_batt_i_message = 0; next_rect_v_message = 0;

143 battery_i_set_point = 0; pmc_enable_periph_clk(ID_ADC); ADC->ADC_CR = ADC_CR_SWRST;/* Reset the controller.*/ ADC->ADC_MR = 0;/* Reset Mode Register.*/ ADC->ADC_PTCR = (ADC_PTCR_RXTDIS | ADC_PTCR_TXTDIS);/* ResetPDC transfer.*/ ADC->ADC_RCR = 0; ADC->ADC_RNCR = 0; volatile uint32_t syst_clk = sysclk_get_cpu_hz(); uint32_t ul_prescal = sysclk_get_cpu_hz() / (2 * ADC_CLOCK) - 1;//Calculate the Prescaler ADC->ADC_MR |= ADC_MR_PRESCAL(ul_prescal);//Set the Prescaler ADC->ADC_MR |= (0x00 << 24);//15, TrackTime= TrackTIM+1* ADCClock Periods, Depends on Impedence of Source, look at Datasheet, minimum by default is 15 ADC->ADC_MR |= (0xAu << 16);//Startup= 640 periods of ADCClock ADC->ADC_MR |= (0x3u << 20);//Settling= 17 periods of ADCClock ADC->ADC_MR |= (0x0u << 4);//0= 12 bits,1= 10bits adc_enable_channel(ADC,ADC_CHANNEL_4);//Enable the3ADC Channels adc_enable_channel(ADC,ADC_CHANNEL_5); adc_enable_channel(ADC,ADC_CHANNEL_13); //ADC->ADC_IER |= (0x1u << 4);//Select channel4 Flag for the Interrupt(not used but could be) adc_enable_interrupt(ADC,ADC_IER_EOC4); ADC->ADC_MR |= (0x0u << 5);//Sleep Bit: Don’t Sleep ADC->ADC_MR |= (0x0u << 6);//Fast Wake up Bit //ADC->ADC_MR |= (0x1u << 1);//Enable Hardware Trigger //ADC->ADC_MR &= ~(0x1u<<0);//Disable Hardware Trigger adc_configure_trigger(ADC,ADC_TRIG_SW ,0);//Usea software trigger which is the adc_start(ADC) command in the Timer4 interrupt routine above //ADC->ADC_MR |= (0x1u << 1);//Triggered by hardware of Timer0 Channel1 NVIC_EnableIRQ(ADC_IRQn);/* EnableADC interrupt.*/ } uint32_t lcd_cnt = 0; float output_power = 0; float input_power = 0;

uint16_t get_batt_i_setpoint(void){ return battery_i_set_point; } int get_input_i(void){ return input_current; }

144 uint16_t get_input_v(void){ return input_voltage; } float get_input_power(void){ return input_power; }

//This routine runs at the end of the the conversion of channel4 and reads all3 active channels. void ADC_Handler(void){ if ((adc_get_status(ADC) & ADC_ISR_EOC4) == ADC_ISR_EOC4){ int battery_i_set_point_temp = 2*adc_get_channel_value(ADC,4);//Scaling for proper range //Filter the battery current setpoint potentiometer voltage witha first order filter with tau = 0.5. The sampling rate is 200Hz. battery_i_set_point = (battery_i_set_point*0.5 + (battery_i_set_point_temp)*0.005)/(0.505); int input_current_temp = adc_get_channel_value(ADC,13); //Filter the input current reading witha first order filter with tau= 0.2. The sampling rate is 200Hz. input_current = (input_current*0.2 + (input_current_temp)*0.005)/(0.205); input_voltage = adc_get_channel_value(ADC,5); } NVIC_ClearPendingIRQ (ADC_IRQn); }

//______//adc_utils.h //______//This code is the header file for the adc_utils.c

#include

#ifndefADC_UTILS_H_ #defineADC_UTILS_H_

//______ADC Declartions and Definations______

#defineADC_CLOCK 6400000 //6.4Mhz, Max is 16MHz and min is1Mhz uint32_t batt_v_reading; uint32_t batt_i_reading; uint32_t rect_v_reading; uint32_t lcd_next_state; uint16_t next_batt_v_message; uint16_t next_batt_i_message;

145 uint16_t next_rect_v_message; uint16_t battery_i_set_point; int input_current; uint16_t input_voltage; float input_power; void timer0_0_setup(void); void adc_setup(void); void adc_timer_11_init(uint32_t); uint32_t get_batt_v_reading(void); uint32_t get_batt_i_reading(void); uint32_t get_rect_v_reading(void); uint16_t get_batt_i_setpoint(void); int get_input_i(void); uint16_t get_input_v(void); float get_input_power(void); void prepare_next_batt_v_message(void); void prepare_next_batt_i_message(void); void prepare_next_rect_v_message(void); uint16_t get_next_batt_v_message(void); uint16_t get_next_batt_i_message(void); uint16_t get_next_rect_v_message(void);

#endif/*ADC_UTILS_H_*/

//______//control.c //______//This code is responsible for calculating the error in the battery current and voltage and then calculating thePID output to theDAC

#include"control.h" #include"adc_utils.h" #include"data_recovery.h" #include"led_utils.h" #include"efficiency_finder_utils.h" #include"gpio_utils.h" #include"lcd_utils.h" #include"rectified_voltage_utils.h"

146 //Intializing the Control Variables void control_setup(void){ battery_voltage = 0;//(int) Initialize the battery Voltage reading to0 battery_current = 0;//(int) Initialize the battery Current reading to0

current_error = 0;//(float) Initialize the battery current error to0 voltage_error = 0;//(float) Initialize the battery voltage error to0

current_target = 0;//(int) Initialize the battery current target to0 voltage_target = 0;//(int) Initialize the battery current target to0

current_error_gain = 5;//Initialize the gain for the error in the battery current voltage_error_gain = 100;//Initialize the gain for the error in the battery voltage max_error = 2500;//Set the maximum error in either the battery voltage or current to be 2500 min_error = -2500;//Set the minimum error in either the battery voltage or current to be -2500

combined_error = 0;//(float) Initialize the combined battery current and voltage error to 0. previous_combined_error = 0;//(float) Initialize the previous combined battery current and voltage error to 0.

previous_combined_command = 0;//(int) Initialize the previous combinedDAC command to 0. combined_command = 0;//(int) Initialize the combinedDAC command to 0.

efficiency_sum_count = 0;//(int) Initialize the counter for the efficiency readings to0 efficiency_float_sum = 0;//(float) Initialize the sum for the efficiency readings to0 efficiency_float_avg = 0;//(float) Initialize the calculated and averaged efficiency value to 0.

battery_charged = 0;//Clear the battery charged flag reset_best_cap = 0;//flag to reset the best capacitor for communcication fora given rectified voltage

eff_8 = 0;//Set the efficiency fora Rectified Voltage of8 to0 initially eff_9 = 0;//Set the efficiency fora Rectified Voltage of8 to0 initially eff_10 = 0;//Set the efficiency fora Rectified Voltage of8 to0 initially eff_11 = 0;//Set the efficiency fora Rectified Voltage of8 to0 initially eff_12 = 0;//Set the efficiency fora Rectified Voltage of8 to0 initially eff_13 = 0;//Set the efficiency fora Rectified Voltage of8 to0 initially

small_error_count = 0;

147 small_error = 0;

finish = 0; finalize_rectified_voltage_state = 3;

input_power_float_region = 0; trickle_charge = 1;//Set the flag to be in the trickle charge region until proven otherwise. battery_charged_count = 0; max_command = 0; first_time = 1; } void reset_efficiencies(void){//This function is called every time communication is lost and then recovered eff_8 = 0;//so that the efficiency algorithm can start over. eff_9 = 0; eff_10 = 0; eff_11 = 0; eff_12 = 0; eff_13 = 0; } uint32_t set_power(void){ //= (2.915)*(1.985/4096)*(4096/5)(Recieved Bits* (~3x scaling to undo on board voltage division)*(RxADC Reference scaling)* Normalizing battery_voltage = (get_batt_v_received()*1.1573);//= (2.915)*(1.985/4096)*(4096/5)(Recieved Bits* (~3x scaling to undo on board voltage division)*(RxADC Reference scaling)* Normalizing to5V battery_current = (get_batt_i_received() - 494);//subtract the offset created by the resistor mismatch in the current sense amplifier //Actual battery Current=(received value- 494)*(1.985/4096)*(1/2.717) //float=(received int- 494)*(1/ReceiverADC Gain)*(1/Currense Sense Amplifier Gain) if(battery_voltage < ((2.7/5)*4096) ){//Enter the Trickle Charge Region if the battery voltage is less than 2.7V trickle_charge = 1; current_target = 400;// 400 /5.5876~ 85mA max_error = 2700; min_error = -2700; //GPIO_10_ON;//Debug: Trickle Charge Flag } else if( (trickle_charge == 1) & (battery_voltage > ((2.8/5)*4096)) ){//If the battery was in the trickle charge region then do not leave until the battery voltage is greater than 2.8V. first_time = 1; //current_target= (2500);//= float target* (4096/1.985)* 2.717, so(int) 2500~(float) 446 mA //= float target*(receiver adc conversation gain)*(gain of current sense amplifier on receiver)

148 current_target = get_batt_i_setpoint();//Set the battery current target from the potentiometer //current_target= 2100;//Or set it manually toa fixed value if(current_target > 2700){//But do not let it get abovea fixed value, here 2700~ 480 mA current_target = 2700; } trickle_charge = 0;//Clear the trickle charge flag //GPIO_10_OFF;//Debug } else if(trickle_charge == 0){//If the battery has been out of the trickle charge region then set the battery target accordingly. current_target = get_batt_i_setpoint();//Variable setpoint //current_target= 2500;//= float target* (4096/1.985)* 2.717, so(int) 2500~(float) 446 mA if(current_target > 2700){//but do not let it get above 2700~ 480 mA current_target = 2700; } } voltage_target = (4.2/5)*4096;//Set the battery voltage target. current_error = current_error_gain*(current_target - battery_current);//(float) the amplified volage error voltage_error = voltage_error_gain*(voltage_target - battery_voltage);//(float) the amplified current error if(current_error > max_error) current_error = max_error;//Do not let the errors exceed the max or min errors if(current_error < min_error) current_error = min_error; if(voltage_error > max_error) voltage_error = max_error; if(voltage_error < min_error) voltage_error = min_error; if(voltage_error == max_error){ LED_2_ON ;//Debug: This lets you know when the control is not dependent on the battery voltage because the reading has saturated. } else{//if the battery voltage error has not saturated then it means the battery voltage is approaching if(finish == 0){//the target voltage and the rectified voltage should not change. finalize_rectified_voltage_state = rectified_voltage_state;//During the last little bit of charging it is advantageous to not change the rectified voltage }//for the sake of maintaining the communication. Therefore, right before it enters the final finish = 1;//charging state, save the rectified voltage value. LED_2_OFF ;//Set the Flag to enter the final charging control region }

149 if(battery_voltage < ((4.1/5)*4096)) {//If however the the battery voltage drops below 4.1V then leave the final control region finish = 0; } else{ if(finish == 0){ finalize_rectified_voltage_state = rectified_voltage_state;//save over the rectified voltage every time it passed under 4.1 Volts. } finish = 1; } previous_combined_error = combined_error;//(float) Shift the combined error to the previous combined error combined_error = current_error + voltage_error - max_error;//(float) Calculate the new combined error //Pass the error througha first order filter with tau= 0.4. combined_error = (previous_combined_error*0.4 + combined_error*0.08)/(0.48);// error= .2*previous+ .08*new /(.2+.08) //Debug for monitoring the combined error if( abs(combined_error) < 50){ GPIO_6_ON ; } else{ GPIO_6_OFF; } //Debug for monitoring the combined error if( abs(combined_error) < 200){ GPIO_2_ON ; } else{ GPIO_2_OFF; } previous_combined_command = combined_command;//(int) Shift the combined command to the previous combined command

//If the combined error is less than 100~4mA then the error is small enough to calculate the efficiency. //If the command is maxed out then the system has reached steady state. if( (abs(combined_error) < 100) || (max_command == 1) ){ GPIO_1_ON ;//Debug small_error_count = 0; small_error = 1; //combined_error= 0;//dont let the error integrate calculate_float_rectified_voltage();//Calculate the rectified voltage rectified_voltage = 1*(rectified_voltage_float + 0.5);

150 if (rectified_voltage == previous_rectified_voltage){ previous_rectified_voltage = rectified_voltage; } else{//Restart the calculation because the rectified voltage changed. efficiency_float_sum = 0; efficiency_sum_count = 0; previous_rectified_voltage = rectified_voltage; } calculate_float_battery_current(); calculate_float_battery_voltage(); calculate_float_battery_power(); calculate_float_input_power(); calculate_float_efficiency();//recalculate the efficiency efficiency_float_sum += efficiency_float; efficiency_sum_count += 1; if(efficiency_sum_count >= 15){//After 15 calculations efficiency_sum_count = 0; efficiency_float_avg = efficiency_float_sum/15;//calculate the average //toggle_gpio_6(); calculate_float_rectified_voltage(); rectified_voltage = 1*(rectified_voltage_float + 0.5); input_float_power_to_lcd(input_power_float);//Send the Rect Voltage to theLCD rect_v_approx_to_lcd(rectified_voltage); change_rectified_voltage();//Based on the efficiency calculation and rectified voltage state senda command to the receiver to change the rectified voltage eff_to_lcd(efficiency_float_avg); efficiency_float_sum = 0;//clear for the next calculation } //Using the values of Kp= 0.1 and Ki= 0.1 for thePID controller the following difference equation was derived for theDAC command. combined_command = previous_combined_command + (0.104*combined_error) - (0.096* previous_combined_error); }

else{//If the system has not reached Steady State then do not calculate the efficiency GPIO_1_OFF; toggle_led_3();//Debug efficiency_float_sum = 0; efficiency_sum_count = 0; calculate_float_rectified_voltage();//Make sure Rectified Voltage is less thana maximum limit combined_command = previous_combined_command + (0.104*combined_error) - (0.096* previous_combined_error);//Calculate theDAC output with the same equation as above. if(finish == 1){ combined_command = previous_combined_command + (0.104*combined_error) - (0.096* previous_combined_error);//During the final charging section it may be

151 advantageous to lower thePID gain. Currently this is not being used } } if(rectified_voltage_float > 15){//If the rectified voltage is too high combined_command = last_chirp;//automatically reduce theDAC command to the minimal needed for communication. } //If the battery voltage has almost reached the target voltage and the battery current is very small then consider the battery charged if( (battery_voltage > (4.195/5)*4096) & (battery_current < 5)) { toggle_led_4(); battery_charged = 1; combined_command = 0; } //If the battery voltage was considered charged but then the battery current is too high then ramp down the battery current. if( (battery_charged) & (battery_current > 10) ){ combined_command = combined_command - 5; // toggle_led_2(); } //If the battery voltage was considered charged but then it dropped in voltage bya sufficient amount then restart the charging cycle. if( (battery_charged) & (battery_voltage < ((.975*4.2/5)*4096)) ){ battery_charged = 0; finish = 0; } //If the control needs to be restarted then set the output to the threshold value needed for communication. This will happen after communication is established followinga chirp. if(restart_control){ combined_command = last_chirp; restart_control= 0; //toggle_gpio_6(); } //Limit the max command toa certain value if( (combined_command > 2300) & (battery_current < current_target) ) { combined_command = 2300; max_command = 1; toggle_led_4(); } else{ max_command = 0; } if(combined_command < 0) combined_command = 0;//Do not let the combined command go below 0.

152 //This isa high frequency filter to cut out any very large change in commands due toa very erroneous reading. if( abs(combined_command - previous_combined_command) > 1000 ){ combined_command = previous_combined_command; //toggle_gpio_11(); } return combined_command;//Send the command value to theDAC }

//______//control.h //______//This code is the header file for the control.c

#include

#ifndefCONTROL_H_ #defineCONTROL_H_ uint32_t set_power(void); uint32_t set_power_debug(void); void control_setup(void); int battery_voltage; int previous_battery_voltage; int battery_voltage_filter_count; int battery_current; int previous_battery_current; int battery_current_filter_count; float current_error; float voltage_error; int current_target; int voltage_target; float current_error_gain; float voltage_error_gain; int max_error; int min_error;

153 float combined_error; float previous_combined_error; int previous_combined_command; int combined_command; float efficiency_float_sum; uint32_t efficiency_sum_count; float efficiency_float_avg; uint32_t battery_charged; float eff_8; float eff_9; float eff_10; float eff_11; float eff_12; float eff_13; void reset_efficiencies(void); float input_power_float_region; uint32_t input_power_region_set; int reset_best_cap; int finalize_rectified_voltage_state; int finish; int small_error; int small_error_count; uint32_t trickle_charge; uint32_t battery_charged_count; uint32_t max_command; uint32_t first_time;

#endif/*CONTROL_H_*/

//______//dacc_utils.c //______//This code is responsible for driving theLTC 2624DAC to drive hte LTC4125 Vpth Pins. //See the Datasheet for more information: http://cds.linear.com/docs/en/datasheet/2604fd.pdf

#include"dacc_utils.h" #include"adc_utils.h" #include"data_recovery.h"

154 #include"control.h" #include"down_link_utils.h" #include"lcd_utils.h" #include"led_utils.h" #include"gpio_utils.h" #include"efficiency_finder_utils.h"

//Setup theDAC Timer void dacc_clock_00_init(uint32_t frequ) { uint32_t ra, rc;

pmc_enable_periph_clk(ID_TC0);

// InitTC to waveform mode. tc_init(TC0, 0, (0 x0u << 0)// Waveform Clock Selection= Clock4=MCK/2(fromPMC) | (0x1u << 15)// Waveform mode is enabled,0 for capture mode | (0x1u << 16)//RA Compare Effect onTIOA: set | (0x2u << 18)//RC Compare Effect onTIOA: clear | (0x2u << 13)// Counter only countsUP with reset onRC Compare ); rc = 120000000/(2*(frequ)); tc_write_rc(TC0, 0, rc); ra = (50 * rc) / 100; tc_write_ra(TC0, 0, ra); tc_enable_interrupt(TC0,0,TC_IER_CPCS);// Enable interrupt onRC compare // ConfigureTC interrupts NVIC_DisableIRQ(TC0_IRQn); NVIC_ClearPendingIRQ(TC0_IRQn); NVIC_SetPriority(TC0_IRQn,0); NVIC_EnableIRQ(TC0_IRQn); tc_start(TC0, 0); }

void dacc_setup(void){ dacc_clk_division = 0;//Each dac bit requires4 divisions of the clock and this variable keeps track of them dacc_buffer = 0;//Each message is 24 bits:4 command bits,4 address bits, 12 data bits and4 don’t care bits. dacc_bit_count = 0;//Dac bit counter dacc_message = 0;//Initialize the Dac message to 0. next_dacc_message_set_cs = 0;//Initialize the set cs flag state to0 next_dacc_message_clear_cs = 0;//Initialize the clear cs flag state to0

155 dacc_reset_count = 0;//Counter for the set and clear cs flag states chirp = 0;//Chirp Command for establishing communication amp_mod = 0;//Modulated amplitude’s flag power_tx = 0;//Value returned from the control function to write to theDAC downlink_mod_amp = 90;//Initialize Amplitude of Amplitude modulation. This gets updated to be proportional to the output level. eff_search_count = 0;//Initialize the periodic counter to send the Efficiency value to theLCD chirp_count = 0;//Initialize the counter for the chirping ramp to 0. power_tx_mod_duty_cycle = 0;

debug_count = 0;//Use this counter to switch between the4 possible Dac channels.

} void prepare_dacc_buffer(void){ if (dacc_message == 0){ if(communication_synced){ if(new_current_measurement){//Only update theDAC command aftera new battery current message has been received toggle_led_1(); new_current_measurement = 0;//Reset the new battery current message flag power_tx = set_power();//Calculate theDAC command eff_search_count += 1; if(eff_search_count == 80){//Periodically rewrite the efficiency value to theLCD battery_float_power_to_lcd(battery_power_float); eff_search_count = 0; } } } else{//If the communication is not synced then ramp up the command at about 75mV/sec to2V. chirp_count += 1; if(chirp_count > 60){ chirp_count = 0; //toggle_gpio_4(); chirp += 1; power_tx = chirp; if(chirp > 2500){//If the command gets to2V then reset it. It would be good to adda pause here before restarting the chirp. chirp = 0; } } amp_mod = 0; amp_mod = get_additional_power();//Check the downlink Communication control to see if the command should be modulated

156 downlink_mod_amp = power_tx/10;//Createa proportional amplitude change for the amplitude modulation if (downlink_mod_amp < 90){ downlink_mod_amp = 90; } if (amp_mod == 1){//Adda positive amplitude shift for downlink communication power_tx_mod_duty_cycle = power_tx + downlink_mod_amp; } else if (amp_mod == -1){//Adda negative amplitude shift for downlink communication power_tx_mod_duty_cycle = power_tx - downlink_mod_amp; } else{ power_tx_mod_duty_cycle = power_tx;//No communication } if(power_tx_mod_duty_cycle < 0){//Do not allow the amplitude modulation to make the command less than 0. power_tx_mod_duty_cycle = 0; } dacc_buffer = 0x300000 + 0x00000 + (power_tx_mod_duty_cycle << 4);//Write the 12 bit command to theDAC (24 bits are needed per write) dacc_message = 0;//reset the message debug_count += 1;//If you want to use multiple channels on theDAC then use this counter if(debug_count > 5){//to switch between channel0 which is the main command channel and the other3 channels by changing the variable"dacc_message". debug_count = 0; dacc_message = 1; } } } else if(dacc_message == 1){//This first channel for example was used to write the error to the DAC every6thDAC write. uint32_t value_6 = combined_error; dacc_buffer = 0x300000 + 0x30000 + (value_6 << 4); dacc_message = 0;//It then returns theDAC channel to the main LTC4125 command channel } else if(dacc_message == 2){ uint32_t value_3 = get_batt_i_setpoint();//This one is setup to write the battery set point value. dacc_buffer = 0x300000 + 0x00000 + (value_3 << 4); dacc_message = 2; } else if(dacc_message == 3){ dacc_message = 0; dacc_buffer = 0;

157 dacc_buffer = 0x300000 + 0x00000 + (1500 << 4);//This is just writinga fixed value for debug purposes. } } uint32_t value_3 = 0;//Defining and declaring this debug variable.

//The interrupt function for theDAC, called at theDAC Timer Frequency void TC0_Handler(void){ uint32_t status2 = tc_get_status(TC0,0); if(next_dacc_message_set_cs){//Raise the cs flag and clear theSDI and clk fora few cycles dacc_reset_count += 1; if(dacc_reset_count >3){//Aftera few cycles lower the cs flag dacc_reset_count = 0; next_dacc_message_set_cs = 0; next_dacc_message_clear_cs = 1; }

PIOC -> PIO_SODR |= PIO_PC17;//Raise the cs flag PIOA -> PIO_CODR |= PIO_PA1;//clear the clock PIOC -> PIO_CODR |= PIO_PC16;//Clear theSDI pin }

else if (next_dacc_message_clear_cs){//lower the flag and keep theSDI and clk cleared fora few cycles dacc_reset_count += 1; if(dacc_reset_count >3){ dacc_reset_count = 0; next_dacc_message_clear_cs = 0;//lower the clear_cs flag and send the data to theDAC next prepare_dacc_buffer(); } PIOC -> PIO_CODR |= PIO_PC17;//lower theCS flag PIOA -> PIO_CODR |= PIO_PA1;//clear the clock PIOC -> PIO_CODR |= PIO_PC16;//Clear theSDI pin }

else{//Start theDATA transfer, each bit is divided into4 regions to properly set theDAC pins switch(dacc_clk_division){ case 0: //Step 0: Clear the clock and set the Data pin to0 or 1. PIOA -> PIO_CODR |= PIO_PA1;//clear the clock if ( (dacc_buffer & (0x1<<23)) == (0x1<<23) ){//If the next bit to send isa 1 then setSDI PIOC -> PIO_SODR |= PIO_PC16;//Set theSDI pin }

158 else{ PIOC -> PIO_CODR |= PIO_PC16;//Clear theSDI pin } dacc_buffer = (dacc_buffer << 1);//Shift theDAC buffer dacc_bit_count += 1;//Increment the counter dacc_clk_division = 1; break; case 1://Step 1://keep the clock low and theSDIPIN status PIOA -> PIO_CODR |= PIO_PA1; dacc_clk_division = 2; break; case 2://Step 2: Set the clock high and keep theSDI pin status PIOA -> PIO_SODR |= PIO_PA1; dacc_clk_division = 3; break; case 3://Step 4: Finish the bit cycle and repeat dacc_clk_division = 0; if(dacc_bit_count > 23){//If all 24 bits have been sent then reset the counter dacc_bit_count = 0; next_dacc_message_set_cs = 1;//and raise theCS flag } break; } } }

//______//dacc_utils.h //______//This code is the header file for the dacc_utils.c

#include

#ifndefDACC_UTILS_H_ #defineDACC_UTILS_H_

//Whena conversion is completed, the resulting analog value is available at the selectedDACC channel output and theEOC bit in theDACC Interrupt Status Register(DACC_ISR) is set. Reading theDACC_ISR clears the EOC bit.

//DAC0 is pin 10 on the spare signals of the board and PB13 of the chip #defineDACC_ANALOG_CONTROL(DACC_ACR_IBCTLCH0(0x02)\ | DACC_ACR_IBCTLCH1(0x02) \ | DACC_ACR_IBCTLDACCORE(0x01))

159 void dacc_setup(void); void prepare_dacc_buffer(void); void dacc_clock_00_init(uint32_t); uint32_t dacc_clk_division; uint32_t dacc_buffer;//need 24 bits,4 for command, 12 data,4 dont care uint32_t dacc_bit_count; uint32_t dacc_message; uint32_t next_dacc_message_set_cs; uint32_t next_dacc_message_clear_cs; uint32_t dacc_reset_count; int chirp; int power_tx; uint32_t amp_mod; int downlink_mod_amp; uint32_t eff_search_count; uint32_t chirp_count; int power_tx_mod_duty_cycle; int debug_count;

#endif/*DACC_UTILS_H_*/

//______//data_recovery.c //______//This code is responsible for decoding the communication signal for the uplink communication.

#include"data_recovery.h" #include"lcd_utils.h" #include"down_link_utils.h" #include"led_utils.h" #include"gpio_utils.h" #include"dacc_utils.h" #include"control.h" uint32_t toggle = 0; uint32_t cycle_count = 0;

//This is the interrupt routine for the Encoded Signal Input on pin PA6 void pin_edge_handler(const uint32_t id, const uint32_t index){ if ((id == ID_PIOA) && (index == PIO_PA6)){ if (clock_mask == 0){ tc_start(TC0,2);//when the encoded signal on pin5 has an edge start the clock GPIO_4_ON ;//Debug: Set the clock high to start the bit clock cycle

160 clock_mask = 1; recovered_clk_quarter = 0; } } }

void recovered_clock_02_init(uint32_t frequ) { uint32_t ra, rc; pmc_enable_periph_clk(ID_TC2); // InitTC to waveform mode. tc_init(TC0, 2, (0 x1u << 0)// Waveform Clock Selection= Clock4=MCK/8(fromPMC) | (0x1u << 15)// Waveform mode is enabled,0 for capture mode | (0x1u << 16)//RA Compare Effect onTIOA: set | (0x2u << 18)//RC Compare Effect onTIOA: clear | (0x2u << 13)// Counter only countsUP with reset onRC Compare ); rc = 120000000/(8*(frequ)); tc_write_rc(TC0, 2, rc); ra = (50 * rc) / 100; tc_write_ra(TC0, 2, ra); tc_enable_interrupt(TC0,2,TC_IER_CPCS);// Enable interrupt onRC compare // ConfigureTC interrupts NVIC_DisableIRQ(TC2_IRQn); NVIC_ClearPendingIRQ(TC2_IRQn); NVIC_SetPriority(TC2_IRQn,0); NVIC_EnableIRQ(TC2_IRQn); }

//Initialize all the values to 0. void data_recovery_setup(void){ clock_recovered = 0; rx_clk = 0; reading = 0; old_reading = 0; bad_reading = 0; readings_register = 0; data_synced = 0; state = 0; rx_clk_recovered = 0; new_bit = 0; next_bit = 0; recovered_clk_quarter = 0;

161 shift_reg_receive = 0; shift_reg_receive_size = 16; shift_reg_receive_count = 0; batt_v_recieved = 0; batt_i_recieved = 0; rect_v_recieved = 0; clock_mask = 0; parity_count = 0; communication_synced = 0; new_current_measurement = 0; last_chirp = 0; last_chirp_copy = 0; restart_control = 0; rectified_voltage_state_count = 0; rectified_voltage_state = 3;//Start of with 10V,a good value for the trickle charge region. skip_reading = 0; }

/*//This could be used to reset the communication variables.I never needed to use it though. void reset_communication(void){ clock_recovered= 0; rx_clk= 0; reading= 0; old_reading= 0; readings_register= 0; bad_reading= 0; data_synced= 0; state= 0; new_bit= 0; next_bit= 0; recovered_clk_quarter= 0; shift_reg_receive= 0; shift_reg_receive_size= 16; shift_reg_receive_count= 0; batt_v_recieved= 0; //batt_i_recieved= 0; rect_v_recieved= 0; clock_mask= 0; communication_synced= 0; GPIO_6_ON; //lcd_cmd_write(0x01,10);//Display Clear

} */

162 uint32_t silence = 0; void check_re_sync(void){ silence = 0; if ( ((shift_reg_receive & 0x07FFF) == 0x7FFE)){//Check for1 1111 1111 1111 1110 for the resync //clock_synced= 1; //ioport_toggle_pin_level(LED_0_PIN);//Debug To watch resyncing data_synced = 1;//Set the Data Synced Flag to start reading messages parity_count = 0;//Reset the parity bit counter shift_reg_receive_count = 0;//reset the shift register to prepare for data shift_reg_receive = 0;//Clear the input receiver buffer } else if(shift_reg_receive == 0x1FFE0){//check for1 1111 1111 1110 0000 which means it is time to send a Downlink Message data_synced = 1; shift_reg_receive_count = 0; parity_count = 0; shift_reg_receive = 0; clock_mask = 1;//Don’t do Data recovery during this time because its downlink communication time //PIOA ->PIO_SODR |= PIO_PA14;//Debug: Turn on the mask flag silence = 1;//The communication from the receiver should be silent so do not listen. data_synced = 0;//make the system re-sync after the downlink communication tc_start(TC1,0);//start the clock for downlink communication //toggle_led_4();//Debug for watching the downlink communication rate } } void check_bit(void){ if (reading == old_reading){//If the two readings on each side of the negative clock edge are the same then shift_reg_receive = (shift_reg_receive << 1);//the data value is 0. Write this into the data receive buffer. next_bit = 0;//Declare the bit to be 0. } else{//If the readings are different then the data value is 1. shift_reg_receive = (shift_reg_receive << 1);//Shift the data receive buffer1 to the left. shift_reg_receive = shift_reg_receive |= 1;//Add1 to the data receive buffer next_bit = 1;//Declare the bit to be 1. parity_count += 1;//Increase the parity bit counter } }

163 void read_signal(void){ if(((PIOA->PIO_PDSR) & (1u << 6)) == (1u << 6)) {//Read the Digital Input status of PA6 reading = 1;//If it is high then the reading is 1. readings_register = (readings_register << 1);//Shift the data readings register1 to the left. readings_register = (readings_register |= 1);//Add1 to the readings register //GPIO_6_ON;//Debug } else{ reading = 0;//Otherwise if the signal is low then the reading is0 readings_register = (readings_register << 1);//Shift the data readings register1 to the left. //GPIO_6_OFF;//Debug } } uint32_t current_reading_recieved_cnt = 0; uint32_t current_zero_filter_count = 0;

//Read the data receive buffer void check_shift_reg_receive(void){ shift_reg_receive = (shift_reg_receive >> 1);//Get rid of the parity bit before reading the data messages

//Battery Voltage Reading if ((shift_reg_receive | 0x0FFF) == 0x3FFF){//Check the Header if it matches the battery voltage header. if(restarting_communication_voltage){//Check the flag that is set after the downlink communication restarting_communication_voltage = 0;//Clear the flag if it was set. shift_reg_receive = batt_v_recieved;//Don’t consider the first message after re- syncing...it can be corrupted } //Filter the battery voltage witha first order filter of tau= 0.4 batt_v_recieved = (batt_v_recieved*0.4 + (shift_reg_receive & 0x0FFF)*0.08)/(0.48); bad_reading = 0;//reset the bad reading counter becausea good reading was received shift_reg_receive = 0;//Reset the receive data buffer } //Battery Current Reading else if ((shift_reg_receive | 0x0FFF) == 0x6FFF){//Check the Header if it matches the battery current header. if(restarting_communication_current){//Check the flag that is set after the downlink communication restarting_communication_current = 0;//Clear the flag if it was set.

164 shift_reg_receive = batt_i_recieved;//Don’t consider the first message after re-syncing...it can be corrupted } //If the reading is very different than the current value then ignore it because it is probably an error. if( (abs(batt_i_recieved - (shift_reg_receive & 0x0FFF)) > 500) & (trickle_charge == 1) ){ shift_reg_receive = batt_i_recieved; GPIO_3_OFF;//Debug: Look for Burps in the received Current. } //If the reading is different bya value of 150 skip it one time, then believe it. This createsa fast low pass filter to eliminate very high frequency errors. else if( (abs(batt_i_recieved - (shift_reg_receive & 0x0FFF)) > 150) & (trickle_charge == 0) ) { if( skip_reading == 1){ shift_reg_receive = batt_i_recieved;//Ignore the reading the first time skip_reading = 0;//Don’t ignore next time GPIO_3_OFF;//Debug: Look for Burps in the received Current. } } else{ GPIO_3_ON ;//Debug: Readings are steady skip_reading = 1;//If the readings are good then reset the ignore reading flag } //Read the current value and applya first order filter to it with tau= 0.4 batt_i_recieved = (batt_i_recieved*0.4 + (shift_reg_receive & 0x0FFF)*0.08)/(0.48); current_reading_recieved_cnt += 1;//Increment the current reading counter. This is used for establishing communication new_current_measurement = 1;//Set the new current reading flag to signal to the controller to update the LTC4125 Vpth Command toggle_gpio_11();//Debug: shows thata new battery current message has been received. if (current_reading_recieved_cnt > 15){//During the chirping, once enough battery current messages have been received, communication is established if(communication_synced == 0){//only come here if restarting communication aftera chirp communication_synced = 1;//Set the communication synced flag restart_control = 1;//restart the control last_chirp = chirp;//Save the last chirp to be used asa reference for the threshold of communication last_chirp_copy = chirp;//Savea copy too GPIO_13_ON;//Debug: Shows that the communication has been established. }

165 current_reading_recieved_cnt = 0;//Reset the current reading received count for re-establishing communication in the future. } bad_reading = 0;//reset the bad reading counter becausea good reading was received shift_reg_receive = 0;//Reset the receive data buffer } //Rectified Volage Reading else if ((shift_reg_receive | 0x0FFF) == 0xCFFF){ //Filter the rectified voltage reading witha first order filter of tau= 0.2 rect_v_recieved = (rect_v_recieved*0.2 + (shift_reg_receive & 0x0FFF)*0.08)/(0.28); bad_reading = 0;//reset the bad reading counter becausea good reading was received shift_reg_receive = 0;//Reset the receive data buffer } else{//If the header bits do not match any of the message headers then maybe communication is broken or corrupted bad_reading += 1;//Increment the bad reading counter if (bad_reading >= 400){//If the bad reading counter reachesa certain value then restart the chirping to re-establish communication from the beginning bad_reading = 0;//Witha value of 400 this would take about 6.5 seconds: .016*400= 6.4 seconds data_synced = 0; chirp = 0;//reset the chirp value to start from 0. communication_synced = 0; //GPIO_6_OFF;//Debug } } } //These functions return the fitlered received values. uint32_t get_batt_v_received(void){ return batt_v_recieved; } uint32_t get_batt_i_received(void){ return batt_i_recieved; } uint32_t get_rect_v_received(void){ return rect_v_recieved; }

//This is the interrupt routine to recover the data from the encoded signal. The clock is started at an edge transition on the Digital Input pin A6 void TC2_Handler(void){ uint32_t status2 = tc_get_status(TC0,2);

166 switch(recovered_clk_quarter){//The data is read by usinga4kHz clock in order to read on both sides of the data clock transitions case 0://At the first timer overflow it is 25% into the data period GPIO_4_ON ;//Debug: Keep the clock high read_signal();//read the signal before the negative data clock transition GPIO_5_ON ;//Debug: Set High for First Reading //if(reading)PIOC ->PIO_SODR |= PIO_PC22;//Debug: If the reading is high, set reading debug pin //elsePIOC ->PIO_CODR |= PIO_PC22;//Debug: else if its low clear the reading debug pin recovered_clk_quarter = 1; break; case 1://At the second timer overflow it is 50% into the data period GPIO_4_OFF;//Debug: clear the clock for the negative transition recovered_clk_quarter = 2; old_reading = reading;//update the value of the old reading with the reading done in case0 break; case 2://At the third timer overflow it is 75% into the data period GPIO_4_OFF;//Debug: Keep the clock low read_signal();//Read the signal again, this time on the low side of the data clock GPIO_5_OFF;//Debug: Set Low for Second Reading //if(reading)PIOC ->PIO_SODR |= PIO_PC22;//Debug: If the reading is high, set reading debug pin //elsePIOC ->PIO_CODR |= PIO_PC22;//Debug: else if its low clear the reading debug pin recovered_clk_quarter = 3; silence = 0;//clear the flag that would make it not listen because it was time to senda downlink message check_bit();//based on the two readings during case0 and case, check the value of the message bit shift_reg_receive_count += 1;//increment the counter recovered_clk_quarter = 0;//reset the cycle check_re_sync();//check the receive shift buffer fora data resync message(checks every new bit, which allows for quick resyncing) //GPIO_6_OFF; if ( (data_synced == 1) & (shift_reg_receive_count > shift_reg_receive_size) ){//If the shift receive buffer is full then read the buffer shift_reg_receive_count = 0;//reset the counter //reset_best_cap= 1; //GPIO_10_OFF; if (parity_count % 2 == 0){//If the parity bit count is correct then read the message. check_shift_reg_receive();

167 } parity_count = 0;//reset the parity bit counter

if(trickle_charge == 1){//in trickle charge keep the voltage fixed rectified_voltage_state = 3; reset_best_cap = 0; //GPIO_10_ON; } if(finish == 1){ rectified_voltage_state = finalize_rectified_voltage_state;//if the battery is almost charged then keep the rectified voltage fixed }

//Based on the rectified voltage state that the power transmitter wants the power receiver to have, this code sets the downlink shift register to one of the following values. If the receiver should reset its knowledge of the best communication capacitance the"reset best cap" value which has anF for the last for bits is used. The receiver should reset its knowledge of the best cap whenever the efficiency is being recalculated after all the values of been cleared. This is needed whenever the operating point changes significantly such that the input power changes bya certain threshold, say 0.1 Watts. Otherwise, the downlink shift register should just have the command to specify the rectified voltage. switch(rectified_voltage_state){ case 1://Rectified Voltage=8 Volts if(reset_best_cap == 1){ downlink_shift_reg = (0x111F);//Rectified Voltage= 8 Volts and Reset Best cap knowledge toggle_gpio_10(); } else{ downlink_shift_reg = (0x1111);//Rectified Voltage= 8 Volts } break; case 2://Rectified Voltage=9 Volts if(reset_best_cap == 1){ downlink_shift_reg = (0x222F); toggle_gpio_10(); } else{ downlink_shift_reg = (0x2222); } break; case 3://Rectified Voltage= 10 Volts if(reset_best_cap == 1){ downlink_shift_reg = (0x333F);

168 toggle_gpio_10(); } else{ downlink_shift_reg = (0x3333); } break; case 4://Rectified Voltage= 11 Volts if(reset_best_cap == 1){ downlink_shift_reg = (0x444F); toggle_gpio_10(); } else{ downlink_shift_reg = (0x4444); } break; case 5://Rectified Voltage= 12 Volts if(reset_best_cap == 1){ downlink_shift_reg = (0x555F); toggle_gpio_10(); } else{ downlink_shift_reg = (0x5555); } break; case 6://Rectified Voltage= 13 Volts if(reset_best_cap == 1){ downlink_shift_reg = (0x666F); toggle_gpio_10(); } else{ downlink_shift_reg = (0x6666); } break; } } if (silence == 0){ clock_mask = 0;//Restart Listening only if the buffer is not=0xFFF0 which the message from the receiver that it is the turn for the transimitter to senda downlink message } tc_stop(TC0,2);//Stop the Data recovery clock. It will start again very soon once there isa transition in the encoded signal. break; }

169 }

//______//data_recovery.h //______//This code is the header file for the data_recovery.c

#include

#ifndefDATA_RECOVERY_H_ #defineDATA_RECOVERY_H_ void recovered_clock_02_init(uint32_t); void read_signal(void); void check_communication(void); void check_bit(void); void data_recovery_setup(void); void pin_edge_handler(const uint32_t, const uint32_t); void check_shift_reg_receive(void); void reset_communication(void); void check_data_synched(void); uint32_t get_batt_v_received(void); uint32_t get_batt_i_received(void); uint32_t get_rect_v_received(void); void check_re_sync(void); uint32_t clock_recovered; uint32_t rx_clk; uint32_t reading; uint32_t old_reading; uint32_t readings_register; volatile uint32_t sync_count; uint32_t clock_synced; uint32_t data_synced; volatile uint32_t state; uint32_t rx_clk_recovered; uint32_t new_bit; uint32_t next_bit; uint32_t recovered_clk_quarter; uint32_t correct; uint32_t shift_reg_receive; uint32_t shift_reg_receive_size; uint32_t shift_reg_receive_count; uint32_t bit_test;

170 uint32_t communication; uint32_t batt_v_recieved; uint32_t batt_i_recieved; uint32_t rect_v_recieved; uint32_t batt_v_recieved_old; uint32_t batt_i_recieved_old; uint32_t rect_v_recieved_old; uint32_t bad_reading; uint32_t clock_mask; uint32_t parity_count; Bool communication_synced; uint32_t new_current_measurement; uint32_t rectified_voltage_state; uint32_t rectified_voltage_state_count; int last_chirp; int last_chirp_copy; int restart_control; uint32_t skip_reading;

#endif/*DATA_RECOVERY_H_*/

//______//down_link_utils.c //______//This code is responsible for creating the amplitude modulated signal for the downlink communication.

#include"down_link_utils.h" #include"data_recovery.h" #include"down_link_utils.h" #include"dacc_utils.h"

//Setup the clock for the down link Communication void down_link_clock_10_init(uint32_t frequ) { uint32_t ra, rc; pmc_enable_periph_clk(ID_TC3);//Enable the Periphial Clock for the Timer. Note Timer3= Timer Modual 1, Timer Source 0.(There are Timers 0,1,2,3,4,5)

// InitTC to waveform mode. tc_init(TC1, 0, (0 x1u << 0)// Waveform Clock Selection | (0x1u << 15)// Waveform mode is enabled,0 for capture mode | (0x1u << 16)//RA Compare Effect onTIOA: set

171 | (0x2u << 18)//RC Compare Effect onTIOA: clear | (0x2u << 13)// Counter only countsUP with reset onRC Compare ); rc = 120000000/(8*(frequ));//Clock divisor tc_write_rc(TC1, 0, rc);//Setting upa counter compare based on the divisor and frequency requested ra = (50 * rc) / 100; tc_write_ra(TC1, 0, ra); tc_enable_interrupt(TC1,0,TC_IER_CPCS);// Enable interrupt onRC compare // ConfigureTC interrupts NVIC_DisableIRQ(TC3_IRQn); NVIC_ClearPendingIRQ(TC3_IRQn); NVIC_SetPriority(TC3_IRQn,0); NVIC_EnableIRQ(TC3_IRQn); //tc_start(TC1, 0); }

//Variables for the communication. They could be added to the header file witha init function. uint32_t cnt = 0;//This variable keeps track of the open loop communication rate. uint32_t additional_power = 0;//This variable is the modulated amount of power for the amplitude modulation. uint32_t downlink_clk = 0;//This variable stores the value of the downlink communication clock. Either High (1) or Low (0) uint16_t downlink_shift_reg_count = 0;//This buffer counter is for keeping track of how many of the downlink bits have been sent.

//Down Link Communication Timer that runs at2kHz. Every timer overflow is eithera rising edge or falling edge. void TC3_Handler(void){ uint32_t status2 = tc_get_status(TC1,0); cnt += 1;//Increase the counter every 500us (2kHz). //PIOB ->PIO_SODR |= PIO_PB3;//Debug: Start with downlink Communication if (cnt >= 34){//Stop the downlink communication amp_mod = 0;//Turn off the amplitude modulation cnt = 0;//reset the downlink communication counter //PIOB ->PIO_CODR |= PIO_PB3;//Debug: lower the Downlink Communication flag with downlink Comm additional_power = 0;//Make sure the amplitude modulation is removed from the signal //PIOA ->PIO_CODR |= PIO_PA10;//Debug: Amplitude Modulation downlink_shift_reg = 0;//Reset the Downlink Communication shift register downlink_shift_reg_count = 0;//Reset the downlink communication shift register counter //GPIO_5_OFF;//Debug: Low Amplitude Modulation tc_stop(TC1,0);//Finish the Down link Communication and stop the clock clock_mask = 0;//Start Listening for an interrupt on the Input Signal Pin

172 restarting_communication_voltage = 1;//These variables flag the recovery code to ignore the first battery voltage and battery current reading because it is likely to be corrupted restarting_communication_current = 1; //GPIO_6_OFF;//Debug: Turn off the debug pin of ignoring the input signal } //Data Encoding if (downlink_clk == 0){//If the clock is low, raise the clock //GPIO_4_ON;//Debug: Rising Edge of Clock if (additional_power == 1) {//Toggle Pin additional_power = -1; //GPIO_5_OFF;//Debug: Low Amplitude Modulation } else{ additional_power = 1; //GPIO_5_ON;//Debug: High Amplitude Modulation } downlink_clk = 1;//prepare for falling edge } else{ downlink_clk = 0;//If the clock is High, Lower the clock //GPIO_4_OFF;//Debug: Falling Edge of Clock if(downlink_shift_reg & (1<<15)){//if the Data bit to be sent isa1 then toggle the output if (additional_power == 1){//If the output was high additional_power = -1;//Then make it low //GPIO_5_OFF;//Debug: Low Amplitude Modulation } else{ additional_power = 1;//Otherwise if the output was low then make it hight //GPIO_5_ON;//Debug: High Amplitude Modulation } } downlink_shift_reg = (downlink_shift_reg << 1);//shift the shift register one bit to the left downlink_shift_reg_count += 1;//increment the data sent counter if(downlink_shift_reg_count >= 16){//if the number of bits that have been sent has reached 16 downlink_shift_reg_count = 0;//reset the shift register counter amp_mod = 0;//turn off the amplitude modulation(*Note these are redundant with the condition above of cnt> 34) cnt = 0;//reset the timing counter(*The condition above an probably be removed) additional_power = 0;//Make sure the amplitude modulation is removed from the signal downlink_shift_reg = 0;//Reset the shift register value tc_stop(TC1,0);//Finish the Down link Communication and stop the clock

173 clock_mask = 0;//Start Listening for an interrupt on the Input Signal Pin restarting_communication_voltage = 1;//These variables flag the recovery code to ignore the first battery voltage and battery current restarting_communication_current = 1;//reading because it is likely to be corrupted } } } uint32_t get_additional_power(void){//This function is called by theDAC and returns eithera 1,0 or -1 depending on if theDAC should return additional_power;//add or subtract from the originally calculated output signal in the control code.(If it should add amplitude modulation) }

//______//down_link_utils.h //______//This code is the header file for the down_link_utils.c

#include

#ifndefDOWN_LINK_UTILS_H_ #defineDOWN_LINK_UTILS_H_ void down_link_clock_10_init(uint32_t); uint32_t get_additional_power(void); uint16_t downlink_shift_reg; uint32_t restarting_communication_voltage; uint32_t restarting_communication_current;

#endif/*DOWN_LINK_UTILS_H_*/

//______//efficiency_finder_utils.c //______//This code is responsible for calculating the efficiency of the system.

#include"efficiency_finder_utils.h" #include"data_recovery.h" #include"adc_utils.h" #include"led_utils.h"

void eff_calculations_setup(void){ battery_current_float = 0;

174 battery_voltage_float = 0; battery_power_float = 0; input_current_float = 0; input_power_float = 0; efficiency_float = 0; rectified_voltage_float = 0;

rectified_voltage = 0; previous_rectified_voltage = 0; }

//______Functions to Calculate Values, called from the control function______

//= (1/VMOM Gain)*(ADC reference)*5(input voltage) void calculate_float_input_power(void){ input_power_float = ((get_input_i())*(5.376)*(1.992/4096)); }

//Actual battery Current=(received value- 494)*(1/2.717)*(1.985/4096) //float=(recieved int- 494)*(1/Currense Sense Amplifier Gain)*(1/ReceiverADC Gain) //*The 494 subtraction is due to an offset in the resistors of the current sense differential amplifier void calculate_float_battery_current(void){ battery_current_float = ((get_batt_i_received() - 494)*0.368)*(1.985/4096); } //= Received Bits*(2.915)*(1.985/4096) //=(Received Bits* (~3x scaling to undo on board voltage division)*(RxADC Reference scaling) void calculate_float_battery_voltage(void){ battery_voltage_float = ((get_batt_v_received()*2.915)*(1.985/4096)); } void calculate_float_battery_power(void){ battery_power_float = battery_current_float*battery_voltage_float; } void calculate_float_efficiency(void){ previous_efficiency_float = efficiency_float; efficiency_float = battery_power_float/input_power_float; } //Undo the voltage divider andADC gain of the receiver void calculate_float_rectified_voltage(void){ rectified_voltage_float = get_rect_v_received()*(9.737)*(1.985/4096); } //= (1/VMOM Gain)*(PowerTXADC reference) void calculate_float_input_current(void){ input_current_float = ((get_input_i())*(1.075)*(1.992/4096) ) ; }

175 //______Functions to Return Values______float get_float_input_power(void){ return input_power_float; } float get_float_input_current(void){ return input_current_float; } float get_float_efficiency(void){ return efficiency_float; } float get_output_power(void){ return battery_power_float; }

//______//efficiency_finder_utils.h //______//This code is the header file for the efficiency_finder_utils.c

#include

#ifndefEFFICIENCY_FINDER_UTILS_H_ #defineEFFICIENCY_FINDER_UTILS_H_ float get_output_power(void); float calculate_efficiency(void); uint32_t get_efficiency(void); float get_float_efficiency(void); float get_float_input_power(void); float get_float_input_current(void); void eff_calculations_setup(void); void calculate_float_input_current(void); void calculate_float_input_power(void); void calculate_float_battery_current(void); void calculate_float_battery_voltage(void); void calculate_float_battery_power(void); void calculate_float_efficiency(void); void calculate_float_rectified_voltage(void); float battery_current_float; float battery_voltage_float; float battery_power_float;

176 float input_current_float; float input_power_float; float efficiency_float; float previous_efficiency_float; float rectified_voltage_float; uint32_t rectified_voltage; uint32_t previous_rectified_voltage;

#endif/*EFFICIENCY_FINDER_UTILS_H_*/

//______//gpio_utils.c //______//This code is responsible for defining the functions to turn on and off theGPIO pins

#include"gpio_utils.h" void toggle_gpio_1(void){ if(gpio_1_state){ gpio_1_state = 0; GPIO_1_OFF; } else{ gpio_1_state = 1; GPIO_1_ON ; } } void toggle_gpio_2(void){ if(gpio_2_state){ gpio_2_state = 0; GPIO_2_OFF; } else{ gpio_2_state = 1; GPIO_2_ON ; } } void toggle_gpio_3(void){ if(gpio_3_state){ gpio_3_state = 0; GPIO_3_OFF; } else{ gpio_3_state = 1;

177 GPIO_3_ON ; } } void toggle_gpio_4(void){ if(gpio_4_state){ gpio_4_state = 0; GPIO_4_OFF; } else{ gpio_4_state = 1; GPIO_4_ON ; } } void toggle_gpio_5(void){ if(gpio_5_state){ gpio_5_state = 0; GPIO_5_OFF; } else{ gpio_5_state = 1; GPIO_5_ON ; } } void toggle_gpio_6(void){ if(gpio_6_state){ gpio_6_state = 0; GPIO_6_OFF; } else{ gpio_6_state = 1; GPIO_6_ON ; } } void toggle_gpio_7(void){ if(gpio_7_state){ gpio_7_state = 0; GPIO_7_OFF; } else{ gpio_7_state = 1; GPIO_7_ON ; } } void toggle_gpio_8(void){ if(gpio_8_state){

178 gpio_8_state = 0; GPIO_8_OFF; } else{ gpio_8_state = 1; GPIO_8_ON ; } } void toggle_gpio_9(void){ if(gpio_9_state){ gpio_9_state = 0; GPIO_9_OFF; } else{ gpio_9_state = 1; GPIO_9_ON ; } } void toggle_gpio_10(void){ if(gpio_10_state){ gpio_10_state = 0; GPIO_10_OFF; } else{ gpio_10_state = 1; GPIO_10_ON; } } void toggle_gpio_11(void){ if(gpio_11_state){ gpio_11_state = 0; GPIO_11_OFF; } else{ gpio_11_state = 1; GPIO_11_ON; } }

//______//gpio_utils.h //______//This code is the header file for the gpio_utils.c

#include

179 #ifndefGPIO_UTILS_H_ #defineGPIO_UTILS_H_

#define GPIO_1_ON(PIOC ->PIO_SODR |= PIO_PC0) #define GPIO_1_OFF(PIOC ->PIO_CODR |= PIO_PC0)

#define GPIO_2_ON(PIOA ->PIO_SODR |= PIO_PA20) #define GPIO_2_OFF(PIOA ->PIO_CODR |= PIO_PA20)

#define GPIO_3_ON(PIOC ->PIO_SODR |= PIO_PC12) #define GPIO_3_OFF(PIOC ->PIO_CODR |= PIO_PC12)

#define GPIO_4_ON(PIOA ->PIO_SODR |= PIO_PA23) #define GPIO_4_OFF(PIOA ->PIO_CODR |= PIO_PA23)

#define GPIO_5_ON(PIOC ->PIO_SODR |= PIO_PC13) #define GPIO_5_OFF(PIOC ->PIO_CODR |= PIO_PC13)

#define GPIO_6_ON(PIOA ->PIO_SODR |= PIO_PA22) #define GPIO_6_OFF(PIOA ->PIO_CODR |= PIO_PA22)

#define GPIO_7_ON(PIOC ->PIO_SODR |= PIO_PC15) #define GPIO_7_OFF(PIOC ->PIO_CODR |= PIO_PC15)

#define GPIO_8_ON(PIOA ->PIO_SODR |= PIO_PA19) #define GPIO_8_OFF(PIOA ->PIO_CODR |= PIO_PA19)

#define GPIO_9_ON(PIOC ->PIO_SODR |= PIO_PC27) #define GPIO_9_OFF(PIOC ->PIO_CODR |= PIO_PC27)

#define GPIO_10_ON(PIOA ->PIO_SODR |= PIO_PA21) #define GPIO_10_OFF(PIOA ->PIO_CODR |= PIO_PA21)

#define GPIO_11_ON(PIOA ->PIO_SODR |= PIO_PA18) #define GPIO_11_OFF(PIOA ->PIO_CODR |= PIO_PA18)

#define GPIO_12_ON(PIOC ->PIO_SODR |= PIO_PC26) #define GPIO_12_OFF(PIOC ->PIO_CODR |= PIO_PC26)

#define GPIO_13_ON(PIOA ->PIO_SODR |= PIO_PA17) #define GPIO_13_OFF(PIOA ->PIO_CODR |= PIO_PA17) void toggle_gpio_1(void);

180 void toggle_gpio_2(void); void toggle_gpio_3(void); void toggle_gpio_4(void); void toggle_gpio_5(void); void toggle_gpio_6(void); void toggle_gpio_7(void); void toggle_gpio_8(void); void toggle_gpio_9(void); void toggle_gpio_10(void); void toggle_gpio_11(void); void toggle_gpio_12(void); void toggle_gpio_13(void); uint32_t gpio_1_state; uint32_t gpio_2_state; uint32_t gpio_3_state; uint32_t gpio_4_state; uint32_t gpio_5_state; uint32_t gpio_6_state; uint32_t gpio_7_state; uint32_t gpio_8_state; uint32_t gpio_9_state; uint32_t gpio_10_state; uint32_t gpio_11_state; uint32_t gpio_12_state; uint32_t gpio_13_state;

#endif/*GPIO_UTILS_H_*/

//______//lcd_utils.c //______//This code is responsible for writing values to theLCD

#include"lcd_utils.h" #include"adc_utils.h" #include"data_recovery.h" void lcd_pin_setup(void){

lcd_adc_state = 0; lcd_counter = 0; new_lcd_state = 0;

181 /* Configure Output Pins forLCD Header Pin3= PA16=RS= Regester Select Pin4= PC7=R/W= Read/Write Pin5= PA15= Enable Pin6= PA14= D0 Pin7= PC6= D1 Pin8= PA13= D2 Pin9= PA24= D3 Pin10= PC5= D4 Pin11= PC4= D5 Pin12= PA25= D6 Pin15= PA26= D7 */

///* //Pin3= PA16=RS= Regester Select PIOA -> PIO_IDR |= PIO_PA16; PIOA -> PIO_PUER |= PIO_PA16; PIOA -> PIO_MDDR |= PIO_PA16; PIOA -> PIO_CODR |= PIO_PA16; PIOA -> PIO_PER |= PIO_PA16; PIOA -> PIO_OER |= PIO_PA16;

//Pin4= PC7=R/W= Read/Write PIOC -> PIO_IDR |= PIO_PC7; PIOC -> PIO_PUER |= PIO_PC7; PIOC -> PIO_MDDR |= PIO_PC7; PIOC -> PIO_CODR |= PIO_PC7; PIOC -> PIO_PER |= PIO_PC7; PIOC -> PIO_OER |= PIO_PC7;

//Pin5= PA15= Enable PIOA -> PIO_IDR |= PIO_PA15; PIOA -> PIO_PUER |= PIO_PA15; PIOA -> PIO_MDDR |= PIO_PA15; PIOA -> PIO_CODR |= PIO_PA15; PIOA -> PIO_PER |= PIO_PA15; PIOA -> PIO_OER |= PIO_PA15;

//Pin6= PA14= D0 PIOA -> PIO_IDR |= PIO_PA14; PIOA -> PIO_PUER |= PIO_PA14; PIOA -> PIO_MDDR |= PIO_PA14; PIOA -> PIO_CODR |= PIO_PA14; PIOA -> PIO_PER |= PIO_PA14;

182 PIOA -> PIO_OER |= PIO_PA14;

//Pin7= PC6= D1 PIOC -> PIO_IDR |= PIO_PC6; PIOC -> PIO_PUER |= PIO_PC6; PIOC -> PIO_MDDR |= PIO_PC6; PIOC -> PIO_CODR |= PIO_PC6; PIOC -> PIO_PER |= PIO_PC6; PIOC -> PIO_OER |= PIO_PC6;

//Pin8= PA13= D2 PIOA -> PIO_IDR |= PIO_PA13; PIOA -> PIO_PUER |= PIO_PA13; PIOA -> PIO_MDDR |= PIO_PA13; PIOA -> PIO_CODR |= PIO_PA13; PIOA -> PIO_PER |= PIO_PA13; PIOA -> PIO_OER |= PIO_PA13;

//Pin9= PA24= D3 PIOA -> PIO_IDR |= PIO_PA24; PIOA -> PIO_PUER |= PIO_PA24; PIOA -> PIO_MDDR |= PIO_PA24; PIOA -> PIO_CODR |= PIO_PA24; PIOA -> PIO_PER |= PIO_PA24; PIOA -> PIO_OER |= PIO_PA24;

//Pin10= PC5= D4 PIOC -> PIO_IDR |= PIO_PC5; PIOC -> PIO_PUER |= PIO_PC5; PIOC -> PIO_MDDR |= PIO_PC5; PIOC -> PIO_CODR |= PIO_PC5; PIOC -> PIO_PER |= PIO_PC5; PIOC -> PIO_OER |= PIO_PC5;

//Pin11= PC4= D5 PIOC -> PIO_IDR |= PIO_PC4; PIOC -> PIO_PUER |= PIO_PC4; PIOC -> PIO_MDDR |= PIO_PC4; PIOC -> PIO_CODR |= PIO_PC4; PIOC -> PIO_PER |= PIO_PC4; PIOC -> PIO_OER |= PIO_PC4;

//Pin12= PA25= D6 PIOA -> PIO_IDR |= PIO_PA25; PIOA -> PIO_PUER |= PIO_PA25;

183 PIOA -> PIO_MDDR |= PIO_PA25; PIOA -> PIO_CODR |= PIO_PA25; PIOA -> PIO_PER |= PIO_PA25; PIOA -> PIO_OER |= PIO_PA25;

//Pin15= PA26= D7 PIOA -> PIO_IDR |= PIO_PA26; PIOA -> PIO_PUER |= PIO_PA26; PIOA -> PIO_MDDR |= PIO_PA26; PIOA -> PIO_CODR |= PIO_PA26; PIOA -> PIO_PER |= PIO_PA26; PIOA -> PIO_OER |= PIO_PA26; }

//change the value in theDDRAM which is for the cursor position void lcd_move_cursur(char line, char position){ if (line == 1){ lcd_cmd_write(position,1); } else if (line == 2){ char cmd = (0xC0 + position); lcd_cmd_write(cmd,1); } } void clear_data(void){ clear_D0 ; clear_D1 ; clear_D2 ; clear_D3 ; clear_D4 ; clear_D5 ; clear_D6 ; clear_D7 ; }

//Axillary function used by the write functions void set_data(char cmd){ if ((cmd & 0x01) == 1) set_D0; if ((cmd & 0x02) == 0x02) set_D1; if ((cmd & 0x04) == 0x04) set_D2; if ((cmd & 0x08) == 0x08) set_D3; if ((cmd & 0x10) == 0x10) set_D4; if ((cmd & 0x20) == 0x20) set_D5; if ((cmd & 0x40) == 0x40) set_D6;

184 if ((cmd & 0x80) == 0x80) set_D7; }

//Wirte commands to theLCD void lcd_cmd_write (char cmd, uint32_t delay_time){ clear_RS ;//Write to Instruction Register clear_RW ;//Write set_data(cmd); set_EN ; delay_us(1);//Flash the Enable Flag clear_EN ; delay_ms(delay_time); clear_data(); };

//Write characters to theLCD void lcd_char_write(char cmd){ set_RS ;//Write to Data Register clear_RW ;//Write set_data(cmd); set_EN ; delay_us(1);//Flash the Enable flag clear_EN ; delay_us(30);//Wait for data to be written clear_data(); }

//The initialization routine to start up theLCD along with writing input power, output power and efficiency void lcd_init(void){ delay_ms(200);//Waita little after reset lcd_cmd_write(0x30,10);//Function set:1 the lower4 bits are irrelevant lcd_cmd_write(0x30,1);//Function set:2 the lower4 bits are irrelevant lcd_cmd_write(0x30,1);//Function set:3 the lower4 bits are irrelevant lcd_cmd_write(0x38,1);//Function set:4 Line, 8-bit,5x7 dots lcd_cmd_write(0x08,1);//Display off, Cursor off, blinking off, lcd_cmd_write(0x01,10);//Display Clear lcd_cmd_write(0x06,10);//Entry mode, auto increment with no shift lcd_cmd_write(0x0C,1);//Display on lcd_write_input_power(); lcd_write_output_power(); lcd_write_efficiency(); }

//Write"ADC_Readings" on line1 void lcd_adc_readings(void){

185 lcd_cmd_write(0x01,10);//Display Clear lcd_move_cursur(1,2); lcd_char_write(0x41);//A lcd_char_write(0x44);//D lcd_char_write(0x43);//C lcd_char_write(0x20);//_ lcd_char_write(0x52);//R lcd_char_write(0x65);//e lcd_char_write(0x61);//a lcd_char_write(0x64);//d lcd_char_write(0x69);//i lcd_char_write(0x6E);//n lcd_char_write(0x67);//g lcd_char_write(0x73);//s };

//Write"No Communication" on line1 void lcd_write_no_comm(void){ lcd_cmd_write(0x01,10);//Display Clear lcd_move_cursur(1,2); lcd_char_write(0x4E);//N lcd_char_write(0x6F);//o lcd_char_write(0x20);// lcd_char_write(0x43);//C lcd_char_write(0x6F);//o lcd_char_write(0x6D);//m lcd_char_write(0x6D);//m lcd_char_write(0x75);//u lcd_char_write(0x6E);//n lcd_char_write(0x69);//i lcd_char_write(0x63);//c lcd_char_write(0x61);//a lcd_char_write(0x74);//t lcd_char_write(0x69);//i lcd_char_write(0x6F);//o lcd_char_write(0x6E);//n };

//Write"Communication" on line1 void lcd_write_comm(void){ lcd_cmd_write(0x01,10);//Display Clear lcd_move_cursur(1,2); lcd_char_write(0x43);//C lcd_char_write(0x6F);//o lcd_char_write(0x6D);//m

186 lcd_char_write(0x6D);//m lcd_char_write(0x75);//u lcd_char_write(0x6E);//n lcd_char_write(0x69);//i lcd_char_write(0x63);//c lcd_char_write(0x61);//a lcd_char_write(0x74);//t lcd_char_write(0x69);//i lcd_char_write(0x6F);//o lcd_char_write(0x6E);//n };

//Write"Batt_V=" on line2 void lcd_write_batt_v_name(void){ lcd_move_cursur(2,0); lcd_char_write(0x42);//B lcd_char_write(0x61);//a lcd_char_write(0x74);//t lcd_char_write(0x74);//t lcd_char_write(0x20);//_ lcd_char_write(0x56);//V lcd_char_write(0x3D);//= }

//Debug function for writinga primitive value void lcd_write_batt_v_value(char adc_value){ lcd_char_write(adc_value); }

//Write"Batt_I=" on line2 void lcd_write_batt_i_name(void){ lcd_move_cursur(2,0); lcd_char_write(0x42);//B lcd_char_write(0x61);//a lcd_char_write(0x74);//t lcd_char_write(0x74);//t lcd_char_write(0x20);//_ lcd_char_write(0x49);//I lcd_char_write(0x3D);//= }

//Debug function for writinga primitive value void lcd_write_batt_i_value(char adc_value){ lcd_char_write(adc_value); }

187 ////Write"Rect_V=" on line2 void lcd_write_rect_v_name(void){ lcd_move_cursur(2,0); lcd_char_write(0x52);//R lcd_char_write(0x65);//e lcd_char_write(0x63);//c lcd_char_write(0x74);//t lcd_char_write(0x20);//_ lcd_char_write(0x56);//V lcd_char_write(0x3D);//= }

//Write"Input_P=" on Line1 void lcd_write_input_power(void){ lcd_move_cursur(1,2); lcd_char_write(0x49);//I lcd_char_write(0x6E);//n lcd_char_write(0x70);//p lcd_char_write(0x20);//_ lcd_char_write(0x50);//P lcd_char_write(0x3D);//= delay_ms(50); } void lcd_write_output_power(void){ lcd_move_cursur(2,0); lcd_char_write(0x42);//B lcd_char_write(0x61);//a lcd_char_write(0x74);//t lcd_char_write(0x20);//_ lcd_char_write(0x50);//P lcd_char_write(0x3D);//= delay_ms(50); } void lcd_write_efficiency(void){ lcd_move_cursur(2,11); lcd_char_write(0x45);//E lcd_char_write(0x3D);//= delay_ms(50); } void lcd_write_rect_v_value(char adc_value){ lcd_char_write(adc_value); }

188 void adc_buffer_to_lcd_batt_v(uint32_t batt_v){ volatile uint32_t ones = batt_v*5/4096; volatile float temp = (batt_v*5.0/4096)-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; lcd_move_cursur(2,8);//Move the cursor to the8th index of the line lcd_char_write(ones + 0x30);//Ones Place lcd_char_write(0x2E);//Decimal place lcd_char_write(tenth + 0x30);//Tenth Place lcd_char_write(hundreth + 0x30);//Hundredths Place delay_ms(20); } void adc_buffer_to_lcd_batt_i(uint32_t batt_i){ volatile uint32_t ones = batt_i*3.3/4096; volatile float temp = (batt_i*3.3/4096)-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; temp = (10*temp- hundreth); volatile uint32_t thousandth = 10*temp; lcd_move_cursur(2,8); lcd_char_write(ones + 0x30); lcd_char_write(0x2E); lcd_char_write(tenth + 0x30); lcd_char_write(hundreth + 0x30); lcd_char_write(thousandth + 0x30); delay_ms(20); } void input_current_to_lcd(uint32_t current){ volatile uint32_t ones = current*(1.2)/4096; volatile float temp = (current*1.2/4096)-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; lcd_write_input_power(); lcd_char_write(ones + 0x30); lcd_char_write(0x2E); lcd_char_write(tenth + 0x30); lcd_char_write(hundreth + 0x30); delay_ms(20); }

189 void battery_float_voltage_to_lcd(float float_battery_voltage){ volatile uint32_t ones = float_battery_voltage*1; volatile float temp = float_battery_voltage-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; temp = (10*temp - hundreth); volatile uint32_t thousandth = 10*temp; lcd_write_batt_v_name(); lcd_char_write(ones + 0x30); lcd_char_write(0x2E); lcd_char_write(tenth + 0x30); lcd_char_write(hundreth + 0x30); lcd_char_write(thousandth + 0x30); delay_ms(20); } void battery_float_current_to_lcd(float float_battery_current){ volatile uint32_t ones = float_battery_current*1; volatile float temp = float_battery_current-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; temp = (10*temp - hundreth); volatile uint32_t thousandth = 10*temp; lcd_write_batt_i_name(); //lcd_char_write(ones+0x30);//Ones Place is always 0... lcd_char_write(0x2E); lcd_char_write(tenth + 0x30); lcd_char_write(hundreth + 0x30); lcd_char_write(thousandth + 0x30); delay_ms(20); } void battery_float_power_to_lcd(float power){ volatile uint32_t ones = power*1; volatile float temp = power-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; lcd_move_cursur(2,6); lcd_char_write(ones + 0x30); lcd_char_write(0x2E); lcd_char_write(tenth + 0x30);

190 lcd_char_write(hundreth + 0x30); delay_ms(20); } void input_float_current_to_lcd(float float_input_current){ volatile uint32_t ones = float_input_current*1; volatile float temp = float_input_current-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; temp = (10*temp - hundreth); volatile uint32_t thousandth = 10*temp; //lcd_move_cursur(1,4);//Move the cursur to the8th index of the line lcd_write_input_power(); lcd_char_write(ones + 0x30); lcd_char_write(0x2E); lcd_char_write(tenth + 0x30); lcd_char_write(hundreth + 0x30); lcd_char_write(thousandth + 0x30); delay_ms(20); }

//This function writes the input power to theLCD void input_float_power_to_lcd(float input_power){ volatile uint32_t ones = input_power*1; volatile float temp = input_power-ones; volatile uint32_t tenth = 10*temp; temp = (10*temp - tenth); volatile uint32_t hundreth = 10*temp; //lcd_move_cursur(1,4);//Move the cursur to the8th index of the line lcd_write_input_power(); lcd_char_write(ones + 0x30); lcd_char_write(0x2E); lcd_char_write(tenth + 0x30); lcd_char_write(hundreth + 0x30); delay_ms(20); }

//This one is used to write the float value of efficiencyy. void eff_to_lcd(float eff){ volatile uint32_t ones = (eff*40960)/4096; volatile float temp = (eff*10.0)-ones; volatile uint32_t tenth = (temp*40960)/4096; //lcd_move_cursur(1,4);//Move the cursur to the8th index of the line

191 lcd_write_efficiency(); lcd_char_write(0x2E); lcd_char_write(ones + 0x30); lcd_char_write(tenth + 0x30); delay_ms(20); }

//This one is used to just send the integer value of the rectified voltage void rect_v_approx_to_lcd(uint32_t rect_v_approx){ volatile uint32_t tens = rect_v_approx/10; volatile uint32_t ones = rect_v_approx - (10*tens); //lcd_move_cursur(2,11);//Move the cursur to the8th index of the line lcd_char_write(0x20);// space lcd_char_write(tens + 0x30); lcd_char_write(ones + 0x30); delay_ms(20); }

//Not used void adc_buffer_to_lcd_rect_v(uint32_t adc_reading){//The board hasa 3.3/40 resistor division and the reference is 3.3V so need to rescale by 40 volatile uint32_t tens = adc_reading*4/4096; volatile uint32_t ones = (adc_reading*40.0/4096)-(tens*10); volatile float temp = (adc_reading*40.0/4096) - (tens*10 + ones); volatile uint32_t tenth = 10*temp; lcd_move_cursur(2,8); lcd_char_write(tens + 0x30); lcd_char_write(ones + 0x30); lcd_char_write(0x2E); lcd_char_write(tenth + 0x30); delay_ms(20); }

//This function was eventually not used. It was originally for cycling through displaying different values.I ended up just manually sending commands to printa value. void lcd_run(uint32_t lcd_state){ switch(lcd_state){ case no_comm: lcd_write_no_comm(); tc_stop(TC0,1); //delay_ms(1000); break; case comm:

192 lcd_write_comm(); tc_start(TC0,1); //delay_ms(1000); break; case adc_readings_setup: lcd_adc_readings(); new_lcd_state = 1; break; case adc_readings://inside theADC state, cycle between the values switch(lcd_adc_state){ case lcd_batt_v: if (new_lcd_state){ lcd_write_batt_v_name(); new_lcd_state = 0; } adc_buffer_to_lcd_batt_v(get_batt_v_received()); lcd_counter += 1; if (lcd_counter > 300){ lcd_adc_state = lcd_batt_i; lcd_counter = 0; new_lcd_state = 1; } break; case lcd_batt_i: if (new_lcd_state){ lcd_write_batt_i_name(); new_lcd_state = 0; } adc_buffer_to_lcd_batt_i(get_batt_i_received()); lcd_counter += 1; if (lcd_counter > 300){ lcd_adc_state = lcd_rect_v; lcd_counter = 0; new_lcd_state = 1; } break; case lcd_rect_v: if (new_lcd_state){ lcd_write_rect_v_name(); new_lcd_state = 0; } adc_buffer_to_lcd_rect_v(get_rect_v_received()); lcd_counter += 1; //if(lcd_next_state){

193 if (lcd_counter > 300){ lcd_adc_state = lcd_batt_v; lcd_counter = 0; new_lcd_state = 1; } break; }

}

}

//______//lcd_utils.h //______//This code is the header file for the lcd_utils.c

#include

#ifndefLCD_UTILS_H_ #defineLCD_UTILS_H_

//______LCD Function Declarations and Define_____ void lcd_cmd_write (char, uint32_t); void clear_data(void); void set_data(char); void lcd_move_cursur(char, char); void lcd_pin_setup(void); void lcd_char_write(char); void lcd_init(void); void lcd_hello_world(void); void lcd_write_batt_v_name(void); void lcd_write_batt_v_value(char); void lcd_write_batt_i_name(void); void lcd_write_batt_i_value(char); void lcd_write_rect_v_name(void); void lcd_write_rect_v_value(char); void adc_buffer_to_lcd_batt_v(uint32_t); void adc_buffer_to_lcd_batt_i(uint32_t); void adc_buffer_to_lcd_rect_v(uint32_t); void battery_float_power_to_lcd(float); void lcd_write_input_power(void); void lcd_write_output_power(void); void lcd_write_efficiency(void); void input_current_to_lcd(uint32_t);

194 void input_float_power_to_lcd(float); void eff_to_lcd(float); void input_float_current_to_lcd(float); void battery_float_current_to_lcd(float); void battery_float_voltage_to_lcd(float); void rect_v_approx_to_lcd(uint32_t); void lcd_write_no_comm(void); void lcd_write_comm(void); void lcd_adc_readings(void); void lcd_run(uint32_t); void lcd_timer_02_init(void);

#define set_RSPIOA->PIO_SODR |= PIO_PA16; #define set_RWPIOC->PIO_SODR |= PIO_PC7; #define set_ENPIOA->PIO_SODR |= PIO_PA15; #define set_D0PIOA->PIO_SODR |= PIO_PA14; #define set_D1PIOC->PIO_SODR |= PIO_PC6; #define set_D2PIOA->PIO_SODR |= PIO_PA13; #define set_D3PIOA->PIO_SODR |= PIO_PA24; #define set_D4PIOC->PIO_SODR |= PIO_PC5; #define set_D5PIOC->PIO_SODR |= PIO_PC4; #define set_D6PIOA->PIO_SODR |= PIO_PA25; #define set_D7PIOA->PIO_SODR |= PIO_PA26;

#define clear_RSPIOA->PIO_CODR |= PIO_PA16; #define clear_RWPIOC->PIO_CODR |= PIO_PC7; #define clear_ENPIOA->PIO_CODR |= PIO_PA15; #define clear_D0PIOA->PIO_CODR |= PIO_PA14; #define clear_D1PIOC->PIO_CODR |= PIO_PC6; #define clear_D2PIOA->PIO_CODR |= PIO_PA13; #define clear_D3PIOA->PIO_CODR |= PIO_PA24; #define clear_D4PIOC->PIO_CODR |= PIO_PC5; #define clear_D5PIOC->PIO_CODR |= PIO_PC4; #define clear_D6PIOA->PIO_CODR |= PIO_PA25; #define clear_D7PIOA->PIO_CODR |= PIO_PA26;

#define no_comm0 #define comm1 #define adc_readings_setup2 #define adc_readings3

#define lcd_batt_v0 #define lcd_batt_i1 #define lcd_rect_v2

195 uint32_t lcd_adc_state; volatile uint32_t lcd_counter; volatile uint32_t new_lcd_state;

#endif/*LCD_UTILS_H_*/

//______//rectified_voltage_utils.c //______//This code is responsible for comparing the efficiency measurements at different rectified voltages

#include"rectified_voltage_utils.h" #include"control.h" #include"adc_utils.h" #include"data_recovery.h" #include"led_utils.h" #include"efficiency_finder_utils.h" #include"gpio_utils.h" #include"lcd_utils.h"

//This Function changes the command for the rectified voltage based on the current rectified voltage and the efficiency measurements. void change_rectified_voltage(void){ switch (rectified_voltage){ case 8: reset_best_cap = 0; eff_8 = efficiency_float_avg; if(eff_8 < eff_9){//If the efficiency at8 Volts is less than at 9 Volts then go to8 Volts rectified_voltage_state = 2;//Go to9V } else if(eff_9 < 0.1){//If the efficiency measurement of9 Volts has not been done then go and try it. reset_best_cap = 1;//tell theRX to reset the best cap for the rectified voltages because it is ata new power level. rectified_voltage_state = 2;//Explore9V } else{ rectified_voltage_state = 1;//Stay at8 Volts because it is the most efficient point and if not done yet, calculate theSS input power asa benchmark. if(input_power_region_set == 0){//If the input power benchmark has not been calculated then calculate it. This would because it isa new power region.

196 input_power_float_region = input_power_float; input_power_region_set = 1; toggle_gpio_9();//Debug GPIO_8_ON ;//Debug } //If the input power has changed by 0.1 Watts from the previous benchmark calculation then restart the efficiency search. else if( ((input_power_float_region-input_power_float) > 0.10) || ((input_power_float- input_power_float_region) > 0.10) ) { input_power_region_set = 0; reset_efficiencies();//Clear all the efficiency calculations so that the algorithm can properly search for the most efficienct point. toggle_gpio_7(); GPIO_8_OFF; } } break; case 9: eff_9 = efficiency_float_avg; reset_best_cap = 0; if(first_time){ first_time = 0; eff_10 = 0;//Make it come back to try 10 volts again because the first time it may have calculated badly during start up cause this is the starting rectified voltage } if(eff_9 < eff_8){ rectified_voltage_state = 1;//Go to8V } else if(eff_9 < eff_10){ rectified_voltage_state = 3;//Go to 10V } else if(eff_8 < 0.1){ reset_best_cap = 1;//tell theRX to reset the best cap for the rectified voltages because it is ata new power level. rectified_voltage_state = 1;//Explore8V } else if(eff_10 < 0.1){ reset_best_cap = 1;//tell theRX to reset the best cap for the rectified voltages because it is ata new power level. rectified_voltage_state = 3;//Explore 10V } else{ rectified_voltage_state = 2;//Stay at9 Volts because everything else has been tried

197 if(input_power_region_set == 0){ input_power_float_region = input_power_float; input_power_region_set = 1; toggle_gpio_9(); GPIO_8_ON ; } else if( ((input_power_float_region-input_power_float) > 0.10) || ((input_power_float- input_power_float_region) > 0.10) ) { input_power_region_set = 0; reset_efficiencies(); toggle_gpio_7(); GPIO_8_OFF; }

} break; case 10: reset_best_cap = 0; eff_10 = efficiency_float_avg; if(eff_10 < eff_9){ rectified_voltage_state = 2;//Go to9V } else if(eff_10 < eff_11){ rectified_voltage_state = 4;//Go to 11V } else if(eff_9 < 0.1){ reset_best_cap = 1; rectified_voltage_state = 2;//Explore9V } else if(eff_11 < 0.1){ reset_best_cap = 1; rectified_voltage_state = 4;//Explore 11V } else{ rectified_voltage_state = 3;//Stay at 10 Volts if(input_power_region_set == 0){ input_power_float_region = input_power_float; input_power_region_set = 1; toggle_gpio_9(); GPIO_8_ON ; } else if( ((input_power_float_region-input_power_float) > 0.10) || ((input_power_float- input_power_float_region) > 0.10) ) { input_power_region_set = 0; reset_efficiencies();

198 toggle_gpio_7(); GPIO_8_OFF; } } break; case 11: reset_best_cap = 0; if(first_time){ first_time = 0; eff_10 = 0;//Make it come back to try 10 volts again because the first time it may have calculated badly during start up cause this is the starting rectified voltage } eff_11 = efficiency_float_avg; if(eff_11 < eff_10){ rectified_voltage_state = 3;//Go to 10V } else if(eff_11 < eff_12){ rectified_voltage_state = 5;//Go to 12V } else if(eff_10 < 0.1){ rectified_voltage_state = 3;//Explore 10V reset_best_cap = 1; } else if(eff_12 < 0.1){ rectified_voltage_state = 5;//Explore 12V reset_best_cap = 1; } else{ rectified_voltage_state = 4;//Stay at 11 Volts if(input_power_region_set == 0){ input_power_float_region = input_power_float; input_power_region_set = 1; toggle_gpio_9(); GPIO_8_ON ; } else if( ((input_power_float_region-input_power_float) > 0.15) || ((input_power_float- input_power_float_region) > 0.15) ) { input_power_region_set = 0; reset_efficiencies(); toggle_gpio_7(); GPIO_8_OFF; } } break; case 12:

199 reset_best_cap = 0; eff_12 = efficiency_float_avg; if(eff_12 < eff_11){ rectified_voltage_state = 4;//Go to 11V } else if(eff_12 < eff_13){ rectified_voltage_state = 6;//Go to 13V } else if(eff_11 < 0.1){ rectified_voltage_state = 4;//Explore 11V reset_best_cap = 1; } else if(eff_13 < 0.1){ rectified_voltage_state = 6;//Explore 13V reset_best_cap = 1; } else{ rectified_voltage_state = 5;//Stay at 12 Volts if(input_power_region_set == 0){ input_power_float_region = input_power_float; input_power_region_set = 1; toggle_gpio_9(); GPIO_8_ON ; } else if( ((input_power_float_region-input_power_float) > 0.10) || ((input_power_float- input_power_float_region) > 0.10) ) { input_power_region_set = 0; reset_efficiencies(); toggle_gpio_7(); GPIO_8_OFF; } } break; case 13: reset_best_cap = 0; eff_13 = efficiency_float_avg; if(eff_13 < eff_12){ rectified_voltage_state = 5;//Go to 12V } else if(eff_12 < 0.1){ rectified_voltage_state = 5;//Explore 12V reset_best_cap = 1; } else{ rectified_voltage_state = 6;//Stay at 13 Volts

200 if(input_power_region_set == 0){ input_power_float_region = input_power_float; input_power_region_set = 1; toggle_gpio_9(); GPIO_8_ON ; } else if( ((input_power_float_region-input_power_float) > 0.10) || ((input_power_float- input_power_float_region) > 0.10) ) { input_power_region_set = 0; reset_efficiencies(); toggle_gpio_7(); GPIO_8_OFF; } } break; } }

//______//rectified_voltage_utils.h //______//This code is the header file for the rectified_voltage_utils.c

#include

#ifndefRECTIFIED_VOLTAGE_UTILS_H_ #defineRECTIFIED_VOLTAGE_UTILS_H_ void change_rectified_voltage(void);

#endif/*RECTIFIED_VOLTAGE_UTILS_H_*/

¥

201 B.2 Power Receiver Code

//______//main.c //______//This is the main routine that initializes theGPIO pins, the different interrupt driven routines and configures intial variable values.

#include//Atmel standard software framework #include"led_utils.h"//Various header files for their respective source code. #include"gpio_utils.h" #include"adc_utils.h" #include"dme_utils.h" #include"data_recovery.h" void pin_setup(void);//This function initializes the routines. For some reason whenI put it in it’ s own source file it did not work.I did not spend time debugging this. void pin_setup (void){ pmc_enable_periph_clk(ID_PIOA);//Enable the Peripheral clock

//This pin is the internal Differential Manchester Encoding Signal Pin. It must run all the time even when the other6 capacitor drive pins are turned off. This is so that while the other pins might turn on and off, this pin providesa refernce for the current state of the communication signal. ie, either high or low. PIOA -> PIO_IDR |= PIO_PA3;//Disable interrupt on this pin or use: pio_disable_interrupt(PIOA, PIO_PA3); PIOA -> PIO_PUER |= PIO_PA3;//Enable the pull_up on this pin or use: pio_pull_up(PIOA, PIO_PA3, 1); PIOA -> PIO_MDDR |= PIO_PA3;//Disable the Multiple Data Lines feature. otherwise you have to write to theMDER and turn it on PIOA -> PIO_CODR |= PIO_PA3;//Set default value as low PIOA -> PIO_PER |= PIO_PA0;//SetPER to make itaGPIO pin instead ofa peripheral module PIOA -> PIO_OER |= PIO_PA3;//Enable the pin as output

//Below are the six pins to drive the modulated capacitors. //signal1 PIOA -> PIO_IDR |= PIO_PA2; PIOA -> PIO_PUER |= PIO_PA2; PIOA -> PIO_MDDR |= PIO_PA2; PIOA -> PIO_CODR |= PIO_PA2; PIOA -> PIO_PER |= PIO_PA2; PIOA -> PIO_OER |= PIO_PA2;

202 //signal2 PIOA -> PIO_IDR |= PIO_PA3; PIOA -> PIO_PUER |= PIO_PA3; PIOA -> PIO_MDDR |= PIO_PA3; PIOA -> PIO_CODR |= PIO_PA3; PIOA -> PIO_PER |= PIO_PA3; PIOA -> PIO_OER |= PIO_PA3;

//signal3 PIOC -> PIO_IDR |= PIO_PC10; PIOC -> PIO_PUER |= PIO_PC10; PIOC -> PIO_MDDR |= PIO_PC10; PIOC -> PIO_CODR |= PIO_PC10; PIOC -> PIO_PER |= PIO_PC10; PIOC -> PIO_OER |= PIO_PC10;

//signal4 PIOA -> PIO_IDR |= PIO_PA30; PIOA -> PIO_PUER |= PIO_PA30; PIOA -> PIO_MDDR |= PIO_PA30; PIOA -> PIO_CODR |= PIO_PA30; PIOA -> PIO_PER |= PIO_PA30; PIOA -> PIO_OER |= PIO_PA30;

//signal5 PIOA -> PIO_IDR |= PIO_PA29; PIOA -> PIO_PUER |= PIO_PA29; PIOA -> PIO_MDDR |= PIO_PA29; PIOA -> PIO_CODR |= PIO_PA29; PIOA -> PIO_PER |= PIO_PA29; PIOA -> PIO_OER |= PIO_PA29;

//signal6 PIOC -> PIO_IDR |= PIO_PC9; PIOC -> PIO_PUER |= PIO_PC9; PIOC -> PIO_MDDR |= PIO_PC9; PIOC -> PIO_CODR |= PIO_PC9; PIOC -> PIO_PER |= PIO_PC9; PIOC -> PIO_OER |= PIO_PC9;

//___Rectified Voltage Control Pins___ PIOC -> PIO_IDR |= PIO_PC17; PIOC -> PIO_PUER |= PIO_PC17; PIOC -> PIO_MDDR |= PIO_PC17; PIOC -> PIO_CODR |= PIO_PC17;

203 PIOC -> PIO_PER |= PIO_PC17; PIOC -> PIO_OER |= PIO_PC17;

PIOC -> PIO_IDR |= PIO_PC16; PIOC -> PIO_PUER |= PIO_PC16; PIOC -> PIO_MDDR |= PIO_PC16; PIOC -> PIO_CODR |= PIO_PC16; PIOC -> PIO_PER |= PIO_PC16; PIOC -> PIO_OER |= PIO_PC16;

PIOA -> PIO_IDR |= PIO_PA1; PIOA -> PIO_PUER |= PIO_PA1; PIOA -> PIO_MDDR |= PIO_PA1; PIOA -> PIO_CODR |= PIO_PA1; PIOA -> PIO_PER |= PIO_PA1; PIOA -> PIO_OER |= PIO_PA1;

PIOC -> PIO_IDR |= PIO_PC14; PIOC -> PIO_PUER |= PIO_PC14; PIOC -> PIO_MDDR |= PIO_PC14; PIOC -> PIO_CODR |= PIO_PC14; PIOC -> PIO_PER |= PIO_PC14; PIOC -> PIO_OER |= PIO_PC14;

//_____GPIO Pins used for various functions including debugging. They comprise the 13 pin female header on the board_____

//GPIO1 PIOC -> PIO_IDR |= PIO_PC0; PIOC -> PIO_PUER |= PIO_PC0; PIOC -> PIO_MDDR |= PIO_PC0; PIOC -> PIO_CODR |= PIO_PC0; PIOC -> PIO_PER |= PIO_PC0; PIOC -> PIO_OER |= PIO_PC0;

//GPIO2 PIOA -> PIO_IDR |= PIO_PA20; PIOA -> PIO_PUER |= PIO_PA20; PIOA -> PIO_MDDR |= PIO_PA20; PIOA -> PIO_CODR |= PIO_PA20; PIOA -> PIO_PER |= PIO_PA20; PIOA -> PIO_OER |= PIO_PA20;

//GPIO3 PIOC -> PIO_IDR |= PIO_PC12;

204 PIOC -> PIO_PUER |= PIO_PC12; PIOC -> PIO_MDDR |= PIO_PC12; PIOC -> PIO_CODR |= PIO_PC12; PIOC -> PIO_PER |= PIO_PC12; PIOC -> PIO_OER |= PIO_PC12;

//GPIO4 PIOA -> PIO_IDR |= PIO_PA23; PIOA -> PIO_PUER |= PIO_PA23; PIOA -> PIO_MDDR |= PIO_PA23; PIOA -> PIO_CODR |= PIO_PA23; PIOA -> PIO_PER |= PIO_PA23; PIOA -> PIO_OER |= PIO_PA23;

//GPIO5 PIOC -> PIO_IDR |= PIO_PC13; PIOC -> PIO_PUER |= PIO_PC13; PIOC -> PIO_MDDR |= PIO_PC13; PIOC -> PIO_CODR |= PIO_PC13; PIOC -> PIO_PER |= PIO_PC13; PIOC -> PIO_OER |= PIO_PC13;

//GPIO6 PIOA -> PIO_IDR |= PIO_PA22; PIOA -> PIO_PUER |= PIO_PA22; PIOA -> PIO_MDDR |= PIO_PA22; PIOA -> PIO_CODR |= PIO_PA22; PIOA -> PIO_PER |= PIO_PA22; PIOA -> PIO_OER |= PIO_PA22;

//GPIO7 PIOC -> PIO_IDR |= PIO_PC15; PIOC -> PIO_PUER |= PIO_PC15; PIOC -> PIO_MDDR |= PIO_PC15; PIOC -> PIO_CODR |= PIO_PC15; PIOC -> PIO_PER |= PIO_PC15; PIOC -> PIO_OER |= PIO_PC15;

//GPIO8 PIOA -> PIO_IDR |= PIO_PA19; PIOA -> PIO_PUER |= PIO_PA19; PIOA -> PIO_MDDR |= PIO_PA19; PIOA -> PIO_CODR |= PIO_PA19; PIOA -> PIO_PER |= PIO_PA19; PIOA -> PIO_OER |= PIO_PA19;

205 //GPIO9 PIOC -> PIO_IDR |= PIO_PC27; PIOC -> PIO_PUER |= PIO_PC27; PIOC -> PIO_MDDR |= PIO_PC27; PIOC -> PIO_CODR |= PIO_PC27; PIOC -> PIO_PER |= PIO_PC27; PIOC -> PIO_OER |= PIO_PC27;

//GPIO 10 PIOA -> PIO_IDR |= PIO_PA21; PIOA -> PIO_PUER |= PIO_PA21; PIOA -> PIO_MDDR |= PIO_PA21; PIOA -> PIO_CODR |= PIO_PA21; PIOA -> PIO_PER |= PIO_PA21; PIOA -> PIO_OER |= PIO_PA21;

//GPIO 11 PIOA -> PIO_IDR |= PIO_PA18; PIOA -> PIO_PUER |= PIO_PA18; PIOA -> PIO_MDDR |= PIO_PA18; PIOA -> PIO_CODR |= PIO_PA18; PIOA -> PIO_PER |= PIO_PA18; PIOA -> PIO_OER |= PIO_PA18;

//GPIO 12 PIOC -> PIO_IDR |= PIO_PC26; PIOC -> PIO_PUER |= PIO_PC26; PIOC -> PIO_MDDR |= PIO_PC26; PIOC -> PIO_CODR |= PIO_PC26; PIOC -> PIO_PER |= PIO_PC26; PIOC -> PIO_OER |= PIO_PC26;

//GPIO 13 PIOA -> PIO_IDR |= PIO_PA17; PIOA -> PIO_PUER |= PIO_PA17; PIOA -> PIO_MDDR |= PIO_PA17; PIOA -> PIO_CODR |= PIO_PA17; PIOA -> PIO_PER |= PIO_PA17; PIOA -> PIO_OER |= PIO_PA17;

//______LEDS used for Demonstration and Debugging______

//LED1

206 PIOC -> PIO_IDR |= PIO_PC30; PIOC -> PIO_PUER |= PIO_PC30; PIOC -> PIO_MDDR |= PIO_PC30; PIOC -> PIO_CODR |= PIO_PC30; PIOC -> PIO_PER |= PIO_PC30; PIOC -> PIO_OER |= PIO_PC30;

//LED2 PIOB -> PIO_IDR |= PIO_PB2; PIOB -> PIO_PUER |= PIO_PB2; PIOB -> PIO_MDDR |= PIO_PB2; PIOB -> PIO_CODR |= PIO_PB2; PIOB -> PIO_PER |= PIO_PB2; PIOB -> PIO_OER |= PIO_PB2;

//LED3 PIOC -> PIO_IDR |= PIO_PC31; PIOC -> PIO_PUER |= PIO_PC31; PIOC -> PIO_MDDR |= PIO_PC31; PIOC -> PIO_CODR |= PIO_PC31; PIOC -> PIO_PER |= PIO_PC31; PIOC -> PIO_OER |= PIO_PC31;

//LED4 PIOB -> PIO_IDR |= PIO_PB3; PIOB -> PIO_PUER |= PIO_PB3; PIOB -> PIO_MDDR |= PIO_PB3; PIOB -> PIO_CODR |= PIO_PB3; PIOB -> PIO_PER |= PIO_PB3; PIOB -> PIO_OER |= PIO_PB3;

//Input Pin to capture the encoded signal PIOA -> PIO_PUER = PIO_PA6;//Enable the pull_up on this pin or use: pio_pull_up(PIOA, PIO_PA24, 1); //PIOA ->PIO_IFDR= PIO_PA24;//Disable the input filter PIOA -> PIO_PER = PIO_PA6;//SetPER to make itaGPIO pin instead ofa peripheral module PIOA -> PIO_ODR = PIO_PA6;//make the pin input(default) PIOA->PIO_ISR;//Clear the Interrupt Status Register First

} int main (void) {

207 sysclk_init();//Initialize the clock(Atmel routine, althoughI did have to edit to run off an external crystal) pin_setup();//Initialize the pins above WDT->WDT_MR = WDT_MR_WDDIS;//Disable the watchdog timer delay_init(F_CPU);//Initialize the delay function(not actually used, but can be used for debugging) dme_setup();//Setup the Differential Manchester Encoding Variables(Downlink Communication ) DME_timer_01_init(2000);//Setup the Differential Manchester Timer on Timer Module 0, Source 1. adc_setup();//Setup theADC variables and configuration adc_timer_00_init(100);//Setup the timer for theADC interrupt on Timer Module 0, Source 0. data_recovery_setup();//Setup the variables for the data recovery recovered_clock_02_init(4000);//Setup the timer for the data recovery on Timer Module 0, Source 2.

//*There are2 Timer Modules with3 Timer sources each.

//Initially set the regulation point for the rectified voltage at 10V. PIOC -> PIO_CODR |= PIO_PC17;//#1= 1.3MOFF PIOC -> PIO_SODR |= PIO_PC16;//#2= 700kON PIOA -> PIO_CODR |= PIO_PA1;//#3= 700kOFF PIOC -> PIO_CODR |= PIO_PC14;//#2= 215kOFF

while(1){ } }

//______//adc_utils.c //______//This code is responsible for reading the Battery Voltage, Battery Current and Rectified Voltage.

#include"adc_utils.h" //#include"lcd_utils.h" //#include"dme_utils.h" #include"gpio_utils.h"

//______ADC Functions______

void adc_timer_00_init(uint32_t frequ) { uint32_t ra, rc; pmc_enable_periph_clk(ID_TC0); tc_init(TC0, 0, (0 x3u << 0)// Waveform Clock Selection= Clock4=MCK/128(fromPMC) | (0x1u << 15)// Waveform mode is enabled,0 for capture mode

208 | (0x1u << 16)//RA Compare Effect onTIOA: set | (0x2u << 18)//RC Compare Effect onTIOA: clear | (0x2u << 13)// Counter only countsUP with reset onRC Compare ); rc = 120000000/(128*(frequ)); tc_write_rc(TC0, 0, rc); ra = (50 * rc) / 100;//needRA forTIOA trigger ofADC tc_enable_interrupt(TC0,0,TC_IER_CPCS);// Enable interrupt onRC compare tc_write_ra(TC0, 0, ra); NVIC_DisableIRQ(TC0_IRQn); NVIC_ClearPendingIRQ(TC0_IRQn); NVIC_SetPriority(TC0_IRQn,1); NVIC_EnableIRQ(TC0_IRQn); // EnableTCTC_CHANNEL_WAVEFORM. tc_start(TC0,0); } void TC0_Handler(void){//recovered Clock uint32_t status2 = tc_get_status(TC0,0); toggle_gpio_1(); adc_start(ADC);//Software Trigger to start the nextADC readings. } void adc_setup(void){ batt_v_reading = 0; batt_i_reading = 0; rect_v_reading = 0; lcd_next_state = 0; next_batt_v_message = 0; next_batt_i_message = 0; next_rect_v_message = 0; pmc_enable_periph_clk(ID_ADC); //adc_init(ADC, sysclk_get_cpu_hz(),ADC_CLOCK, 10); //8= startup time ADC_MR_STARTUP_SUT512= 512 ADC Clock Cycles ADC->ADC_CR = ADC_CR_SWRST;/* Reset the controller.*/ ADC->ADC_MR = 0;/* Reset Mode Register.*/ ADC->ADC_PTCR = (ADC_PTCR_RXTDIS | ADC_PTCR_TXTDIS);/* ResetPDC transfer.*/ ADC->ADC_RCR = 0; ADC->ADC_RNCR = 0; volatile uint32_t syst_clk = sysclk_get_cpu_hz(); uint32_t ul_prescal = sysclk_get_cpu_hz() / (2 * ADC_CLOCK) - 1;//Calculate the Prescaler ADC->ADC_MR |= ADC_MR_PRESCAL(ul_prescal);//Set the Prescaler ADC->ADC_MR |= (0x00 << 24);//15, TrackTime= TrackTIM+1* ADCClock Periods, Depends on Impedence of Source, look at Datasheet, minimum by default is 15 ADC->ADC_MR |= (0xAu << 16);//Startup= 640 periods of ADCClock ADC->ADC_MR |= (0x3u << 20);//Settling= 17 periods of ADCClock

209 ADC->ADC_MR |= (0x0u << 4);//0= 12 bits,1= 10bits ADC->ADC_CHER |= (0x1u << 4);//use Channel4 which is pin3 ext1 ADC->ADC_CHER |= (0x1u << 5);//use Channel5 which is pin4 ext1 ADC->ADC_CHER |= (0x1u << 13);//use Channel 13 which is pin4 ext3 ADC->ADC_IER |= (0x1u << 4);//Select channel0 Flag for the Interrupt ADC->ADC_MR |= (0x0u << 5);//Sleep Bit: Don’t Sleep ADC->ADC_MR |= (0x0u << 6);//Fast Wake up Bit //ADC->ADC_MR |= (0x1u << 0);//Enable Hardware Trigger //ADC->ADC_MR |= (0x1u << 1);//Triggered by hardware of Timer0 Channel0 adc_configure_trigger(ADC,ADC_TRIG_SW ,0); NVIC_EnableIRQ(ADC_IRQn);/* EnableADC interrupt.*/ } uint32_t counter = 0; void ADC_Handler(void){ toggle_gpio_2(); if ((adc_get_status(ADC) & ADC_ISR_EOC4) == ADC_ISR_EOC4){ //toggle_gpio_3(); batt_v_reading = adc_get_channel_value(ADC,13);//read the value and clear the interrupt prepare_next_batt_v_message(); batt_i_reading = adc_get_channel_value(ADC,4);//read the value and clear the interrupt prepare_next_batt_i_message(); rect_v_reading = adc_get_channel_value(ADC,5);//read the value and clear the interrupt prepare_next_rect_v_message(); } NVIC_ClearPendingIRQ (ADC_IRQn); } uint32_t get_batt_v_reading(void){ return batt_v_reading; } uint32_t get_batt_i_reading(void){ return batt_i_reading; } uint32_t get_rect_v_reading(void){ return rect_v_reading; } void prepare_next_batt_v_message(void){ next_batt_v_message = 0x3000 + batt_v_reading;//header= 0010+ 12 bits of Data; }

210 void prepare_next_batt_i_message(void){ next_batt_i_message = 0x6000 + batt_i_reading;//header= 0010+ 12 bits of Data; } void prepare_next_rect_v_message(void){ next_rect_v_message = 0xC000 + rect_v_reading;//header= 0010+ 12 bits of Data; } uint16_t get_next_batt_v_message(void){ return next_batt_v_message; } uint16_t get_next_batt_i_message(void){ return next_batt_i_message; } uint16_t get_next_rect_v_message(void){ return next_rect_v_message; }

//______//adc_utils.h //______//This code is the header file for the adc_utils.c

#include

#ifndefADC_UTILS_H_ #defineADC_UTILS_H_

//______ADC Declartions and Definations______

#defineADC_CLOCK 6400000 //6.4Mhz, Max is 16MHz and min is1Mhz uint32_t batt_v_reading; uint32_t batt_i_reading; uint32_t rect_v_reading; uint32_t lcd_next_state; uint16_t next_batt_v_message; uint16_t next_batt_i_message; uint16_t next_rect_v_message; void adc_setup(void); void adc_timer_00_init(uint32_t);

211 uint32_t get_batt_v_reading(void); uint32_t get_batt_i_reading(void); uint32_t get_rect_v_reading(void); void prepare_next_batt_v_message(void); void prepare_next_batt_i_message(void); void prepare_next_rect_v_message(void); uint16_t get_next_batt_v_message(void); uint16_t get_next_batt_i_message(void); uint16_t get_next_rect_v_message(void);

#endif/*ADC_UTILS_H_*/

//______//data_recovery.c //This code is responsible for demodulating the downlink communication.

#include"data_recovery.h" //#include"lcd_utils.h" #include"dme_utils.h" #include"led_utils.h" #include"adc_utils.h" uint32_t toggle = 0; uint32_t cycle_count = 0; void recovered_clock_02_init(uint32_t frequ) { uint32_t ra, rc;

pmc_enable_periph_clk(ID_TC2);

// InitTC to waveform mode. tc_init(TC0, 2, (0 x1u << 0)// Waveform Clock Selection= Clock4=MCK/128(fromPMC) | (0x1u << 15)// Waveform mode is enabled,0 for capture mode | (0x1u << 16)//RA Compare Effect onTIOA: set | (0x2u << 18)//RC Compare Effect onTIOA: clear | (0x2u << 13)// Counter only countsUP with reset onRC Compare ); rc = 120000000/(8*(frequ)); tc_write_rc(TC0, 2, rc); ra = (50 * rc) / 100; tc_write_ra(TC0, 2, ra); tc_enable_interrupt(TC0,2,TC_IER_CPCS);// Enable interrupt onRC compare

212 // ConfigureTC interrupts NVIC_DisableIRQ(TC2_IRQn); NVIC_ClearPendingIRQ(TC2_IRQn); NVIC_SetPriority(TC2_IRQn,0); NVIC_EnableIRQ(TC2_IRQn); }

//Initialize all the values to 0. void data_recovery_setup(void){ clock_recovered = 0; rx_clk = 0; reading = 0; old_reading = 0; readings_register = 0; sync_count = 0; synced = 0; state = 0; rx_clk_recovered = 0; new_bit = 0; next_bit = 0; recovered_clk_quarter = 0; correct = 0; shift_reg_receive = 0; shift_reg_receive_size = 15; shift_reg_receive_count = 0; bit_test = 0; rectified_voltage_state = 0; no_message = -2;//This isa counter variable for unreceived downlink messages aftera handshake for downlink communication has been sent. no_message_good_reset_value = -5; no_message_default_reset_value = -1;

searching_for_communication = 0;

bit_counter = 0; recovered_clk_quarter = 0; recovered_clk_cnt = 0;

mod_cap_1_score = 0; mod_cap_2_score = 0; mod_cap_3_score = 0;

mod_cap_fail = 0;

213 //Initialize the"good" capacitance value for each rectified voltage rect_volt_8_good_cap = 0x8; rect_volt_9_good_cap = 0x8; rect_volt_10_good_cap = 0x8; rect_volt_11_good_cap = 0x8; rect_volt_12_good_cap = 0x8; rect_volt_13_good_cap = 0x8; }

//This function was not actually used but it could be used to reset the variables in the event that communication needed to start over from scratch. void reset_communication(void){ clock_recovered = 0; rx_clk = 0; reading = 0; old_reading = 0; readings_register = 0; sync_count = 0; synced = 0; state = 0; rx_clk_recovered = 0; new_bit = 0; next_bit = 0; recovered_clk_quarter = 0; correct = 0; shift_reg_receive = 0; shift_reg_receive_size = 15; shift_reg_receive_count = 0; bit_test = 0;

}

//These functions are not used anymore. They were used to givea reliability score to to each capacitor for each rectified voltage. The score would then be used on deciding which capacitance value should be tried next when the communication failed. Instead, the capacitance values are just cycled. void decrease_mod_cap_score(void){ switch(comm_signals){ case 0x3: mod_cap_1_score -= 1; if(mod_cap_1_score < -5) mod_cap_1_score = -5; break; case 0x8: mod_cap_2_score -= 1; if(mod_cap_2_score < -5) mod_cap_2_score = -5; break;

214 case 0x20: //LED_1_OFF; mod_cap_3_score -= 1; if(mod_cap_3_score < -5) mod_cap_3_score = -5; break; } } void increase_mod_cap_score(void){ switch(comm_signals){ case 0x3: mod_cap_1_score += 1; if(mod_cap_1_score > 5) mod_cap_1_score = 5; break; case 0x8: mod_cap_2_score += 1; if(mod_cap_1_score > 5) mod_cap_1_score = 5; break; case 0x20: mod_cap_3_score += 1; //LED_1_ON; if(mod_cap_1_score > 5) mod_cap_1_score = 5; break; } } void check_bit(void){ if (reading == old_reading){//If the two readings on each side of the negative clock edge are the same then shift_reg_receive = (shift_reg_receive << 1);//the data value is 0. Write this into the data receive buffer. next_bit = 0;//Declare the bit to be 0. //PIOC ->PIO_CODR |= PIO_PC21;//Debug } else{//If the readings are different then the data value is 1. shift_reg_receive = (shift_reg_receive << 1);//Shift the data receive buffer1 to the left. shift_reg_receive = shift_reg_receive |= 1;//Add1 to the data receive buffer next_bit = 1;//Declare the bit to be 1. //PIOC ->PIO_SODR |= PIO_PC21;//Debug } } void read_signal(void){ if(((PIOA->PIO_PDSR) & (1u << 6)) == (1u << 6)) {//Read the Digital Input status of PA6 reading = 1;//If it is high then the reading is 1.

215 readings_register = (readings_register << 1);//Shift the data readings register1 to the left. readings_register = (readings_register |= 1);//Add1 to the readings register } else{ reading = 0;//Otherwise if the signal is low then the reading is0 //PIOC ->PIO_CODR |= PIO_PC21;//Debug readings_register = (readings_register << 1);//Shift the data readings register1 to the left. } } uint32_t message_count = 0;

//Read the data receive buffer void check_shift_reg_receive(void){ if ( (shift_reg_receive == 0x2222) || (shift_reg_receive == 0x222F) ){//Request to regulate to9V toggle_led_1();//Debug:A downlink message was received toggle_gpio_3(); //9V if(rectified_voltage_state == 2){//Do not change states because the state is already9V no_message = no_message_good_reset_value;//Just reset the no message counter to reset value rect_volt_9_good_cap = comm_signals;//save the current modulated cap value as the last good working cap value for this rect voltage } else{ if( (shift_reg_receive == 0x222F) ){//If the command was to reset the knowledge of the best cap value rect_volt_9_good_cap = 0x3;//Then set the best cap to the smallest value which isa combination of signals1 and2(about1nF) toggle_gpio_4(); } comm_signals = rect_volt_9_good_cap;//Otherwise use the last good working cap first for this rectified voltage //comm_signals=0x3;//Alternatively, you could try to use the smallest cap right away, hoping it will work this time. set_all_signals_low();//Lower all the comm signals no_message = no_message_default_reset_value;//Start the no message counter off at the default value } rectified_voltage_state = 2;//Set the Rectified voltage to9 Volts PIOC -> PIO_SODR |= PIO_PC17;//#1= 1.3MON//These pins drive configure the parallel resistors to set the regulation point

216 PIOC -> PIO_CODR |= PIO_PC16;//#2= 700kOFF//Change the regulation point could be done ina more elegant way with higher resolution PIOA -> PIO_CODR |= PIO_PA1;//#3= 700kOFF PIOC -> PIO_CODR |= PIO_PC14;//#2= 215kOFF

//increase_mod_cap_score();//Not used anymore, see the note above by the function code } else if( (shift_reg_receive == 0x3333) || (shift_reg_receive == 0x333F) ){//Request to regulate to 10V //10V toggle_led_1(); toggle_gpio_3(); if(rectified_voltage_state == 3){ no_message = no_message_good_reset_value; rect_volt_10_good_cap = comm_signals; } else{ if( (shift_reg_receive == 0x333F) ){ rect_volt_10_good_cap = 0x3; toggle_gpio_4(); } comm_signals = rect_volt_10_good_cap;//Try using the smaller caps when changing voltage //comm_signals=0x3; set_all_signals_low(); no_message = no_message_default_reset_value;//start of with -1 fora new rectified voltage; } rectified_voltage_state = 3; PIOC -> PIO_CODR |= PIO_PC17;//#1= 1.3MOFF PIOC -> PIO_SODR |= PIO_PC16;//#2= 700kON PIOA -> PIO_CODR |= PIO_PA1;//#3= 700kOFF PIOC -> PIO_CODR |= PIO_PC14;//#2= 215kOFF

//increase_mod_cap_score(); } else if( (shift_reg_receive == 0x4444) || (shift_reg_receive == 0x444F) ){//Request to regulate to 11V //11V toggle_led_1(); toggle_gpio_3(); if(rectified_voltage_state == 4){ no_message = no_message_good_reset_value; rect_volt_11_good_cap = comm_signals; } else{

217 if( (shift_reg_receive == 0x444F) ){ rect_volt_11_good_cap = 0x3; toggle_gpio_4(); } comm_signals = rect_volt_11_good_cap;//Try using the smaller caps when changing voltage //comm_signals=0x3; set_all_signals_low(); no_message = no_message_default_reset_value;//start of with -1 fora new rectified voltage; } rectified_voltage_state = 4; PIOC -> PIO_SODR |= PIO_PC17;//#1= 1.3MON PIOC -> PIO_SODR |= PIO_PC16;//#2= 700kON PIOA -> PIO_CODR |= PIO_PA1;//#3= 700kOFF PIOC -> PIO_CODR |= PIO_PC14;//#2= 215kOFF //increase_mod_cap_score(); } else if( (shift_reg_receive == 0x5555) || (shift_reg_receive == 0x555F) ){//Request to regulate to 12V //12V toggle_led_1(); toggle_gpio_3(); if(rectified_voltage_state == 5){ no_message = no_message_good_reset_value; rect_volt_12_good_cap = comm_signals; } else{ if( (shift_reg_receive == 0x555F) ){ rect_volt_12_good_cap = 0x3; toggle_gpio_4(); } comm_signals = rect_volt_12_good_cap;//Try using the smaller caps when changing voltage //comm_signals=0x3; set_all_signals_low(); no_message = no_message_default_reset_value;//start of with -1 fora new rectified voltage; } rectified_voltage_state = 5; PIOC -> PIO_CODR |= PIO_PC17;//#1= 1.3MOFF PIOC -> PIO_SODR |= PIO_PC16;//#2= 700kON PIOA -> PIO_SODR |= PIO_PA1;//#3= 700kON PIOC -> PIO_CODR |= PIO_PC14;//#2= 215kOFF //increase_mod_cap_score(); }

218 else if( (shift_reg_receive == 0x6666) || (shift_reg_receive == 0x666F) ){//Request to regulate to 13V //13V toggle_led_1(); toggle_gpio_3(); if(rectified_voltage_state == 6){ no_message = no_message_good_reset_value; rect_volt_13_good_cap = comm_signals; } else{ if( (shift_reg_receive == 0x666F) ){ rect_volt_13_good_cap = 0x3; toggle_gpio_4(); } comm_signals = rect_volt_13_good_cap;//Try using the smaller caps when changing voltage //comm_signals=0x3; set_all_signals_low(); no_message = no_message_default_reset_value;//start of with -1 fora new rectified voltage; } rectified_voltage_state = 6; PIOC -> PIO_SODR |= PIO_PC17;//#1= 1.3MON PIOC -> PIO_SODR |= PIO_PC16;//#2= 700kON PIOA -> PIO_SODR |= PIO_PA1;//#3= 700kON PIOC -> PIO_CODR |= PIO_PC14;//#2= 215kOFF //increase_mod_cap_score(); } else if( (shift_reg_receive == 0x1111) || (shift_reg_receive == 0x111F) ){//Request to regulate to8V //8V toggle_led_1(); toggle_gpio_3(); if(rectified_voltage_state == 1){ no_message = no_message_good_reset_value; rect_volt_8_good_cap = comm_signals; } else{ if( (shift_reg_receive == 0x111F) ){ rect_volt_8_good_cap = 0x3; toggle_gpio_4(); } comm_signals = rect_volt_8_good_cap;//Try using the smaller caps when changing voltage //comm_signals=0x3; set_all_signals_low(); no_message = no_message_default_reset_value;//start of with -1 fora new rectified voltage;

219 } rectified_voltage_state = 1; PIOC -> PIO_CODR |= PIO_PC17;//#1= 1.3MOFF PIOC -> PIO_CODR |= PIO_PC16;//#2= 700kOFF PIOA -> PIO_CODR |= PIO_PA1;//#3= 700kOFF PIOC -> PIO_CODR |= PIO_PC14;//#2= 215kOFF //increase_mod_cap_score(); } else{//If the header is not recognizable then count it asa corrupted message toggle_led_3(); //LED_3_OFF if(rect_v_reading > 500){//but only count it asa bad message if the rectified voltage is so high no_message += 1;//This takes affect during the chirp when the rectified voltage is rising and communication is being established. } //decrease_mod_cap_score(); if (no_message >= 3){//If the corrupted message count has reached3 then the amount of capacitance value should be changed. no_message = 0; toggle_led_4(); //Another option to fix communication would be to change the rectified voltage because this also affects the communication link. Below the cap values are cycled between 3 different options. In reality there are 31 options because there are5 different signals.(No communication is nota valid option) if(comm_signals == 0x3){ comm_signals = 0x8; } else if(comm_signals == 0x8){ comm_signals = 0x20; } else if(comm_signals == 0x20){ comm_signals = 0x3; } } } } uint32_t bit_counter = 0; uint32_t recovered_clk_quarter = 0; uint32_t recovered_clk_cnt = 0;

//4kHz clock to read the1kHz data stream. The data recovery for each bit is divided up into4 sections in order to read the encoded signal level on both sides of the negative transition of the data clock. The debugs below could be changed toGPIO pins. They are actuallyGPIO pins, but not labeled as such because

220 theGPIO pins were in only made in the final board design. Before that they were just outputs from the evaluation board header. void TC2_Handler(void){ uint32_t status2 = tc_get_status(TC0,2); //ioport_toggle_pin_level(LED_0_PIN); recovered_clk_cnt += 1; if (recovered_clk_cnt >= 5){//This isa hard coded delay between the request for the transmitter to start sending data and when the transmitter actually sends the data. This was done in lieu of looking fora transition in the data signal because the data signal was too messy often to properly lock on in1 message cycle. //PIOC ->PIO_SODR= PIO_PC31;//Debug: start looking at bits bit_counter += 1; switch(recovered_clk_quarter){ case 0: //PIOC ->PIO_SODR |= PIO_PC21;//Debug: recover clock high recovered_clk_quarter = 1; break; case 1: //PIOC ->PIO_CODR |= PIO_PC21;//Debug: Set the recovered clock low //PIOB ->PIO_SODR= PIO_PB2;//Debug: set high for first reading read_signal(); old_reading = reading; recovered_clk_quarter = 2; break; case 2: //PIOC ->PIO_CODR |= PIO_PC21;//Debug: Keep the recovered clock low //PIOC ->PIO_CODR= PIO_PC31;//Debug: Set Low for Second Reading( Debug) recovered_clk_quarter = 3; break; case 3: //PIOC ->PIO_SODR |= PIO_PC21; read_signal(); //PIOB ->PIO_CODR= PIO_PB2;//Debug: Set Low for Second Reading( Debug) check_bit(); //PIOC ->PIO_SODR= PIO_PC31;//Debug: start looking at bits shift_reg_receive_count += 1; recovered_clk_quarter = 0; if (shift_reg_receive_count > shift_reg_receive_size){ shift_reg_receive_count = 0; //ioport_toggle_pin_level(LED_0_PIN); PIOC -> PIO_CODR = PIO_PC31;//Debug: Stop looking at bits and read receive buffer check_shift_reg_receive();//Read the receive shfit buffer.

221 shift_reg_receive = 0; recovered_clk_quarter = 0; bit_counter = 0; recovered_clk_cnt = 0; tc_stop(TC0,2); } break; } } }

//______//data_recovery.h //______//This code is the header file for the data_recovery.c

#include

#ifndefDATA_RECOVERY_H_ #defineDATA_RECOVERY_H_ void recovered_clock_02_init(uint32_t); void read_signal(void); void check_communication(void); void check_bit(void); void data_recovery_setup(void); void pin_edge_handler(const uint32_t, const uint32_t); void check_shift_reg_receive(void); void reset_communication(void); uint32_t get_batt_v_received(void); uint32_t get_batt_i_received(void); uint32_t get_rect_v_received(void); void decrease_mod_cap_score(void); void increase_mod_cap_score(void); int mod_cap_1_score; int mod_cap_2_score; int mod_cap_3_score; int mod_cap_4_score; int mod_cap_5_score; int mod_cap_6_score; int mod_cap_fail;

222 int rect_volt_8_good_cap; int rect_volt_9_good_cap; int rect_volt_10_good_cap; int rect_volt_11_good_cap; int rect_volt_12_good_cap; int rect_volt_13_good_cap; int no_message_default_reset_value; int no_message_good_reset_value; uint32_t clock_recovered; uint32_t rx_clk; uint32_t reading; uint32_t old_reading; uint32_t readings_register; volatile uint32_t sync_count; uint32_t synced; volatile uint32_t state; uint32_t rx_clk_recovered; uint32_t new_bit; uint32_t next_bit; uint32_t recovered_clk_quarter; uint32_t correct; uint16_t shift_reg_receive; uint32_t shift_reg_receive_size; uint32_t shift_reg_receive_count; uint32_t bit_test; uint32_t communication; uint32_t batt_v_recieved; uint32_t batt_i_recieved; uint32_t rect_v_recieved; uint32_t batt_v_recieved_old; uint32_t batt_i_recieved_old; uint32_t rect_v_recieved_old; uint32_t bit_counter; uint32_t recovered_clk_quarter; uint32_t recovered_clk_cnt; uint32_t rectified_voltage_state; int no_message; int searching_for_communication;

#endif/*DATA_RECOVERY_H_*/

223 //______//dme_utils.c //______//This code is responsible for creating theDME signal for uplink communication.

#include"dme_utils.h" #include"adc_utils.h" #include"led_utils.h" #include"gpio_utils.h"

//Sets up the timer for the Down Link Communication. void DME_timer_01_init(uint32_t frequ) { uint32_t rc; pmc_enable_periph_clk(ID_TC1); tc_init(TC0, 1, (0 x1u << 0)// Waveform Clock Selection= Clock0=MCK/2(fromPMC) | (0x1u << 15)// Waveform mode is enabled,0 for capture mode | (0x1u << 16)//RA Compare Effect onTIOA: set | (0x2u << 18)//RC Compare Effect onTIOA: clear | (0x2u << 13)// Counter only countsUP with reset onRC Compare ); rc = 120000000/(8*(frequ)); tc_write_rc(TC0, 1, rc); tc_enable_interrupt(TC0,1,TC_IER_CPCS);// Enable interrupt onRC compare // ConfigureTC interrupts forDME NVIC_DisableIRQ(TC1_IRQn); NVIC_ClearPendingIRQ(TC1_IRQn); NVIC_SetPriority(TC1_IRQn,0); NVIC_EnableIRQ(TC1_IRQn); tc_start(TC0, 1); } void dme_setup(void){ send_shift_reg_size = 16;//16 bits for each Down link Communication Message send_shift_reg_count = 0;//Data bit counter for the Communication Shift Buffer send_shift_reg = 0xFFFF;//Initialize the Shift buffer comm_state = 0; tx_clk = 0; silence = 0; silence_count = 0; debug_count = 0; tx_clk_startup = 1; tx_clk_startup_count = 0;

224 adc_value_to_send = 0; comm_signals = 0x0008; parity_counter = 0;

} void start_communication(void){ comm_state = 0; send_shift_reg = 0xFFFF; send_shift_reg_count = 0; parity_counter = 0; adc_value_to_send = 0; silence = 0; silence_count = 0; tx_clk = 0; tx_clk_startup = 1; tx_clk_startup_count = 0; comm_signals = 0x0007; tc_start(TC0,1); } void set_signals_high(void){ PIOC -> PIO_SODR = PIO_PC3;

/* set_signal_1_high; set_signal_2_high; set_signal_3_high; set_signal_4_high; set_signal_5_high; set_signal_6_high; */ ///* if (comm_signals & 1) set_signal_1_high; if (comm_signals & (0x2u)) set_signal_2_high; if (comm_signals & (0x4u)) set_signal_3_high; if (comm_signals & (0x8u)) set_signal_4_high; if (comm_signals & (0x10u)) set_signal_5_high; if (comm_signals & (0x20u)) set_signal_6_high; //*/ } void set_signals_low(void){ PIOC -> PIO_CODR = PIO_PC3;

225 /* set_signal_1_low; set_signal_2_low; set_signal_3_low; set_signal_4_low; set_signal_5_low; set_signal_6_low; */

///* if (comm_signals & 1) set_signal_1_low; if (comm_signals & (0x2u)) set_signal_2_low; if (comm_signals & (0x4u)) set_signal_3_low; if (comm_signals & (0x8u)) set_signal_4_low; if (comm_signals & (0x10u)) set_signal_5_low; if (comm_signals & (0x20u)) set_signal_6_low; //*/ } void set_all_signals_low(void){ set_signal_1_low; set_signal_2_low; set_signal_3_low; set_signal_4_low; set_signal_5_low; set_signal_6_low; } uint32_t restart_1 = 0; void TC1_Handler(void)//generates tx clock on Pin9 { uint32_t status_2 = tc_get_status(TC0,1); if (tx_clk_startup){ tx_clk_startup_count += 1; if (tx_clk_startup_count > 10){ tx_clk_startup = 0; tx_clk = 1; } } else{ if (tx_clk){//Rising Edge First of Clock raise_transmit_clock;//Set the clock bit if (silence == 0){ if (signal_is_high) {//Toggle Pin

226 set_signals_low(); } else{ set_signals_high(); } } tx_clk = 0; } else{ tx_clk = 1; lower_transmit_clock;//Clock Falling Edge if (silence == 0){ if (send_shift_reg_count == send_shift_reg_size){ if (parity_counter % 2 == 0){//if its an even number than keep it the same and do nothing to senda0 } else{//senda one to make it an even number of ones. if (signal_is_high){ set_signals_low(); } else{ set_signals_high(); } } } else{ if(next_bit_is_one){//if theMSB is1 then toggle the pin parity_counter += 1; if (signal_is_high){ set_signals_low(); } else{ set_signals_high(); } } } }//if it is0 then do nothing

send_shift_reg = (send_shift_reg << 1);//shift the shift register once to the left send_shift_reg_count += 1;//increment the data sent counter if (send_shift_reg_count > send_shift_reg_size){ send_shift_reg_count = 0; send_shift_reg_size = 16;//reset send_shift size if this is after restart forward communication silence = 0;

227 parity_counter = 0; switch(comm_state){ case start_up: send_shift_reg = 0xFFFF; comm_state = adc_values; break; case adc_values: switch(adc_value_to_send){ case send_batt_voltage: send_shift_reg = get_next_batt_v_message(); //send_shift_reg= get_next_batt_v_message(); //send_shift_reg=0x300F; adc_value_to_send = send_batt_current; break; case send_batt_current: send_shift_reg = get_next_batt_i_message(); //ioport_toggle_pin_level(LED_0_PIN); //send_shift_reg=0x655F; adc_value_to_send = send_rect_voltage; break; case send_rect_voltage: //send_shift_reg= get_next_rect_v_message(); //silence= 0; send_shift_reg = get_next_rect_v_message(); //send_shift_reg=0xCAAF; adc_value_to_send = re_sync; break; case re_sync: //ioport_toggle_pin_level(LED_0_PIN); //PIOB ->PIO_CODR= PIO_PB3;//finish resync message send_shift_reg = 0xFFFF; silence_count += 1; //silence_count= 0; if (silence_count>=10){ silence_count = 0; send_shift_reg = 0xFFF0;//This will tell the power transmitter it can talk next //ioport_toggle_pin_level(LED_0_PIN); adc_value_to_send = down_link; toggle_led_2(); //adc_value_to_send= send_batt_voltage; }

228 else{ adc_value_to_send = send_batt_voltage; } break; case down_link: //PIOB ->PIO_SODR= PIO_PB3;//begin resync message silence = 1; tc_start(TC0,2);//Start the clock for reading the Downlink Communication(Clock is open loop) //PIOC ->PIO_SODR |= PIO_PC21;//recover clock high adc_value_to_send = re_sync;//Resync everything right away in case things went bad during the Downlink time //restart_1= 1;

break; } //comm_state= misc_message; break; case misc_message: send_shift_reg = 0xF00F; comm_state = start_up; //debug_count += 1; //if(debug_count> 100){ // debug_count= 0; // tc_stop(TC0,1); // set_signal_low; //} break; }

} } } }

//______//dme_utils.h //______//This code is the header file for the dme_utils.c

#include

229 #include"gpio_utils.h"

#ifndefDME_UTILS_H_ #defineDME_UTILS_H_

//_____Differential Manchester Encoding Definitions

#define start_up0 #define adc_values1 #define misc_message2

#define send_batt_voltage0 #define send_batt_current1 #define send_rect_voltage2 #define re_sync3 #define down_link4

#define raise_transmit_clock GPIO_13_ON #define lower_transmit_clock GPIO_13_OFF

#define next_bit_is_one send_shift_reg& (1<<15) #define signal_is_high(PIOC ->PIO_ODSR& (0x1u << 3)) == (0x1u << 3)

///

#define set_signal_1_highPIOA->PIO_SODR= PIO_PA2 #define set_signal_1_lowPIOA->PIO_CODR= PIO_PA2

#define set_signal_2_highPIOA->PIO_SODR= PIO_PA3 #define set_signal_2_lowPIOA->PIO_CODR= PIO_PA3

#define set_signal_3_highPIOC->PIO_SODR= PIO_PC10 #define set_signal_3_lowPIOC->PIO_CODR= PIO_PC10

#define set_signal_4_highPIOA->PIO_SODR= PIO_PA30 #define set_signal_4_lowPIOA->PIO_CODR= PIO_PA30

#define set_signal_5_highPIOA->PIO_SODR= PIO_PA29 #define set_signal_5_lowPIOA->PIO_CODR= PIO_PA29

#define set_signal_6_highPIOC->PIO_SODR= PIO_PC9 #define set_signal_6_lowPIOC->PIO_CODR= PIO_PC9

void dme_setup(void);

230 void DME_timer_01_init(uint32_t); void comm_timer_02_init(uint32_t); void start_communication(void); void set_signals_high(void); void set_signals_low(void); void set_all_signals_low(void);

uint32_t send_shift_reg_size; uint32_t send_shift_reg_count; uint16_t send_shift_reg; uint32_t comm_state; uint32_t tx_clk; uint32_t debug_count; uint32_t tx_clk_startup; uint32_t tx_clk_startup_count; uint32_t adc_value_to_send; uint16_t comm_signals; uint32_t locked; uint32_t silence; uint32_t silence_count; uint32_t parity_counter;

#endif/*DME_UTILS_H_*/

//______//gpio_utils.c //______//This code is responsible for defining the functions to turn on and off theGPIO pins

#include"gpio_utils.h" void toggle_gpio_1(void){ if(gpio_1_state){ gpio_1_state = 0; GPIO_1_OFF; } else{ gpio_1_state = 1; GPIO_1_ON ; } } void toggle_gpio_2(void){ if(gpio_2_state){ gpio_2_state = 0;

231 GPIO_2_OFF; } else{ gpio_2_state = 1; GPIO_2_ON ; } } void toggle_gpio_3(void){ if(gpio_3_state){ gpio_3_state = 0; GPIO_3_OFF; } else{ gpio_3_state = 1; GPIO_3_ON ; } } void toggle_gpio_4(void){ if(gpio_4_state){ gpio_4_state = 0; GPIO_4_OFF; } else{ gpio_4_state = 1; GPIO_4_ON ; } } void toggle_gpio_5(void){ if(gpio_5_state){ gpio_5_state = 0; GPIO_5_OFF; } else{ gpio_5_state = 1; GPIO_5_ON ; } } void toggle_gpio_6(void){ if(gpio_6_state){ gpio_6_state = 0; GPIO_6_OFF; } else{ gpio_6_state = 1; GPIO_6_ON ;

232 } }

//______//gpio_utils.h //______//This code is the header file for the gpio_utils.c

#include

#ifndefGPIO_UTILS_H_ #defineGPIO_UTILS_H_

#define GPIO_1_ON(PIOC ->PIO_SODR |= PIO_PC0) #define GPIO_1_OFF(PIOC ->PIO_CODR |= PIO_PC0)

#define GPIO_2_ON(PIOA ->PIO_SODR |= PIO_PA20) #define GPIO_2_OFF(PIOA ->PIO_CODR |= PIO_PA20)

#define GPIO_3_ON(PIOC ->PIO_SODR |= PIO_PC12) #define GPIO_3_OFF(PIOC ->PIO_CODR |= PIO_PC12)

#define GPIO_4_ON(PIOA ->PIO_SODR |= PIO_PA23) #define GPIO_4_OFF(PIOA ->PIO_CODR |= PIO_PA23)

#define GPIO_5_ON(PIOC ->PIO_SODR |= PIO_PC13) #define GPIO_5_OFF(PIOC ->PIO_CODR |= PIO_PC13)

#define GPIO_6_ON(PIOA ->PIO_SODR |= PIO_PA22) #define GPIO_6_OFF(PIOA ->PIO_CODR |= PIO_PA22)

#define GPIO_7_ON(PIOC ->PIO_SODR |= PIO_PC15) #define GPIO_7_OFF(PIOC ->PIO_CODR |= PIO_PC15)

#define GPIO_8_ON(PIOA ->PIO_SODR |= PIO_PA19) #define GPIO_8_OFF(PIOA ->PIO_CODR |= PIO_PA19)

#define GPIO_9_ON(PIOC ->PIO_SODR |= PIO_PC27) #define GPIO_9_OFF(PIOC ->PIO_CODR |= PIO_PC27)

#define GPIO_10_ON(PIOA ->PIO_SODR |= PIO_PA21) #define GPIO_10_OFF(PIOA ->PIO_CODR |= PIO_PA21)

#define GPIO_11_ON(PIOA ->PIO_SODR |= PIO_PA18)

233 #define GPIO_11_OFF(PIOA ->PIO_CODR |= PIO_PA18)

#define GPIO_12_ON(PIOC ->PIO_SODR |= PIO_PC26) #define GPIO_12_OFF(PIOC ->PIO_CODR |= PIO_PC26)

#define GPIO_13_ON(PIOA ->PIO_SODR |= PIO_PA17) #define GPIO_13_OFF(PIOA ->PIO_CODR |= PIO_PA17) void toggle_gpio_1(void); void toggle_gpio_2(void); void toggle_gpio_3(void); void toggle_gpio_4(void); void toggle_gpio_5(void); void toggle_gpio_6(void); void toggle_gpio_7(void); void toggle_gpio_8(void); void toggle_gpio_9(void); void toggle_gpio_10(void); void toggle_gpio_11(void); void toggle_gpio_12(void); void toggle_gpio_13(void); uint32_t gpio_1_state; uint32_t gpio_2_state; uint32_t gpio_3_state; uint32_t gpio_4_state; uint32_t gpio_5_state; uint32_t gpio_6_state; uint32_t gpio_7_state; uint32_t gpio_8_state; uint32_t gpio_9_state; uint32_t gpio_10_state; uint32_t gpio_11_state; uint32_t gpio_12_state; uint32_t gpio_13_state;

#endif/*GPIO_UTILS_H_*/

//______//led_utils.c //______//This code is responsible for the functions to turn on and off the4 Debugging LEDs

#include"led_utils.h" void toggle_led_1(void){

234 if(led_1_state){ led_1_state = 0; LED_1_OFF ; } else{ led_1_state = 1; LED_1_ON ; } } void toggle_led_2(void){ if(led_2_state){ led_2_state = 0; LED_2_OFF ; } else{ led_2_state = 1; LED_2_ON ; } } void toggle_led_3(void){ if(led_3_state){ led_3_state = 0; LED_3_OFF ; } else{ led_3_state = 1; LED_3_ON ; } } void toggle_led_4(void){ if(led_4_state){ led_4_state = 0; LED_4_OFF ; } else{ led_4_state = 1; LED_4_ON ; } }

//______//led_utils.h //______//This code is the header file for the led_utils.c

235 #include

#ifndefLED_UTILS_H_ #defineLED_UTILS_H_

#define LED_1_ON(PIOC ->PIO_SODR |= PIO_PC30) #define LED_1_OFF(PIOC ->PIO_CODR |= PIO_PC30)

#define LED_2_ON(PIOB ->PIO_SODR |= PIO_PB2) #define LED_2_OFF(PIOB ->PIO_CODR |= PIO_PB2)

#define LED_3_ON(PIOC ->PIO_SODR |= PIO_PC31) #define LED_3_OFF(PIOC ->PIO_CODR |= PIO_PC31)

#define LED_4_ON(PIOB ->PIO_SODR |= PIO_PB3) #define LED_4_OFF(PIOB ->PIO_CODR |= PIO_PB3)

void toggle_led_1(void); void toggle_led_2(void); void toggle_led_3(void); void toggle_led_4(void); uint32_t led_1_state; uint32_t led_2_state; uint32_t led_3_state; uint32_t led_4_state;

#endif/*LED_UTILS_H_*/

¥

236 Bibliography

[1] Thilani Imanthika Dissanayake Bogoda. Adaptive Primary Side Control for a Wireless Power Transfer Optimization. Master’s thesis, MIT, 2012. [2] Michael W. Baker and Rahul Sarpeshkar. Feedback Analysis and Design of RF Power Links for Low-Power Bionic Systems. IEEE TRANSACTIONS ON BIOMEDICAL CIRCUITS AND SYSTEMS, 1(1), March 2007. [3] Soumyajit Mandal and Rahul Sarpeshkar. Power-Efficient Impedance- Modulation Wireless Data Links for Biomedical Implants. IEEE TRANSAC- TIONS ON BIOMEDICAL CIRCUITS AND SYSTEMS, 2(4), December 2008. [4] D. C. Galbraith, M. Soma, and R. L. White. A wideband efficient inductive transdermal power and data link with coupling insensitive gain. IEEE TRANS- ACTIONS ON BIOMEDICAL ENGINEERING, 34(4), April 1987. [5] W. Liu, K. Vichienchom, M. Clements, S. C. DeMarco, C. Hughes, E. McGucken, M. S. Humayun, E. de Juan, J. D. Weiland, , and R. Greenberg. A neuro- stimulus chip with telemetry unit for retinal prosthetic device. IEEE JOURNAL OF SOLID STATE CIRCUITS, 35(10), October 2000. [6] G. J. Suaning and N. H. Lovell. CMOS neurostimulation ASIC with 100 channels, scaleable output, and bidirectional -frequency telemetry. IEEE TRANSAC- TIONS ON BIOMEDICAL ENGINEERING, 48(2), February 2001. [7] P. R. Troyk, I. E. Brown, W. H. Moore, and G. E. Loeb. Development of BION technology for functional electrical stimulation: Bidirectional telemetry. In 23rd Annual EMBS International Conference, October 2001. [8] M. Ghovanloo and K. Najafi. A wideband frequency-shift keying wireless link for inductively powered biomedical implants. IEEE TRANSACTIONS ON BIOMEDICAL ENGINEERING, 51(12), December 2004. [9] Y. Hu and M. Sawan. A fully integrated low-power BPSK demodulator for implantable medical devices. IEEE Trans. Circuits Syst. I, Fundam. Theory Appl, 52(12), December 2004. [10] P. Mohseni, K. Najafi, S. J. Eliades, and X. Wang. Wireless multichannel biopo- tential recording using an integrated FM telemetry circuit. IEEE Trans. Circuits Syst. I, Fundam. Theory Appl, 13(3), September 2005.

237 [11] A. Ghahary and B. H. Cho. Design of a transcutaneous energy transmission system using a series resonant converter. In 21st Ann. IEEE Power Specialists Conf, June 1990.

[12] G. A. Kendir, W. Liu, R. Bashirullah, G. Wang, M. S. Humayun, , and J. Wei- land. âĂIJAn optimal design methodology for inductive power link with Class-E amplifier. IEEE Trans. Circuits Syst., Reg. Papers, 52(6), May 2005.

[13] Guoxing Wang, Wentai Liu, Mohanasankar Sivaprakasam, and Gurhan Alper Kendiri. Design and Analysis of an Adaptive Transcutaneous Power Teleme- try for Biomedical Implants . IEEE TRANSACTIONS ON CIRCUITS AND SYSTEMS, 52(10), October 2008.

[14] N. de N. Donaldson and T. A. Perkins. Analysis of resonant coupled coils in the design of transcutaneous links . Medical and Biological En- gineering and Computing, 21(5), September 1983.

[15] Philip R. Troyk and Martin A. K. Schwan. Closed-Loop Class E Transcuta- neous Power and Data Link for MicroImplants . lEEE TRANSACTIONS ON BIOMEDICAL ENGINEERING, 39(6), June 1992.

[16] William J. Heetderks. RF Powering of Millimeter- and Submillimeter-Sized Neu- ral Prosthetic Implants . IEEE TRANSACTIONS ON BIOMEDICAL ENGI- NEERING, 35(5), May 1988.

[17] R. E. Zulinski and J. W. Steadman. Class E power amplifiers and frequency multipliers with finite dc-feed inductance . IEEE Trans. Biomed. Eng, 34(6), September 1987.

[18] M. Soma, D. C. Galbraith., and R. L. White. Radio-frequency coils in im- plantable devices: misalignment analysis and design procedure . IEEE Trans. Biomed. Eng, 34(6), April 1987.

[19] Andrew E. Czarnecki. Efficient Inductively Coupled Resonant Power Transfer for an Implantable Electroencephalography Recording Device. Master’s thesis, NorthEastern, 2008.

[20] R. Bashirullah, M. Sivaprakasam, G. a. Kendir, M. S. Humayun, and J. D. Weiland. A closed loop transcutaneous power transfer system for implantable devices with enhanced stability . IEEE International Symposium on Circuits and Systems, 2(4), December 2004.

[21] O. Omeni and C Toumazou. A CMOS Micro-power Wideband DatdPower Trans- fer System for Biomedical Implants. In Circuits and Systems, May 2003.

[22] C. M. Zierhofer and E. S. Hochmair. High-Efficiency Coupling-Insensitive Tran- scutaneous Power and Data Transmission Via an Inductive Link . IEEE Trans. Biomed. Circuits Syst, 37(7), July 1990.

238 [23] R. Sarpeshkar, W. Wattanapanitch, S. K. Arfin, B. I. Rapoport, S. Mandal, M. W. Baker, M. S. Fee, S. Musallam, and R. A. Andersen. Low-power circuits for brain-machine interfaces. IEEE Trans. Biomed. Circuits Syst, 13(3), September 2005.

[24] L. H. Jung, P. Byrnes-Preston, R. Hessler, T. Lehmann, G. J. Suaning, and N. H. Lovell. A Dual Band Wireless Power and FSK Data Telemetry for Biomedical Implants. In Conference of the IEEE EMBS, August 2007.

[25] Guoxing Wang, Peijun Wang, Yina Tang, and Wentai Liu. Analysis of Dual Band Power and Data Telemetry for Biomedical Implants . IEEE TRANSACTIONS ON CIRCUITS AND SYSTEMS, 6(3), 20012.

[26] Guoxing Wang, Wentai Liu, Mohanasankar Sivaprakasam, Mingcui Zhou, James D. Weiland, and Mark S. Humayun. A Dual Band Wireless Power and Data Telemetry for Retinal Prosthesis . In Proceedings of the 28th IEEE EMBS Annual International Conference, August 2006.

[27] Bryce Hesterman. Denver Chapter, IEEE Power Electronics Society: Analysis and Modeling of Magnetic Coupling. http://www.denverpels.org/Downloads/ Denver_PELS_20070410_Hesterman_Magnetic_Coupling.pdf.

[28] E. Bou, E. Alarcon, and J. Gutierrez. A Comparison of Analytical Models for Resonant Wireless Power Transfer. In Progress In Electro- magnetics Research Symposium Proceedings, August 2012.

[29] Linear Technology. LTC4125: 5W AutoResonant Wireless Power Transmitter. http://cds.linear.com/docs/en/datasheet/4125f.pdf.

[30] IEEE. Introduction to Power Electronics: Chapter 19 Resonant Con- version. http://www.ieee.li/pdf/introduction_to_power_electronics/ chapter_19.pdf.

[31] University of Colorado. THE SERIES RESONANT CONVERTER. http:// ecee.colorado.edu/~ecen5817/notes/ch4.pdf.

[32] University of Colorado. Sinusoidal Approximations. http://ecee.colorado. edu/~ecen5817/notes/sin/ch2.pdf.

[33] WPI. WPI Computer Networks: Data Encoding Techniques. http://www. embedded.com/print/4007497.

[34] Wikipedia. Differential Manchester encoding. https://en.wikipedia.org/ wiki/Differential_Manchester_encoding.

[35] UT Dallas. UT Dallas: Telecommunication Networks: Digital Transmission (Line Coding). https://www.utdallas.edu/~torlak/courses/ee4367/lectures/ CodingI.pdf.

239 [36] Robert Guastella. Back to the future: Manchester encoding - Part 1. http: //www.embedded.com/print/4007497.

[37] Okawa Electric Design. (Sample)Sallen-Key Low-pass Filter Design Tool. http: //sim.okawa-denshi.jp/en/OPstool.php.

[38] U of M, Carnegie Mellon, and U of Detroit Mercy. Introduction: Digital Con- troller Design. http://ctms.engin.umich.edu/CTMS/index.php?example= Introduction§ion=ControlDigital.

[39] Mohammed S. Santina and Allen R. Stubberud. Control Systems, Robotics, and Automation - Vol II: Discrete-Time Equivalents to Continuous-Time Systems. http://www.eolss.net/sample-chapters/c18/e6-43-04-02.pdf.

[40] Peyman Gohari. Portland State University ELEC: Lecture 6: Discrete Equiva- lents. http://web.cecs.pdx.edu/~tymerski/ece452/6.pdf.

[41] Finn Haugen. TechTeam: Discrete-time signals and systems. http: //techteach.no/publications/discretetime_signals_systems/discrete. pdf.

[42] MathWorks: Continuous to Discrete Conversion Meth- ods. http://www.mathworks.com/help/control/ug/ continuous-discrete-conversion-methods.html.

[43] Wikipedia: Infinite Impulse Response. https://en.wikipedia.org/wiki/ Infinite_impulse_response.

[44] Wikipedia: Smith Predictor. https://en.wikipedia.org/wiki/Smith_ predictor.

[45] Control Systems Lab: Discrete-time PID Controller Implementation. http://controlsystemslab.com/ discrete-time-pid-controller-implementation/.

[46] Caltech. Control and Dynamical Systems: Chapter 10 PID Control. http: //www.cds.caltech.edu/~murray/books/AM08/pdf/am06-pid_16Sep06.pdf.

[47] Atmel. AVR221: Discrete PID controller. http://www.atmel.com/images/ doc2558.pdf.

[48] Texas Instruments. Li-Ion Battery Charger solution using the MSP430. http: //www.ti.com/lit/an/slaa287/slaa287.pdf.

[49] Linear Technology. LTC3652: Power Tracking 2A Battery Charger for Solar Power. http://cds.linear.com/docs/en/datasheet/3652fe.pdf.

240