Tag Archives: PWM

MSP430 Timer Tutorial Launchpad article

MSP430 Timer PWM Tutorial

 

In this MSP430 timer PWM tutorial the basic workings of the on board timer peripheral will be explained, along with some C code examples which can be downloadable at the end of the tutorial.  Additionally the video below demonstrates the examples ‘A picture paints a thousand words, a video displays a thousand pictures’.

The MSP430G2253 will be used as it has two timers opposed to the MSP430G2231 which only has one timer, this will allow for different examples to be shown.  All the code in the MSP430 timer tutorial is written in Code Composer Studio (CCS) v5.5.  As the tutorial will be using the MSP430G2253 as the test microcontroller, downloading the datasheet for this maybe of use and can be found here.

Before reading further if you are having trouble understanding how the registers work, and how the C code updates the individual register settings?  It would be worth reading my MSP430 Programming Tutorial, Part 1 covers the basics and Part 2 gives clear examples.  You can find them here Part 1 and Part 2.

The MSP430G2253 has two 16 bit timers, Timer0 and Timer1 both are Timer_A variants with three capture/compare registers.  The MSP430 family guide lists two types of 16 bit timer, Timer_A and Timer_B.  For the most part they are very similar except Timer_A has up to three capture/compare registers, were as Timer_B has up to seven.  The MSP430G2253 also has a watchdog timer which can be used detect system malfunctions, but will not be covered in this tutorial. The feature list for Timer_A is shown below:

  • Asynchronous 16 bit timer/counter with four operating modes
  • Selectable configurable clock source
  • Up to three configurable counter/compare registers
  • Configurable as outputs for PWM
  • Asynchronous input and output latching
  • Interrupt vector register for fast decoding of all Timer_A interrupts

Asynchronous 16 Bit Timer

The 16 bit timer increments or decrements a value from the Timer_A register (TAR), every rising edge of the clock pulse.  The TAR value can be read or written with software, and an interrupt can be enabled to generate when it overflows.  If the timer is run asynchronous to the CPU clock, any reading from the TAR should occur while the timer is not running, as the result is likely to be unpredictable.

The four modes of operation for the timer are:

Stop – The timer is stopped

Up – The timer counts from zero to the value of TACCR0

Continuous – The timer counts from zero to 0FFFFh

Up/Down – The timer repeatedly counts from zero up to the value of TACCRO (+1) and then back down to zero.

Configurable Clock Source

The clock source for the timer can be from ACLK, SMCLK or from an external source via TACLK or INCLK (Device specific).  The clock source selected can be then divided by 1, 2, 4 or 8.

Counter Compare Registers

The capture/compare blocks inside Timer_A are all identical.  Any of the TACCRx blocks may be used to capture timer data or generate intervals.  When in capture mode the Capture Compare inputs CCIxA and CCIxB, can be connected to external pins or internal signals. They can be configured to capture on a rising, falling or both edges.  The compare mode is used to generate PWM output signals, or interrupts at specific time intervals.  Each capture/compare block has an output unit, which is used to to generate output signals like PWM.

Interrupt Vector Register

The Timer_A module has two interrupt vectors linked to it: TACCR0 interrupt vector TACCR0 Capture Compare Interrupt Flag (CCIFG) and Timer_A Interrupt Vector Register (TAIV) for all CCIFG flags and Timer_A Interrupt Flag (TAIFG).  The TACCR0 CCIFG has the highest priority of all the interrupts for Timer_A.  The TAIV is used to prioritise and combine the TACCR1 CCIFG, TACCR2 CCIFG and TAIFG flags.

Timer_A Registers

The Timer_A module is configured with software by setting the bits inside the various registers, which alter the timers parameters.  The image below list the various registers associated with the Timer_A module.

MSP430 Timer Tutorial Guide Timer_A Registers

Timer_A Control

This register determines where the clock is sourced from and how the clock is divided either by 1, 2, 4 or 8.  The timers control mode is also set here, whether it’s stopped, counts up, continuous or up/down.  The TAR , clock divider and count direction can also be reset with the TACLR bit being set.  Lastly the Timer_A interrupt enable/disable and interrupt pending flag are also found here.  A typical command for this register looks like this TA0CTL = TASSEL_2 + MC_1; or TA1CTL = TASSEL_2 + MC_1;

Timer_A Counter

The Timer_A registers or TAR holds the count of Timer_A.  A command using this register could look something like this depending on your application TAR = 4500-1;

Timer_A Capture/Compare 0

The Timer_A capture/compare register 0 or TACCR0, is used in two cases.  In compare mode this holds the value for comparison with the timer value in the TAR.  When in capture mode, the value in the TAR is copied into the TACCR0 when a capture is performed.  An example of the register code would be as follows TA0CCR0 = 200-1;. 

Timer_A Capture/Compare Control 0

The Timer_A capture/compare control register 0 or TACCTL0, is a 16 bit register used to determine how the TACCR0 is set-up.  The register controls whether the timer module is set to capture or compare.  The trigger edge for the capture mode can be set, as well as where the source originates from, either internal or external.  Asynchronous or synchronous operation can determined, as well as synchronised capture or compare input.  There are various output modes, which are used to determine the operation of PWM signals for example.  Also this register allows interrupts to enabled for the timer module.  An example of the register code would be as follows TA0CCTL0 = OUTMOD_7 + CCIE;.

Timer_A Capture/Compare 1

The Timer_A capture/compare register 1 or TACCR1.  Has the same operation as TACCR0.  An example of the register code would be as follows TA0CCR1 = 200-1;. 

Timer_A Capture/Compare Control 1

The Timer_A capture/compare control register 1 or TACCTL1, is a 16 bit register used to determine how the TACCR1 is set-up.  Has the same operation as TACCTL0.  An example of the register code would be as follows TA0CCTL1 = OUTMOD_7;.

Timer_A Capture/Compare 2

The Timer_A capture/compare register 2 or TACCR2.  Has the same operation as TACCR0.  An example of the register code would be as follows TA0CCR2 = 200-1;. 

Timer_A Capture/Compare Control 2

The Timer_A capture/compare control register 2 or TACCTL2, is a 16 bit register used to determine how the TACCR2 is set-up.  Has the same operation as TACCTL0.  An example of the register code would be as follows TA0CCTL2 = CCIE;. 

Timer_A Interrupt Vector

The Timer_A interrupt vector register or TAIV, is used to prioritise and combine the remaining interrupt flags.  When reading the TAIV it will give the value of the current interrupt, as well as clearing that interrupts flag.

 

Timer Example 1

This first example demonstrates the use of one timer, which is used to flash the MSP430G2253 Launchpad LED’s on and off.  The code snippet below only shows the timer set-up and the interrupt handler, as these are the most relevant parts.

The code is fairly short and quite simple to walk through, in line 5 we first load the TA0CCR0 with the value 3000.  Line 6 turns the interrupt on for the TA0CCR0 when it overflows.  Line 7 sets the clock source to ACLK (12kHz) and the counter to count-up mode.  So the interrupt is generated every 250mS approximately.  Line 9 sets the MSP430 to low power mode and enables interrupts.  Lines 12 to 22 are the interrupt handler for Timer0_A, this interrupt automatically clears when called.  Inside the interrupt handler, the variable Control is used to ensure the green LED flashes once for every time the red LED flashes four times.  The closing brace marks the end of the main function.

Example 1 Code

The link below contains the zip file with the full example C code, there is a small advert page first via Adfly, which can be skipped and just takes a few seconds, but helps me to pay towards the hosting of the website.

