Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LT1054_voltage_mode_buck_DC_ctrl.ino
Go to the documentation of this file.
1 /*
2  Control system for a simple voltage-mode buck converter based on
3  the LT1054. ATMega-based Arduinos (such as the Linduino) only.
4 
5  Reads an analog input pin, compares to desired setpoint, integrates the error,
6  maps the integral to a range from 0 to 255 and uses
7  the result to set the pulse width modulation (PWM) of an output pin.
8  Also prints the results to the Serial Monitor.
9 
10  The circuit:
11  - LT1054 clock overdrive circuit, driven by Digital Pin 3 (PWM capable)
12  - Analog Input 0 connected to buck converter output.
13 
14 
15  Derived from AnalogInOutSerial example:
16  http://www.arduino.cc/en/Tutorial/AnalogInOutSerial
17  PWM frequency adjustment function from:
18  https://playground.arduino.cc/Code/PwmFrequency
19 
20 Copyright 2018(c) Analog Devices, Inc.
21 
22 All rights reserved.
23 
24 Redistribution and use in source and binary forms, with or without
25 modification, are permitted provided that the following conditions are met:
26  - Redistributions of source code must retain the above copyright
27  notice, this list of conditions and the following disclaimer.
28  - Redistributions in binary form must reproduce the above copyright
29  notice, this list of conditions and the following disclaimer in
30  the documentation and/or other materials provided with the
31  distribution.
32  - Neither the name of Analog Devices, Inc. nor the names of its
33  contributors may be used to endorse or promote products derived
34  from this software without specific prior written permission.
35  - The use of this software may or may not infringe the patent rights
36  of one or more patent holders. This license does not release you
37  from the requirement that you obtain separate licenses from these
38  patent holders to use this software.
39  - Use of the software either in source or binary form, must be run
40  on or directly connected to an Analog Devices Inc. component.
41 
42 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
43 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
44 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
46 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
48 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 
53 */
54 
55 // These constants won't change. They're used to give names to the pins used:
56 const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
57 const int analogOutPin = 3; // Analog output pin that the LED is attached to
58 #define fixed 0
59 #define closed_loop 1
60 
61 float vout = 3.3; // Floating poiont output voltage.
62 int setpoint = int (vout * 1024.0 / 5.0);
63 //int setpoint = 512; // 1.25V
64 int feedback = 0; // value read from the pot
65 int outputValue = 0; // value output to the PWM (analog out)
66 int error = 0;
67 int integral = 128;
68 
69 #define verbose
70 
71 void setup()
72 {
73  // initialize serial communications at 115200 bps:
74 #ifdef verbose
75  Serial.begin(115200);
76 #endif
78 }
79 
80 uint8_t state = closed_loop;
81 void loop()
82 {
83  char ch;
84  float fbv, dc;
85  if (Serial.available())
86  {
87  ch = Serial.read();
88  switch (ch)
89  {
90  case '0':
91  state = fixed;
92  outputValue = 0 ;
93  break;
94  case '1':
95  state = fixed;
96  outputValue = 26 ;
97  break;
98  case '2':
99  state = fixed;
100  outputValue = 51 ;
101  break;
102  case '3':
103  state = fixed;
104  outputValue = 77 ;
105  break;
106  case '4':
107  state = fixed;
108  outputValue = 102;
109  break;
110  case '5':
111  state = fixed;
112  outputValue = 128;
113  break;
114  case '6':
115  state = fixed;
116  outputValue = 153;
117  break;
118  case '7':
119  state = fixed;
120  outputValue = 179;
121  break;
122  case '8':
123  state = fixed;
124  outputValue = 204;
125  break;
126  case '9':
127  state = fixed;
128  outputValue = 230;
129  break;
130  case 'A':
131  state = fixed;
132  outputValue = 255;
133  break;
134  case '\r':
135  break;
136  case '\n':
137  break;
138  default:
139  state = closed_loop;
140  }
141  if (ch != '\r' && ch != '\n')
142  {
143  Serial.print("Setting PWM to ");
144  Serial.print(outputValue);
145  Serial.println("/255");
146  }
147  analogWrite(analogOutPin, outputValue);
148  }
149  if (state == closed_loop)
150  {
151  // read the analog in value:
152  feedback = analogRead(analogInPin);
153  error = setpoint - feedback;
154  integral = integral + error/4; //kI = 0.25
155  if (integral > 1023) integral = 1023;
156  if (integral < 0) integral = 0;
157 
158  // map it to the range of the analog out
159  // (could probably just right-shift by two...)
160  // outputValue = map(integral, 0, 1023, 0, 255);
161  outputValue = integral >> 2; // Map 10 bit integral to 8 bit output, maintainting integral precision
162  // change the analog out value:
163  analogWrite(analogOutPin, outputValue);
164 #ifdef verbose
165  // print the results to the Serial Monitor:
166  Serial.print("feedback = ");
167  fbv = (float) feedback * (5.0 / 1024.0);
168  Serial.print(fbv, 2);
169  Serial.print("\t PWM duty cycle = ");
170  dc = (float) outputValue * (100.0 / 256.0);
171  Serial.println(dc, 1);
172 #endif
173  // wait some milliseconds before the next loop for the analog-to-digital
174  // converter to settle after the last reading:
175  delay(10);
176  }
177 }
178 
179 
180 /**
181  * Divides a given PWM pin frequency by a divisor.
182  *
183  * The resulting frequency is equal to the base frequency divided by
184  * the given divisor:
185  * - Base frequencies:
186  * o The base frequency for pins 3, 9, 10, and 11 is 31250 Hz.
187  * o The base frequency for pins 5 and 6 is 62500 Hz.
188  * - Divisors:
189  * o The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64,
190  * 256, and 1024.
191  * o The divisors available on pins 3 and 11 are: 1, 8, 32, 64,
192  * 128, 256, and 1024.
193  *
194  * PWM frequencies are tied together in pairs of pins. If one in a
195  * pair is changed, the other is also changed to match:
196  * - Pins 5 and 6 are paired on timer0
197  * - Pins 9 and 10 are paired on timer1
198  * - Pins 3 and 11 are paired on timer2
199  *
200  * Note that this function will have side effects on anything else
201  * that uses timers:
202  * - Changes on pins 3, 5, 6, or 11 may cause the delay() and
203  * millis() functions to stop working. Other timing-related
204  * functions may also be affected.
205  * - Changes on pins 9 or 10 will cause the Servo library to function
206  * incorrectly.
207  *
208  * Thanks to macegr of the Arduino forums for his documentation of the
209  * PWM frequency divisors. His post can be viewed at:
210  * http://forum.arduino.cc/index.php?topic=16612#msg121031
211  */
212 void setPwmFrequency(int pin, int divisor)
213 {
214  byte mode;
215  if (pin == 5 || pin == 6 || pin == 9 || pin == 10)
216  {
217  switch (divisor)
218  {
219  case 1:
220  mode = 0x01;
221  break;
222  case 8:
223  mode = 0x02;
224  break;
225  case 64:
226  mode = 0x03;
227  break;
228  case 256:
229  mode = 0x04;
230  break;
231  case 1024:
232  mode = 0x05;
233  break;
234  default:
235  return;
236  }
237  if (pin == 5 || pin == 6)
238  {
239  TCCR0B = TCCR0B & 0b11111000 | mode;
240  }
241  else
242  {
243  TCCR1B = TCCR1B & 0b11111000 | mode;
244  }
245  }
246  else if (pin == 3 || pin == 11)
247  {
248  switch (divisor)
249  {
250  case 1:
251  mode = 0x01;
252  break;
253  case 8:
254  mode = 0x02;
255  break;
256  case 32:
257  mode = 0x03;
258  break;
259  case 64:
260  mode = 0x04;
261  break;
262  case 128:
263  mode = 0x05;
264  break;
265  case 256:
266  mode = 0x06;
267  break;
268  case 1024:
269  mode = 0x07;
270  break;
271  default:
272  return;
273  }
274  TCCR2B = TCCR2B & 0b11111000 | mode;
275  }
276 }
static void loop()
static float vout
static int outputValue
static void setPwmFrequency(int pin, int divisor)
Divides a given PWM pin frequency by a divisor.
static void setup()
static uint8_t state
const int analogOutPin