MSP430 Timer Tutorial Timer Example 1

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

Timer Example 2

The second example demonstrates the use of two timers, which are used to output PWM signals on GPIO pins P1.2 and P2.1.  The timer set-up code and also the GPIO set-up code is shown below.  The clock was set to 8MHz for this example.

Before walking through the code, the image below is extracted from the MSP430G2253 datasheet, this shows GPIO pin P1.2 and it’s functions.  The line which is highlighted demonstrates P1.2 can be used as an input and output for Timer0_A.

MSP430 Timer Tutorial GPIO Pin Functions

Walking through the code starting with line 5, this sets GPIO pin P1.2 as an output.  Line 6 selects the function for GPIO pin P1.2, and in this case it is used for PWM.  Lines 7 and 8 perform the same operation, except they are for GPIO pin P2.1.  line 11 the TA0CCR0 is loaded with 200, this sets the PWM frequency to 40kHz approximately.  Line 12 sets the output mode to reset/set.  Line 13 sets the count value of TA0CCR1, which determines the PWM duty cycle, in this case 50%. Line 14 sets the clock used by the TA0CTL to SMCLK and the counter to count-up mode.  Lines 17 to 20 set-up Timer1_A in the same way as Timer0_A, except the frequency is set to 8kHz approximately.

The image below shows a capture from the oscilloscope for this code, GPIO pin P1.2 is shown on channel 1 and P2.1 is shown by channel 2.

MSP430 Timer Tutorial Dual PWM example

Example 2 Code

The link below contains the zip file with the full example C code, there is a small advert page first via Adfly, which can be skipped and just takes a few seconds, but helps me to pay towards the hosting of the website.

MSP430 Timer Tutorial Timer Example 2

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

Timer Example 3

The third example demonstrates the use of two timers, using PWM generated by Timer0_A and a timed interrupt on Timer1_A to alter the duty cycle.  The PWM output is configured to output on GPIO pin P1.6.  As with the previous code examples, only the timer set-up code is shown. The clock was set to 1MHz for this example.

Lines 5 to 8 in this example are almost identical to lines 5 to 8 in the example 2 code.  The main difference is the PWM frequency is set to 1kHz (clock set to 1MHz) and the duty cycle is initially set to 0.1%.  Lines 11 to 13 set-up Timer1_A, this has a count of 4000 so generates an interrupt every 4mS.  Line 15 sets the MSP430 to low power mode and enables interrupts.

Lines 18 to 25 are the interrupt handler for Timer1_A, as with the first example this interrupt automatically clears when called.  Inside the interrupt the value stored in TA0CCR1 is added to the variable IncDec_PWM which is multiplied by 2 every time the interrupt handler is called.  IncDec_PWM is a global variable and assigned the value 1.  This equates to the value in TA0CCR1 being incremented or decremented by 2, therefore the duty cycle changes by 2 or (0.2%) every time the interrupt handler is called.  This equates to a transition time of approximately two seconds from high to low and low to high.  The final if statement inside the interrupt handler reverses the direction of the duty cycle, causing the LED to decrease in brightness until a value greater than 998 is reached, and increase in value when a value less than 2 is reached.

Example 3 Code

The link below contains the zip file with the full example C code, there is a small advert page first via Adfly, which can be skipped and just takes a few seconds, but helps me to pay towards the hosting of the website.

MSP430 Timer Tutorial Timer Example 3

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

There is also one more additional example for the timer, which demonstrates the capture mode.  This is actually part of a another tutorial based around switch debouncing, the timer is used to capture the undesired pulses generated by a noisy switch.  You can find the additional code by browsing to the end of my Switch Debouncing Tutorial Pt/1.

C2000 Solar MPPT Tutorial 4

C2000 Solar MPPT Tutorial Pt/4

 

In this fourth and final part of the C2000 Solar MPPT Tutorial, the system set-up and testing will be looked at.  This will involve the overall hardware set-up for testing, ADC calibration, reduction of noise on the ADC sampling, efficiency test and some improvements for future iterations.  The final C2000 solar MPPT tutorial C code is also downloadable at the bottom of the page.

System Testing

Once the hardware was calculated and designed, the PCB was laid out and then printed using the freeware version of EagleCad.  The PCB was then printed on a LPKF milling machine, the finished component side of the PCB can be seen in the image below.

C2000 Solar MPPT Tutorial PCBThe board was given a thorough visual check, it was noted some of the drill holes on the component side were marginally out of alignment.  This is due to a slight misaligned of the milling machine alignment pins, the bottom of the PCB is milled first and then flipped so the component side can be milled.  When the board is flipped the minor misaligned becomes apparent, it is not enough to cause an issue, but I manually make all my own footprints allowing for the small idiosyncrasies and tolerances of the milling machine.

The components used for the design were mainly sourced from the education institution stock, with only the INA138 being ordered in.  This reduced any unwanted lead times and also keeps costs down.  There are down sides to this which were found with the IRFI640G MOSFETs.  The mistake was made of soldering these directly onto the PCB without checking the MOSFETs first, they were sourced from a large bag of perhaps 500 or more IRFI640G, all previously reclaimed from other boards.  Once the board was constructed it was noted the power supply was going straight into over current protection, this was narrowed down to two faulty MOSFETs that were short circuit, between Drain and Source.  A quick on the fly test I used to check the MOSFETs can be seen in the image below.

C2000 Solar MPPT Tutorial MOSFET Testing

System Calibration

Once the board was working, the next step was to test the buck circuits under controlled conditions,  The test involved the C2000 being set-up to supply a fixed PWM output of 50% duty cycle on PWM1, with PWM2 180o out of phase.  A dummy load in the shape of a 100W potentiometer set to 50Ω was connected to the output terminal, with a 20V supply applied to the solar panel input pins.  A multimeter was used to then measure the output DC voltage, which was observed to be 10V, this confirmed the buck circuit was operating correctly, the 20V was adjusted down to approximately 15V and the voltage was observed to half on the output.

After this initial test the ADC values being sampled needed to be calibrated, this would involve measuring the input voltage and current as well as the output voltage and current.  To achieve this to a good accuracy the same test conditions were used and two Hewlett Packard 34401A multimeter’s.  Some constant values were calculated from the signal conditioning circuitry (see the second part of this tutorial here) used to sample the ADC values, these were calculated as follows.

C2000 solar MPPT Tutorial ADC Constant Equations

These values would then need to be adjusted to meet the tolerances of the circuit.  A laptop was also set-up running Code Composer Studio (CCS) and the calculated ADC variables were viewed, and then the constant calculations values altered until the accuracy was satisfactory. The actual ADC constant values used can be seen in the below code snippet

Various test were carried out at this point to see how the ADC calibration and sampling was working, experimenting with sample and hold times, over sampling.  A useful tool is the graphing feature in CCS this allows trends to be observed in variables.  The original set-up used a timer to trigger the ADC sampling, however this generated more noise due to the MOSFET switching, so the PWM was used to trigger the ADC SOC.

 

The next image shows a screen capture from CCS, with the debug mode in operation.  The MPPT circuit was supplied with 17.5V from a regulated power supply, the load potentiometer was set to 40Ω, a PWM frequency of 25kHz (not 15kHz) with a 50% duty cycle was used in an open loop configuration.

C2000 Solar MPPT Tutorial 25kHz_25SH

What this graphed data shows is a 2 minute sample window (click the image to expand), the top graph is the input current with a variation of 2.4mA, and the bottom graph input volts with a variation of 10mV.  At the top right of the graph the ADC input variable values can also be seen, the two highlighted in yellow just indicates the value has just changed.

Efficiency Test

This basic efficiency calculation test was made by graphing the the input and output power under different power conditions.  The power efficiency fluctuated between 85~93%, with the greatest efficiency being achieved towards mid-range power.  The graphed data can be seen below with the input power at the top and the output power at the bottom.

C2000 solar MPPT Tutorial Power Efficiency Graph

Improvements

This was a prototype design and the first attempt at a solar MPPT, as such there are some improvements that can be made for future iterations.

On the software side, the clock speed for the C2000 could be reduced as there is plenty of idle time, the processor could also be placed into a low power mode between timer interrupts, this would bring an overall reduction in power dissipation.  Additionally a battery charging statement machine could be easily added, with a further form of regulation to switch between full charge and float charge.  If the circuit did not require an interleaved design, the code structure and algorithm could be easily ported across to a lower power and less expensive microcontroller like an MSP430G series.

On the hardware, the MOSFETs are key components that could be changed making the system more efficient.  Greater use of surface mount devices would reduce the circuit trace lengths and noise.  An improved ground plan design would also help reduce noise.  The trace lengths for each circuit phase ideally need to be identical, this will help to balance the phases.  It is possible to sample the current in each phase, then use software to adjust the duty cycle to correct any imbalances, however this increases the overall systems complexity particularly the software.

C2000 Solar MPPT Tutorial C Code Download

The link below contains the zip file with the complete C code, there is a small advert page first via Adfly, which can be skipped and just takes a few seconds, but helps me to pay towards the hosting of the website.

C2000 Solar MPPT Tutorial Full C Code

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

C2000 Solar MPPT tutorial

C2000 Solar MPPT tutorial Pt/3

 

In this third part of the C2000 Solar MPPT Tutorial, the software will be looked at in greater detail.  This will entail a look at the Perturb & Observe algorithm, ADC code and timing code to ensure everything operates in a controlled manner.

The software is based around a Perturb and Observe (P&O) algorithm, the P&O algorithm falls under the category of a hill climbing algorithm.  Hill climbing algorithms are named so due to the algorithm taking steps over sampled data to reach a desired value, in the case of the P&O this takes steps towards the MPP by increasing or decreasing the duty cycle.  There are other hill climbing algorithms such as dP/dV Feedback Control and Incremental Conductance, I intend to revisit these and write code at a later date, but for now will focus on the P&O.  Some further information on MPPT algorithms can also be found here.

Perturb & Observe Algorithm

The P&O algorithm is a relatively simple algorithm, as such it has a few drawbacks:

  • The algorithm can be confused and track in the wrong direction, this can occur under fast changing irradiance conditions, the severity of this confusion depends on the P&O setup i.e. step size and update frequency.
  • The algorithm oscillates around the set point showing characteristics of an on/off controller.  More on this can be found on a previous tutorial I wrote regarding PID control, which can be found here.

The flowchart below shows the P&O algorithm used for this project

C2000 Solar MPPT Tutorial Perturb and Observe Algorithm Flow Chart

As can be seen from the flowchart the algorithm is fairly easy to follow, turning this into C code is also relatively easy, the final C code P&O algorithm can be seen below inside the function Adj_PWM().

So lets now run through the code briefly starting with line 3, this basically assigns the value in the counter compare A register to variable PWM_Temp.  PWM_Temp could simply be assigned to a temporary global variable, but I chose to get it straight from the register in this case.  Lines 5 to 24 form the main body of the algorithm, looking back at the flowchart the first two steps “Sample” and “Calculate” are carried out elsewhere in the ADC section of the code.  Lines 5 to 14 are illustrated by the right hand branch of the flowchart and lines 15 to 24 are illustrated by the left hand branch of the flowchart.

You have some simple if and else statements that determine which direction the algorithm takes, which is dependant on the sampled ADC data.  The result of these steps will either increase or decrease the PWM duty cycle, this increase or decrease determines the step size and in this case that value is 2.

The next block of code from lines 26 to 31 are used to prevent the duty cycle from reaching too large, and too small a value.  This was used during tuning, but also serves to provide some boundaries for the PWM, for example the duty cycle for the half bridge MOSFET drivers cannot exceed 99%, or the boost function will not operate correctly.

Lines 32 and 33 are used to update the duty cycle to the counter compare A registers for PWM1 and PWM2, both are the same duty cycle but PWM2 is 180o out of phase with PWM1.  Line 35 then assign the latest calculated solar panel voltage IP_Volt to the variable Old_IP_Volt and line 36 assign the latest calculated solar panel power New_PW_In to the variable Old_PW_In, both these variables are then used when the Adj_PWM() function is called again.

In order to help visualise the two PWM signals, the below image shows an oscilloscope trace with PWM1 in yellow and PWM2 in blue, both are set to 50% duty cycle and PWM2 is out of phase by 180o with PWM1.

C2000 Solar MPPT Tutorial 50% Duty 180 Phase

ADC Code

The next piece of code to be looked at is the ADC, I am not going to show the set-up code for the ADC or the PWM that triggers the ADC SOC, but will just show the code relating to the sampling and calculation.  However I intend to write a tutorial on each peripheral inside the C2000 with code examples, when time allows.  The ADC sampling is triggered by the PWM on every first event, therefore the sampling rate is 15ksps.  The final ADC sampling code can be seen below inside the function Data_Update()

So starting with lines 3 to 6 these are the local variables used for the function, the two floats are used to store the ADC values and the two integers are used to determine how many samples in the for loop.  The float in line 4 is a float array with four arrays, now the same result could be achieved with four separate floats.  I have left it as a float array for now, but if four floats were used the code should be optimised, by using 64 samples the following division of 128 (lines 23 to 26) could be substituted with a right bit wise shift of 7.

Lines 8 to 21 consist of the for loop, this uses the integer i as a counter and numberOfsamples as the count value.  Inside the for loop shown on line 10 this statement will wait until the next PWM trigger is received, which then initiates the ADC SOC channel number 0, once ADC channel 0 is finished it initiates channel 1 and so on and so forth.  The samples are saved in each of the channel numbers registers, then using the += addition assignment operator are added to the sum_of_ADC_samples_Array[n].  So an accumulated value is built up of the total samples every time the for loop is executed.  In addition there are 8 ADC channels being sampled, channel 0 to 7, but only 4 samples are accumulated so ADC channel 0 and 4 are added to sum_of_ADC_samples_Array[0] and channel 1 and 5 are added to sum_of_ADC_samples_Array[1] and so on and so forth.  When the ADC channel sampling sequence has finished, the trigger flag for the SOC sequence is cleared (line 20) and the loop waits for the next trigger event from the PWM.  Once i reaches 64 the loop is exited, each of the of the sum_of_ADC_samples_Array[n] now have 128 accumulated sample values in.

Lines 23 to 26 divide the sum_of_ADC_samples_Array[n] by 128 and assign the value to ADC_An floats.  Lines 28 to 31 convert the new floats to real world voltages read on the GPIO. Lines 33 to 36 then use constant values calculated from the electronic component values in the circuitry, to convert the floats to actual voltages and currents sampled in the circuit.  Lines 38 to 40 simply convert the input voltage and current to an input power and the output voltage and current to an output power.

 

Timing Code

The timing code is quite critical as it determines the update frequency of the MPPT, it must also ensure the code does not overrun and cause unpredictable behaviour.  The internal timer module was used, Timer 0 was set-up to trigger an interrupt every 100mS or 10Hz. The interrupt code is shown below.

When the interrupt is called an integer called SysTick is set to one, then the interrupt flag is cleared allowing the interrupt request to be executed and exited quickly.

Inside the main function there is a continuous while loop, the following code is run inside this loop.

Every time the interrupt sets the integer called SysTick to one, it allows the functions Data_Update() and Adj_PWM() to be executed, once these functions have completed SysTick is set to zero.  There are some additional lines of code on line 5 and line 10, these are used for testing and allowing the code execution time to be displayed on an oscilloscope.  The code on line 5 switches GPIO pin 19 high, then the code on line 10 switches GPIO pin 19 back to low, so a square wave pulse is produced and the pulse width gives an indication of the code execution time of the functions Data_Update() and Adj_PWM(). The following images show captures from an oscilloscope.

C2000 solar MPPT PWM and MPPT update frequency

This first image shows the 15kHz PWM being displayed on channel 1, the individual wave pulses are not visible as the time base is set to display channel 2.  The blue trace shown on channel 2 can be seen to have a frequency of 10Hz, with a pulse width of 4.4mS, so the functions Data_Update() and Adj_PWM() take 4.4mS to execute.  Putting this into context there should be 128 ADC samples captured, taken from 64 triggers of the PWM signal, therefore 64*66.67uS (one 15kHz cycle) = 4.27mS.  A single ADC sample and conversion takes around 650nS, if we multiply that by the 8 samples, a conversion is being completed every 8*650nS = 5.2uS (it will be faster than this due to ADC pipelining effects).  It can be clearly seen that there is plenty of room for more oversampling if required, as the 5.2uS sample and conversion time easily fits inside the 66.67uS window of the PWM trigger.  There is also a small amount of code overhead being added artificially by toggling GPIO pin 19, which is not significant but something to be aware of.

C2000 solar MPPT PWM and MPPT update frequency zoomed

The second image has a smaller time base setting (100uS) effectively zooming in, which allows the individual pulses from the 15kHz PWM to be visible.  So going back to the step size of 2 shown in the Adj_PWM() function, this can be put into context when the maximum duty cycle value as a variable, for 100% duty cycle equals 1000.  Therefore with a PWM update frequency of 10Hz and a maximum step size of 2, this equates to a maximum duty cycle change of 2% per second.

I captured some video which shows 3 variables being graphed in Code Composer Studio, these variables are PV Power, PV Volts and the Duty Cycle.  The video also demonstrates the MPPT in action under simulated fast changing cloud conditions, as well as some natural cloud.

There will be one final part to this series of tutorials this will cover some of the set-up and testing, and will also include a link to the full C code for the project.

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

C2000 Solar MPPT Tutorial 3

C2000 Solar MPPT tutorial Pt/2

 

In this second part of the C2000 Solar MPPT Tutorial, the hardware and circuit design will be looked at in greater depth.  The schematic for the system is posted again below for reference, which can be enlarged by simply clicking on it.

C2000 Solar MPPT Tutorial PWM and MPPT update frequency zoomed hardware schematic

Buck Converter Design

The first step was to design the buck circuit, this is determined by the output parameters of the system and it’s load.  For the first prototype based around the panel purchased for testing, it was decided to aim for a 12V output, therefore a maximum current of 750mA (assuming 10% losses).

When calculating a buck circuit the frequency of operation, inductor size and output capacitor size are important, as they determine the current and voltage ripple size.  It is desirable to have as smaller current and voltage ripple as possible.  A large current ripple can cause additional losses in a system, as there maybe times when the peak current is greater than the load requirements.  A large voltage ripple is obviously not desirable, good quality regulated power supplies have very low voltage ripples.

A general rule is the higher the frequency the smaller the inductor and output capacitor size, and a smaller inductor and capacitor size generally lowers the system cost.  However higher PWM frequencies decrease the system efficiency due to switching losses in the mosfets, so a trade off has to be reached which meets the design constraints of the end system.

For this system a PWM frequency of 15kHz was chosen, based on this, the solar panel and other design parameters for the buck circuit calculations can be performed.  First we can determine the system duty cycle at MPP, note the duty cycle will change to track the MPP with differing irradiance.  A figure of 90% was used for the buck converter efficiency,a typically buck converter efficiency is 90% or greater.

C2000 Solar MPPT Tutorial duty cycle equation

Next an ideal current ripple can be determined, it is important to note that the below formulae used only determines a single phase current ripple.

C2000 Solar MPPT Tutorial current ripple equation

ΔIL is the inductor ripple current, and in this case a 30% figure was used for the multiplier. Now that the current ripple is know the inductor size can be calculated with the following equation.

C2000 Solar MPPT Tutorial inductor size equation

Using two 1.34mH inductors on each phase will ensure the inductor ripple current is effectively halved, knowing this an inductor ripple current of 90mA can be used to calculate the minimum output capacitor size.

C2000 Solar MPPT Tutorial output capacitor size equation

Δvout is the desired ripple voltage.  The constant 8 is determined by the simplification of an equation, which can be found in various sources, one such source is an Application Note by On-Semiconductor AND9135/D.

There are two other factors for the inductor and capacitor that are important to consider: the inductor peak current and the capacitors Equivalent Series Resistance (ESR).  The inductor for this project will be hand wound using a toroidal core, which will be covered shortly.  The capacitors ESR can affect the reliability of the capacitor.  A capacitor will dissipate power as heat depending on it’s ESR, so a low ESR is desirable as excessive heating will shorten the life of a capacitor and be less efficient.  For this early prototype, cheap off the shelf capacitors were used as their reliability over time was not a concern at this stage.

The inductors were constructed using a T68-26A toroidal core, this core has a nominal inductance or Al value of 58nH.  The following equation was used to determine how many turns of wire the core would need.

C2000 Solar MPPT Tutorial inductor turns ratio equation

A 0.3mm outside diameter enamelled cable was chosen, this has a maximum current rating of 1.4A.  Then a very useful website found here was used, this allows you to calculate the total length of cable required based on the toroidal core dimensions and cable diameter. Using a vice the cores were both wound and then measured using a LCR meter and measured at 1.3mH, an image below shows the hand winding process used.

C2000 solar MPPT toroidal inductor core winding

MOSFET Losses

For the prototype system Vishay IRFI640G MOSFETs were used, these are not the most efficient having a high RDSON value (180mΩ), but they were stocked at the time of writing.

The power losses from the High Side and Low Side MOSFETs are a combination of conduction and AC switching losses.  The conduction losses are a result of I²R losses inside the MOSFET when it is fully on, and the switching losses are the result of the MOSFET transitions from its on and off states.  Some example calculations will now be shown using data from the IRFI640G datasheet and various sources, on a synchronous MOSFET buck circuit efficiency.

C2000 Solar MPPT Tutorial switching losses legend

The first equation is for the High Side MOSFET and is based on the Vmp of the solar panel at maximum output current running through each interleaved phase.

C2000 Solar MPPT Tutorial High Side losses equation

The next equation is for the Low Side MOSFET using the same current figure.

C2000 Solar MPPT Tutorial Low Side losses equationThe results from these two equations can be combined to work out the overall efficiency, the losses will also be multiplied by a factor of 2 as this is for a two phase interleaved circuit.

C2000 Solar MPPT Tutorial 15kHz Power losses equation

Now if we increase the PWM frequency to 150kHz, the circuit losses will also be shown to increase.

C2000 Solar MPPT Tutorial 150kHz Power losses equation

The switching losses in this next example will be shown to increase with increasing current, the next example uses a 15kHz switching frequency but with 2A, increasing the overall power to 24W.

C2000 Solar MPPT Tutorial 15kHz at 2A Power losses equation

A MOSFET with a lower RDS(ON) will have lower conduction losses, but it will typically have a higher QG (Gate Charge) resulting in higher switching losses.  Therefore a careful balance between these characteristics should be found to maximise the circuits efficiency.  Taking into account the nominal parameters of the system, such as input voltage, output current, switching frequency and duty cycle, will allow the best efficiency to be achieved.  This will often involve using MOSFETs with different characteristics for the High and Low Side drivers.

 

MOSFET Driver Circuit

The Half-Bridge (H-Bridge) driver is an IC designed specifically for driving MOSFETs. The IC takes the incoming PWM signal, and then drives two outputs for a High and a Low Side MOSFET.  This type of H-bridge is often used to to drive motors, but has other applications such as the following example.  The IC used is a IRS2003 half bridge driver made by International Rectifier, the image below shows an example circuit from the datasheet.

C2000 Solar MPPT Tutorial IRS2003 example circuit

The IRS2003 allows 2 PWM signals to be connected to HIN and LINNot this gives the user the opportunity to fine tune the dead-band switching of the MOSFETs.  The capacitor wired between VB and VS along with the diode form a charge pump, this allows the drive voltage to the MOSFETs to be almost doubled.  HIN and LINNot in this case are wired together and supplied with the same PWM signal, the IRS2003 has internal timing to ensure the High Side MOSFET, and the Low Side MOSFET are never on at the same time.  The capacitor between VB and VS needs to be sized to ensure it can drive enough current to the gate of the chosen MOSFET, over coming the gate capacitance.

ADC Feedback Circuits

There are four ADC ports used on this project, two sampling voltage and two sampling current.  The hardware employed to sample the voltage signals will be covered first, followed by the current sampling circuit.  But first a brief introduction to the TMS320F28027 ADC.

The ADC measures voltage from 0V to 3.3V, with a 12bit resolution.  It is important to not exceed the input voltage of the microcontrollers GPIO pins, the TMS320F28027 has a maximum input voltage of 3.63V.  Using this information the step resolution for the ADC can be calculated.

C2000 Solar MPPT Tutorial ADC resolution equation

The input on the ADC also has a small internal capacitance and resistance, this is used for Sample and Hold acquisition depending on the characteristics of the circuit being sampled. The internal ADC circuit taken from the TMS320x2802x datasheet is shown below.

C2000 Solar MPPT Tutorial internal ADC S-H

To ensure the readings being sampled are as accurate as possible, the source resistance or RS shown in the above image ideally needs to be as small as possible.  This will be achieved by placing an opamp configured as a unity gain buffer in all the ADC sample circuits.  The unity gain buffer will ensure a high input impedance, therefore reducing loading effects on the sampled circuitry to a minimum, as well as offering a very low output impedance to the C2000 internal ADC circuit.  Rail to rail opamps were used and supplied with 3.3V, this ensured the voltage passed to the ADC would not exceed this, thus ensuring the system has ADC protection built in.

The voltage sampling circuits consist of a simple potential divider, the maximum voltage the solar panel can produce is 21.6V when open circuit.

C2000 Solar MPPT Tutorial voltage potential divider equation

The same resistor and opamp configuration is used for the input and output voltage measurement.  A more complex opamp circuit could have been used with offset, to fully exploit the range of the ADC, however this would provide more than enough accuracy for the prototype.

The current sampling circuit involved a slightly more complex approach.  The circuit would revolve around a Texas Instruments INA138 High Side Measurement current shunt monitor. The INA138 is basically a differential amplifier housed inside a small package, with a wide operating voltage.  The INA138 would be supplied with 12V, this then allows for a greater range to be measured around the 0V-3.3V range and was also the second supply voltage available for this circuit.  A typical configuration taken from the datasheet is shown in the image below.

C2000 Solar MPPT Tutorial INA138 typical circuit

There are differences in input and output current so two formulas would be needed to ensure the range was correct.  The shunt resistors comprised of two 1Ω (1%) resistors in parallel, so the combined value becomes 0.5Ω.  The parallel resistors were measured and the actual value was approximately 0.47Ω.  A quick calculation to check these could withstand the power loads was made.

C2000 Solar MPPT Tutorial shunt resistor power equation

This was not the best long term solution, but within tolerance for the 1% resistors in parallel.

The shunt resistor is connected directly across the internal differential amplifiers inputs. The calculations for the INA138 are fairly simple, the gain resistor soldered externally determines the overall gain of the device.  The datasheet for the INA138 states that the device has a gain of 1 with a 5kΩ resistor, gain of 2 with a 10kΩ, gain of 5 with a 25kΩ and so on and so forth. The input and output current gain resistors were calculated as follows.

C2000 Solar MPPT Tutorial INA138 gain resistors equation

These values would ensure the output from both the current feedback circuits falls in-line with the ADC input.

Schematic Design and Layout

Certain aspects of the design were simulated in OrCad 16.6 first, to back-up the theory with simulation.  Then the design was taking over to EagleCad to enable faster prototyping.  Component symbols and foot prints where designed for all the non standard parts, ensuring these were all compatible with the LPKF milling machine used.  Once the schematic design was complete and the Electrical Rule Check (ERC) and Design Rule Check (DRC) were satisfactory, a schematic design was made for a two layer board.  The layout kept the PWM and digital switching side and analogue circuitry away from each other to avoid unnecessary noise.  The below image shows the final PCB prototype layout.

C2000 Solar MPPT Tutorial PCB layout

The next part of this tutorial will go more in-depth into the C2000 software and Perturb and Observe algorithm, also including a downloadable version of the C code.

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

C2000 Solar MPPT Tutorial C code Perturb and Observe algorithm

C2000 Solar MPPT tutorial Pt/1

 

This series of four posts will cover a project build for a C2000 Solar MPPT Tutorial.  The Maximum Power Point Tracker (MPPT) circuit is based around an interleaved synchronous buck circuit topology.  The microcontroller used is the Texas Instruments (TI) C2000 family, the C2000 Launchpad is used which has a TMS320F28027 chip on-board.  Considerable research was carried out on this project, as there was no prior knowledge of the C2000, all the relevant peripherals were tested separately and then brought together and tweaked for the final code.  TI provides all the documentation required, which can be found here and for this tutorial the ADC, ePWM and the F2802x Peripheral Driver Library Users’ Guide were referenced.

The C2000 solar MPPT tutorial can also be used as a guide if designing a circuit for other microcontrollers such as Arduino, as the electronic principles and some of the code is transferable to any platform.

The image below shows the final prototype MPPT PCB with the C2000 Launchpad secured on top via the header connections.

C2000 Solar MPPT Tutorial final prototype PCB

The video below shows the system set-up, allowing the Perturb and Observe algorithm to be tuned.  There is also a second video demonstrating the algorithm tracking the maximum power point of the solar panel, this can be found on my YouTube account and will be embedded in the final tutorial.

In this part a basic overview of the hardware design will be covered, further tutorial parts will cover the following areas in greater detail:

  • Buck circuit calculation, a look at MOSFET efficiency, current and voltage sampling and circuit design and layout
  • Software approach including phase shifted PWM, ADC sampling and the Perturb and Observe algorithm
  • Final set-up, testing and tuning

Maximum Power Point Tracking

Maximum power point tracking is employed, to ensure the maximum power is extracted from a solar panel.  In order to understand this further we first need to look at the power curve characteristics of a solar panel, the image below shows a Suntech STP230-20Wd (230W panel) power curve.

C2000 Solar MPPT Tutorial solar panel power curve

The maximum power point (MPP) of a solar panel lies at the knee of the current and voltage curve.  Reading the datasheet on the Suntech panel tells us that Vmp (voltage at maximum power point) is 29.8V and Imp (current at maximum power point) is 7.72A, locating the intersection point of these two values, it can be seen that the MPP is at the knee of the curve. The graph also illustrates that the voltage variation is much less compared to the current only with differing irradiance, however the current varies linearly with solar intensity.  Temperature also affects the power output from a panel, current increases slightly with an increase in temperature, whereas voltage decreases with an increase in temperature.  As the voltage is affected by temperature more than the current, voltage calculations need to be considered when large string arrays are used, to ensure the system meets the requirements of the inverter used.

The panel has an internal resistance which changes dynamically with differing irradiance levels.  So if a static load is connected directly to a panel and its resistance is higher or lower than the panels internal resistance at MPP, then the power drawn from the panel will be less than the maximum available.  Taking a simple example under bright midday sun, say we connected the Suntech STP230-20Wd directly to a 12V lead acid battery, the panel voltage would be dragged down near to the load voltage of the battery as the batteries resistance is lower than the panels.  With a quick calculation the panel is now outputting 12V and 7.72A, therefore 93W, this equates to a loss of 137W or 60%. Obviously this is an extreme example, but even using a 24V battery would still equate to a 20% loss, which is far from efficient.

This is where MPPT comes into play.  MPPT circuits can be based on various switch mode power supply (SMPS) topologies, they generally have a fixed frequency but varying duty cycle.  The duty cycle is controlled via an algorithm so as to track the changing MPP, the output power is determined by the efficiency of the circuit and usually closely matches the incoming power within 3-10% (typical losses).  The output voltage and current will not necessarily be fixed under changing irradiance conditions depending on the system employed, so further circuitry maybe required or a more elaborate algorithm.

System Overview

The image below shows an overview of the final system

C2000 Solar MPPT Tutorial Prototype System Diagram

The solar panel in the diagram will be represented in real life by a 10W panel purchased from Ebay, this has a Vmp of 17.2V and an Imp of 580mA.  Four ADC inputs and 2 PWM outputs will be used on the C2000.  The input voltage and current and output voltage and current will both be monitored, so the input and output power can be determined.  A pair of half bridge driver integrated circuits (IC) will be used to drive the four N-Channel MOSFETs. There is also an auxiliary supply, this was used to power a 12V linear regulator which powered the half bridge drivers.  The 12V regulator could also be powered directly from the panel, which was used in testing under bright sun conditions.

 

The chosen SMPS topology will be based on a synchronous buck converter circuit, there will be two of these in parallel forming an interleaved design.  Using an interleaved approach is over kill for the 10W panel prototype, but it gives the system scalability for future iterations.  The synchronous buck design was chosen as it offers a higher efficiency, these design choices will become clear as the tutorial progresses.

Interleaved Synchronous Buck Converter

The buck converter circuit will be over viewed as this forms a large part of the system design, this will naturally lead into the advantages of the synchronous and interleaved design chosen.  A boost circuit could quite easily be implemented in place of buck design, but in this case the target output voltage was 12V.

A buck converter is basically a small DC to DC converter.  The main principle at work in a buck converter, is the tendency for an inductor to resist changes in current.  A buck converter output voltage will always be lower or the same as the input voltage.  A simplified schematic of a buck converter can be seen in the below image.

C2000 Solar MPPT Tutorial buck converter circuit

A buck converter relies on a switch to change or reduce the current flowing through the inductor, the switch usually takes the form of a MOSFET (Q).

  1. When the MOSFETs gate is saturated effectively closing the switch, current flows through the inductor (L) in a clockwise direction into the load (R) and also charging the output capacitor (C).  At this point the voltage on the cathode of the diode is positive, therefore the diode (D) is blocking any flow of current and is said to be reverse biased.  The Instantaneous current flow into the load from Vin is slow, as energy is stored in the inductor as it’s magnetic field increases.  So during the on phase of the MOSFET, energy is loaded into the inductor.
  2. When the MOSFET is switched off, the voltage across the inductor is reversed.  The inductors magnetic field begins to collapse, this collapse releases the stored energy allowing current to flow from the inductor into the load.  The diode now has a negative voltage on the cathode so becomes forward biased.  Therefore the inductors discharge current flows in a clockwise direction through the load and back through the diode. Once the inductors energy has fallen below a certain threshold, the load voltage falls and the capacitor becomes the main source of current, ensuring the load is still supplied until the next switching cycle begins.  To ensure Continuous Conduction Mode (CCM) the inductor must not be fully discharged before the MOSFET is switch on again, and the cycle repeats.

Now that the basic concept of a buck converter has been explained the synchronous design can be covered.  The synchronous design simply replaces the diode with a second MOSFET, this eliminates the losses incurred by the forward voltage drop across the diode, thus making the circuit more efficient.  This is slightly more complex to implement, as the second mosfet switching needs to be carefully timed with the switching of the first mosfet.  It is essential to ensure that both are never on at the same time, or the current will have a direct path to ground, effectively causing a short circuit.  The MOSFET switching is effectively 180 degrees out of phase, with a short delay period between each transition referred to as a Dead-Band.  A dead-band is usually a common feature of most half bridge drivers, the C2000 also allows for the dead-band to be programmed in and tuned, so in reality with modern microcontrollers this is quite simple to implement.

The interleaved design simply takes two synchronous buck circuits and places them in parallel, the main components MOSFETs and inductor are individual to each circuit, but they share a common input and output as well as the same input and output capacitors.  Using an interleaved design reduces the current ripple by half, as each interleaved phase shares the total current.  The shared current allows smaller inductors and capacitors to be used, which can also reduce system size and cost.  Additionally this systems PWM frequency was chosen to be 15kHz as it reduces the switching losses in the MOSFETs, but increases the current ripple and also the inductor size.  By using the interleaved approach it then helps to negate these factors.  These trade-offs will be covered in more detail in the hardware section of this tutorial, where MOSFET losses will be covered.

10W Solar Panel

As mentioned previously the solar panel was purchased from Ebay for around £20.  It’s a polycrystalline panel, which is encased in an aluminium frame and comes with 2 large croc clip leads and a small diode box.  The panel seems pretty good quality and appears to be weather proofed, the diode box is not sealed very well but as it sits under the panel I don’t believe there would be any issues.  Have enclosed 2 shots of the panel, and I can probably dig out the links to the company if anyone is interested.

C2000 Solar MPPT Tutorial 10W panel front

C2000 Solar MPPT Tutorial 10W panel back

System Schematic

C2000 Solar MPPT Tutorial hardware schematic

The next part of this tutorial will go more in-depth into the circuit calculations and schematic design.

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

PID tutorial C code example using a Stellaris LM3S6965

PID Tutorial C code Example Pt/2

In this PID tutorial C code example Pt/2, the basic concept of a Boost PID controller will be explored.  All the PID controller C code is stepped through, as well as some basic concepts for testing and tuning the controller.  The final C code example can be downloaded via the link at the end of the article.

Hardware Overview

The image below shows a rough blocked out diagram of the boost circuit and feedback loop.

PID Tutorial C code Example using a Stellaris LM3S6965

As can be seen it’s a fairly simple design, with the output voltage being monitored and fed back to the LM3S6965.

A schematic for the boost converter can be seen below, this circuit was originally made to test a variable voltage boost converter.  The original design would use a 5V input which would then be boosted to either 9V, 12V or 15V, this was controlled via a state machine running on the Stellaris LM3S6965.

PID Tutorial C code Example using a Stellaris LM3S6965

The drive circuit for the mosfet uses 2 transistors in a totem pole configuration, and a 3rd transistor is to ensure a small current is sourced from the LM3S6965.  The main boost circuit itself consists of L1, Q1, D1 and C3.  The sampled output voltage via the potential divider is first passed through an operational amplifier U1A, configured as a non inverting amplifier which provides a gain of 2.2.  The operational amplifier U1B acts as a unity gain buffer, it’s input is connected to 3 resistors R7, R8 and R9.  These 3 resistors provide the offset voltage of 770mV and U1B ensures there is a high impedance input.  The output of U1B feeds the offset voltage to R4 and then to the negative input on U1A (effectively offsetting ground).  The boost converter was originally set-up to measure voltages between 4V and 19V.  So the operational amplifier arrangement with offset, ensures the sampled voltage range uses almost the full range of the ADC.  For the PID testing the output voltage will be regulated to 9V, which is equal to 353 on the ADC which is also the set point value.

Software

The software used was written after reading various sources on PID.  It has been designed so it is easy to understand, as it uses local and global variables.  A more efficient way would be to use a typedef structure or typedef struct in C.

So firstly we have our constants and global variables.

In the first part of this tutorial the proportional (Kp), integral (Ki) and derivative (Kd) constant values were mentioned.  These are the values which provide the tuning for the PID control system.  The next constant is the set point, this was observed as the read ADC value, when 9V was present on the output.  The 9V was measured and adjusted using a multimeter with a fixed load on the output, the duty cycle had a fixed value which was then increased until 9 volts was reached.  The first 2 global variables are used to store the accumulated and historic error values required for integration and differentiation.  The global variable PWM_Temp is initially given a value, then this is used to store the old duty cycle value, which is then used in the new duty cycle calculation.

The next set of variables are all local to the PID function called PWM_Duty_Change(), all the code that follows will be inside this function, until the closing brace of the function is stated and mentioned.  Additionally the entire code which was used on the LM3S6965 can be downloaded (bottom of the page), so it can be seen how and when the function was called.

The first 2 local variables are called iMax and iMin, these are used to prevent integral windup.  More will explained on integral windup further in the tutorial, but for now we will just run through the variables.  The next 4 variables have already briefly been touched upon in part 1 of this tutorial, these are Err_Value, P_Term, I_Term and D_Term.  Then we are left with new_ADC_value which is simply the latest sampled value form the ADC, and finally PWM_Duty which will be the new PWM duty cycle value passed to the timer module.

The read ADC code does not need much explanation, other than a function was created to read the ADC and return the value as an integer.  If you are using this code on another microcontroller, you simply need to construct an ADC read function, then insert instead of the read_ADC().

Going back to part 1 of this tutorial it was shown that the error value can be obtained, by simply taking the newest error value away from the set point, that’s all this line performs.

To obtain the proportional term the Kp constant is multiplied by the error value.

The accumulated error value is used in integration to calculate the average error, so first the current error value must be added to the accumulated value, and that’s what this line performs.

The if and else if statements are used to cap the accumulated integral term, by simply setting upper and lower thresholds.

The integral term is then calculated by multiplying the Ki constant with the accumulated integral value.

The first line of this code snippet calculates the derivative term.  To understand how the code works the second line needs to be run through quickly, this basically assigns the newest ADC value to the d_temp global variable.  So the d_Temp variable effectively stores the historic error value, therefore allowing the derivative to be calculated.  Now looking at the first line again, the newest ADC value is taken away from the historic value, the difference between the 2 would allow the rate of change to be calculated (assuming the time between the readings is a known quantity). Then this value is multiplied by the derivative constant and assigned to the derivative term.

Now that we have all the PID terms calculated, they can be used to change the PWM duty cycle.  This next piece of code adds all the PID terms together, then they are subtracted from the PWM_Temp variable (PWM_Temp usage is shown shortly as it comes towards the end of the function).  This value is then assigned to the PWM_Duty variable.  The way the PID terms are used here is specific to this program, firstly the sum of the PID terms is subtracted, this is due to the final electronic circuit used.  What’s important here is the PID terms are summed, then they need to be used in such away as to construct a valid PWM duty cycle or other chosen control method.

The if and else if statements are used to prevent the duty cycle from going too high or too low, in this case this simply prevents the output voltage from going too high or too low.  If say you were using a half bridge driver integrated circuit, these usually state a maximum duty cycle of say 99%, if this is exceeded the voltage doubler cannot function correctly, so having limits can be a good protection system.

This line is again limited to this specific application, it simply calls the function adjust_PWM(), which has the new PID calculated duty cycle value, as a parameter.

The final statement in the function before the closing brace, assigns the current PWM duty cycle value to the PWM_Temp global variable.

Integral windup can occur if the integral term accumulates a significant error, during the rise time to the set point.  This would cause the output to overshoot the set point, with potentially disastrous results, it can also cause additional lag in the system.  The integral windup prevention used in this example, places a cap on the maximum and minimum value the integrated error can be.  This effectively sets a safe working value and is considered good working practice in any PID system.  The values used for integral windup as with the PID constant gain values are specific to this system, these would need to be determined and tuned to your system.

Step Response

The intention was to also explore the well documented Ziegler-Nichols approach, however time constraints for the project did not allow this method to be fully explored.  Some basic concepts of how to carry out a step response test will be shown, as I am sure it will prove useful.

The systems step response shows how the system responds to a sudden change, electronic circuits switch quickly, so an oscilloscope was the best piece of equipment for the job.  The boost converter was set up with a fixed load, a fixed PWM duty cycle and no feedback , therefore in an open loop configuration.  Then some additional test code was added, initiating these 2 extra functions when a button was pressed on the LM3S6965 development board :

  1. A free GPIO pin would be taken from low to high
  2. The PWM duty cycle would decrease by 10% effectively increasing the output voltage

The free GPIO pin would be connected to channel 2 on the oscilloscope, and in this way can be used as a trigger to start a capture event.  Channel 1 on the oscilloscope would be connected to the output of the boost converter, thereby capturing the step response as the output voltage rises.  The image below is a photograph of the captured step response on the oscilloscope.

PID Tutorial C code Example using a Stellaris LM3S6965

The GPIO pin was polled before the PWM duty cycle was updated, however this happens so quickly, it is difficult to distinguish this.  The lower square wave type step is the GPIO pin on channel 2, and the top curved step response is the output from the boost converter.  It can be seen to overshoot it’s settling level at the beginning then oscillate for a time before settling down, this oscilloscopes accuracy wasn’t the best, using a longer time base did not show any extra detail on the oscillations.

If the step response was of a first order, a calculation based on the reaction curve could be performed.  However the step response from the boost circuit is of a second order, and has an under-damped nature.  In order to explore this calculation further, requires another tutorial altogether, however further reading on this can be found here.

The step response of a similar system under the control of a PID controller can also be viewed.  This can be achieved by using a similar set up, the external pin is used again to trigger an oscilloscope capture.  That same GPIO pin is also used to switch a mosfet, which places an additional load in parallel with the output of the boost converter.  The PID algorithm will then regulate the output voltage to ensure it meets the set point with the new load, and the step response can then be captured.

Testing and Tuning

The system was set up and a basic tuning approach was used, the image below shows the system on the test bench.

PID Tutorial C code Example using a Stellaris LM3S6965

The image shows the following pieces of equipment:

  • Hewlett Packard multimeter connected to the output, monitoring the output voltage
  • Bench power supply, supplying 5V to the circuit
  • Oscilloscope, used to monitor the PWM duty cycle
  • 0-100Ω bench potentiometer
  • Boost converter PCB, LM3S6965 development board and a laptop to tweak the code

With everything connected the PID algorithm was set up, but with only the proportional part in operation.  The set point was set to 353 as mentioned previously, which produced close to 9V give or take 10-15mV.  The load was fixed and set to 100Ω.  Initially the proportional gain constant Kp was set very low around 0.001, this was too low so it was increased over a few steps until 0.01.  At this point the output voltage was observed to be approximately 7.5V, and the duty cycle waveform was observed to have a small amount of jitter, as the duty cycle fluctuated +/- 0.5%.  The Kp value was again increased, until the output voltage read approximately 8V, the duty cycle was again observed and found to be fluctuating by a greater amount, by approximately +/-5%.  The increase in jitter on the PWM duty cycle can be equated to greater oscillations on the output voltage, the multimeter was not suitable for observing these.  It would have been possible to see them on the oscilloscope but this probably would have involved a stop capture then restart method, therefore to make the process quicker the PWM duty cycle was considered ‘good enough’.

At this point the Kp value was backed off, to the previous level of 0.01 so the output voltage was at 7.5V.  This point can be considered close to the offset level mentioned in part 1 of this tutorial, and for ease of reading the image showing the offset level can again be seen below. This image also illustrates again how too larger Kp value can introduce instability in the output.

PID Tutorial C code Example using a Stellaris LM3S6965

Now with this level reached, the integral part of the algorithm was introduced.  All the hardware was untouched, just a simple modification to the algorithm was made.  The initial value chosen for Ki was 0.01.  This was then loaded on to the LM3S6965 and the output voltage on the multimeter was immediately observed to read 9.02V, +/-10mV.  The oscilloscope was also observed to have minor jitter as before of only a few half percent.  The integral value was not tweaked any further, but in most cases tuning the Kp and Ki values would take a greater time and under a wide range of conditions.

With the PI controller working on a basic level, the next test was to see how it performed under different load conditions.  First the bench potentiometer was left at 100Ω and the input current and output voltage were noted, the wiper was then moved to the middle (approximately 50Ω) and again the output voltage and input current were noted.  At 100Ω the output voltage was 9.02V with a current of 180mA, at 50Ω the output voltage was 8.99V with a current of 500mA, both output voltages still showed minor voltage variations in the +/-10mV range.

The next step was to move the potentiometer wiper rapidly between the 100Ω and 50Ω position, then observe the output voltage and duty cycle (not the most scientific test, but goes some way to demonstrating the system).  With this test being performed the duty cycle was observed to rapidly increase and decrease, too quick to observe anything further and a step response would be the best method to use here.  The output voltage was observed to have a minor variations, fluctuating +/-15-20mV

After this test, the derivative constant was introduced and tweaked to find the best settings. The Kd constant was not observed to have a huge affect on the system, unless increased dramatically which produced instability.  This set up is not ideal for testing the derivative term and a more detailed and longer term approach would be best.

The basic test performed seemed to conclude the PI controller was working as per the research carried out.  The system used here updates at a very fast rate, therefore observing the step response at this point would be best practice.  As this system has no critical importance other than to explore PID, it simply wasn’t necessary to tune it to a high degree of accuracy.  I have a number of projects in the works however, which touch on this subject again and I intend to post them when I have time.

Example Code

The link below contains the zip file with the complete C code and an external functions folder, there is a small advert page first via Adfly, which can be skipped and just takes a few seconds, but helps me to pay towards the hosting of the website.

PID LM3S6965 C code

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.

Stellaris LM3S6965 PWM post banner

Stellaris LM3S6965 PWM Tutorial

In this tutorial the Stellaris LM3S6965 Evaluation board will be used to demonstrate a simple PWM (Pulse Width Modulated) example.  This is part of a larger project I am working on, which is not covered in this tutorial but will be posted at a later date.

When carrying out any programming on the Stellaris LM3S series, I would highly recommend downloading the Peripheral Driver Library PDF, this contains details of all the functions used to control the on chip peripherals.  The current release at the time of writing is spmu019p.pdf and can be downloaded from here

You will also need to install StellarisWare which is the Texas Instruments library files for the Stellaris and also contains code examples.  Viewing the various libraries while in code composer can be very useful to fully understand what each function does.  The 2 files for the PWM are pwm.h and pwm.c, which can be found in the StellarisWare installation folder, in my case this C:/StellarisWare/driverlib/

The first thing that needs to be setup with the Stellaris is the system clock, the following code below uses the external crystal oscillating at 8MHz.

Next the PWM peripheral needs to be enabled, there are 3 PWM modules on the LM3S6965 evaluation board.  For this example PWM0 will be used, which is located on GPIO port F.

The next step is assign a pin type to the GPIO, there is a specific function to configure a pin or pins for use by the PWM peripheral.

PWM0 and GPIO pin 0 on port F is assigned, this combination was used for the PWM as it allows the onboard status LED to be controlled by varying the brightness, and will also allow a meter to be used to measure the frequency from the PWM.  The image below and left shows the I/O Break Pads, the image on the right the on board peripheral signals, both are extracts from the LM3S6965 evaluation board user guide.

Stellaris LM3S6965 PWM TutorialStellaris LM3S6965 PWM Tutorial

 

 

 

 

 

 

 

After the GPIO is setup the PWM can now be configured.  As stated before there are 3 PWM modules on this particular microprocessor, only 1 is being used in this example PWM0.  Each PWM generator module has a 16 bit counter, 2 PWM comparators, a PWM signal generator, a dead-band generator and an interrupt/ADC-trigger selector.  This program example will just produce a simple output using the up down counter.

PWMGenConfigure() is used to set the mode of operation for the PWM generator.  The counting mode, syncronization mode, and debug behaviour are all configured.  Once configured the generator is in a disabled state.  A code snippet of this function is shown below.

PWMGenPeriodSet() is used to set the period of the PWM generator.  Note the comment regarding the placement of this function with regards to PWMGenConfigure().

PWMPulseWidthSet() is used to set the width of the pulse for the specified PWM ouput.    Note the comment regarding the placement of this function with regards to PWMGenConfigure().

PWMGenEnable() is used to enable the timer/counter of the PWM generator.

PWMOutputState() enables or disables the PWM outputs.

In this example a frequency of approximately 24kHz was generated, with approximately a 50% duty cycle.  The image below shows a basic multimeter with a frequency counter, displaying a value which coincided with the example program, and 2 further images showing Oscilloscope traces with the PWM duty cycle at 50% and 15%.

Stellaris LM3S6965 PWM Tutorial

 

Image with PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, 166);

Stellaris LM3S6965 PWM Tutorial

Image with PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, 50);

Stellaris LM3S6965 PWM Tutorial

Example Code

The link below contains the zip file with the complete C code, there is a small advert page first via Adfly, which can be skipped and just takes a few seconds, but helps me to pay towards the hosting of the website.

Stellaris LM3S6965 PWM C code

I take great care when writing all the tutorials and articles, ensuring all the code is fully tested to avoid issues for my readers.  All this takes time and a great deal of work, so please support the site by using the Adfly links etc.  If you have found this useful or have any problems implementing, please feel free to leave a comment and I will do my best to help.