| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

Precision_Voltage_Source.ino
Go to the documentation of this file.
1 /*
2 Linduino Precision Voltage Source
3
4 This project implaments the LTC2756 18-bit dac to create a high accuracy voltage source.
5
6 Output range is -5v to + 5v.
7
8 Copyright 2018(c) Analog Devices, Inc.
9
10 All rights reserved.
11
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14 - Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 - Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20 - Neither the name of Analog Devices, Inc. nor the names of its
21 contributors may be used to endorse or promote products derived
22 from this software without specific prior written permission.
23 - The use of this software may or may not infringe the patent rights
24 of one or more patent holders. This license does not release you
25 from the requirement that you obtain separate licenses from these
26 patent holders to use this software.
27 - Use of the software either in source or binary form, must be run
28 on or directly connected to an Analog Devices Inc. component.
29
30 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
31 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
32 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
34 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
36 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #include <Arduino.h>
43 #include <stdint.h>
44 #include "Linduino.h"
45 #include "UserInterface.h"
46 #include "LT_I2C.h"
47 #include "LT_SPI.h"
48 #include "QuikEval_EEPROM.h"
49 #include "LTC2756.h"
50 #include <Wire.h>
51 #include <SPI.h>
52 #include <LiquidCrystal.h>
53
54 // LCD constants
55 const int16_t RS = 8;
56 const int16_t E = 9;
57 const int16_t D4 = 4;
58 const int16_t D5 = 5;
59 const int16_t D6 = 6;
60 const int16_t D7 = 7;
61 const int16_t BUTTON_PIN = 0;
62 const int8_t UP = 1;
63 const int8_t DOWN = 2;
64 const int8_t LEFT = 3;
65 const int8_t RIGHT = 4;
66 const int8_t SELECT = 5;
67
68 int8_t demo_board_connected; // Demo Board Name stored in QuikEval EEPROM
69
70 // Global Variables
71 float LTC2756_lsb = 3.8146972656e-5; // Typical lsb for -5V to +5v bipolar mode only
72 int32_t LTC2756_offset = 0x20000; // Typical offset for -5V to +5v bipolar mode only
73 int16_t pos; // Digit position variable
74 int8_t volts[5] = {0, 0, 0, 0, 0}; // Array that holds the desired volts
75 int8_t hex[5] = {0x00, 0x00, 0x00, 0x00,0x02}; // Array that holds the desired DAC code
76 uint8_t HEX_DEC; // Holds the the mode (HEX code or Voltage)
77 bool sign = 0; // Holds the current sign for decimal voltage
78
79 // initialize the library with the numbers of the interface pins
80 LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
81
82 void setup()
83 {
84 char demo_name[] = "DC1792"; // Demo Board Name stored in QuikEval EEPROM
85 quikeval_SPI_init(); // Configure the spi port for 4volts SCK
86 quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz
87 quikeval_SPI_connect(); // Connect SPI to main data port
88
89 demo_board_connected = discover_demo_board(demo_name); //! Checks if correct demo board is connected.
90
91 lcd.begin(16, 2); // Initialize LCD
92
93 // Display Message
94 lcd.print("Voltage Source");
95 delay(2000);
96
97 if (!demo_board_connected) // Checks for the correct demo board
98 {
99 lcd.clear();
100 lcd.print("No Demo Board");
101 lcd.setCursor(0, 1);
102 lcd.print(" Detected");
103 while (1); // Does nothing if the demo board is not connected
104 }
105
106 init_dac();
107 if ( (read_switches() == SELECT)) // If SELECT button is held on startup, Menu is in HEX mode
108
109 {
110 HEX_DEC = 1;
111 pos = 4;
112 lcd.setCursor(0, 1);
113 lcd.print("HEX Mode");
114 delay(2000);
115 }
116 else
117 {
118 HEX_DEC = 0;
119 pos = 4;
120
121 }
122 lcd.clear();
123 }
124
125 void loop()
126 {
127
128 if (HEX_DEC)
129 display_hex(); // Hex MODE
130 else
131 display_decimal(); // Decimal mode
132 }
133
134 // Reads the Switches
135 // Returns the selected button
136 int8_t read_switches()
137 {
138 int16_t input = 0;
139
140 input = analogRead(BUTTON_PIN);
141 if ((input <= 170) && (input >= 120))
142 return UP;
143 if ((input <= 350) && (input >= 300))
144 return DOWN;
145 if ((input <= 550) && (input >= 450))
146 return LEFT;
147 if ((input <= 800) && (input >= 700))
148 return SELECT;
149 if (input <= 100)
150 return RIGHT;
151 return 0;
152 }
153
154 // Initializes the DAC to 0V in bipolar mode
155 void init_dac()
156 {
157 uint8_t tx[4],rx[4];
158
159 // Set DAC to -5v to +5v
160 tx[3] = LTC2756_WRITE_SPAN;
161 tx[2] = 0x00;
162 tx[1] = LTC2756_BIPOLAR_N5_P5;
163 tx[0] = 0x00;
164
165 LTC2756_transfer_4bytes(LTC2756_CS, tx, rx);
166
167 // Set DAC Voltage to 0V
168 tx[3] = LTC2756_WRITE_CODE;
169 tx[2] = 0x80;
170 tx[1] = 0x00;
171 tx[0] = 0x00;
172
173 LTC2756_transfer_4bytes(LTC2756_CS, tx, rx);
174
175 // Update DAC
176 tx[3] = LTC2756_UPDATE;
177 tx[2] = 0x00;
178 tx[1] = 0x00;
179 tx[0] = 0x00;
180
181 LTC2756_transfer_4bytes(LTC2756_CS, tx, rx);
182 }
183
184 // Converts decimal to voltage
185 void set_voltage()
186 {
187 float voltage=0;
188
189 //Convert the Array to a float
190 voltage += volts[0]*.0001;
191 voltage += volts[1]*.001;
192 voltage += volts[2]*.01;
193 voltage += volts[3]*.1;
194 voltage += volts[4];
195 if (sign) // adjusts for the sign
196 voltage *= -1;
197
198 // Convert voltage to code
199 uint32_t code;
200 code = LTC2756_voltage_to_code(voltage, LTC2756_lsb, LTC2756_offset);
201
202 uint8_t tx[4],rx[4];
203 union
204 {
205 uint8_t byte[4];
206 uint32_t code;
207 } data;
208
209 // Load tx array with write command and code
210 data.code = code<<6;
211 tx[3] = LTC2756_WRITE_CODE;
212 tx[2] = data.byte[2];
213 tx[1] = data.byte[1];
214 tx[0] = data.byte[0];
215
216 LTC2756_transfer_4bytes(LTC2756_CS, tx, rx);
217
218 // Load tx arra with update DAC command
219 tx[3] = LTC2756_UPDATE;
220 tx[2] = 0x00;
221 tx[1] = 0x00;
222 tx[0] = 0x00;
223
224 LTC2756_transfer_4bytes(LTC2756_CS, tx, rx);
225 }
226 void display_decimal()
227 {
228 int8_t in;
229
230 in = read_switches();
231
232 // Display Name
233 lcd.setCursor(0, 0);
234 lcd.print("Voltage Source");
235
236 // Display voltage
237 lcd.setCursor(0, 1);
238 lcd.print("V:");
239 if (sign)
240 lcd.print("-");
241 else
242 lcd.print("+");
243 lcd.print(volts[4]);
244 lcd.print(".");
245 lcd.print(volts[3]);
246 lcd.print(volts[2]);
247 lcd.print(volts[1]);
248 lcd.print(volts[0]);
249
250 // Controls position
251 if (in == RIGHT)
252 pos -= 1;
253 if (in == LEFT)
254 pos += 1;
255 if (pos > 5)
256 pos = 0;
257 if (pos < 0)
258 pos = 5;
259
260 // Sets cursor to correct location
261 lcd.cursor();
262 if (pos == 0)
263 lcd.setCursor(8, 1);
264 if (pos == 1)
265 lcd.setCursor(7, 1);
266 if (pos == 2)
267 lcd.setCursor(6, 1);
268 if (pos == 3)
269 lcd.setCursor(5, 1);
270 if (pos == 4)
271 lcd.setCursor(3, 1);
272 if (pos == 5)
273 lcd.setCursor(2, 1);
274
275 // V_Out Array Control
276 if (in == UP)
277 {
278 if (pos == 5)
279 sign -= 1;
280 else
281 volts[pos] += 1;
282 lcd.noCursor();
283 lcd.clear();
284 }
285 if (in == DOWN)
286 {
287 if (pos == 5)
288 sign -= 1;
289 else
290 volts[pos] -= 1;
291 lcd.noCursor();
292 lcd.clear();
293 }
294 if (pos == 4)
295 {
296 if (volts[pos] < 0)
297 volts[pos] = 5;
298 if (volts[pos] > 5)
299 volts[pos] = 0;
300 }
301 else
302 {
303 if (volts[pos] < 0)
304 volts[pos] = 9;
305 if (volts[pos] > 9)
306 volts[pos] = 0;
307 }
308
309 //Sets the DAC when select is pressed
310 if (in == SELECT)
311 {
312 set_voltage();
313 lcd.clear();
314 }
315 delay(150);
316
317 }
318 void display_hex()
319 {
320 int8_t in;
321
322 in = read_switches();
323
324 // Display Name
325 lcd.setCursor(0, 0);
326 lcd.print("Voltage Source");
327
328 // Display HEX code
329 lcd.setCursor(0, 1);
330 lcd.print("DAC code:0x");
331 lcd.print(hex[4], HEX);
332 lcd.print(hex[3], HEX);
333 lcd.print(hex[2], HEX);
334 lcd.print(hex[1], HEX);
335 lcd.print(hex[0], HEX);
336
337 // Controls position
338 if (in == RIGHT)
339 pos -= 1;
340 if (in == LEFT)
341 pos += 1;
342 if (pos > 4)
343 pos = 0;
344 if (pos < 0)
345 pos = 4;
346
347 // Sets cursor to correct location
348 lcd.cursor();
349 if (pos == 0)
350 lcd.setCursor(15, 1);
351 if (pos == 1)
352 lcd.setCursor(14, 1);
353 if (pos == 2)
354 lcd.setCursor(13, 1);
355 if (pos == 3)
356 lcd.setCursor(12, 1);
357 if (pos == 4)
358 lcd.setCursor(11, 1);
359
360
361 // Array Control
362 if (in == UP)
363 {
364 hex[pos] += 1;
365 lcd.noCursor();
366 lcd.clear();
367 }
368 if (in == DOWN)
369 {
370 hex[pos] -= 1;
371 lcd.noCursor();
372 lcd.clear();
373 }
374
375 if (pos == 4)
376 {
377 if (hex[pos] < 0x00)
378 hex[pos] = 0x03;
379 if (hex[pos] > 0x03)
380 hex[pos] = 0x00;
381 }
382 else
383 {
384 if (hex[pos] < 0x00)
385 hex[pos] = 0x0F;
386 if (hex[pos] > 0x0F)
387 hex[pos] = 0x00;
388 }
389
390 // Sets the DAC when select is pressed
391 if (in == SELECT)
392 {
393 set_voltage_hex();
394 lcd.clear();
395 }
396 delay(150);
397 }
398
399 // Sets the DAC with the HEX Code
400 void set_voltage_hex()
401 {
402
403 uint32_t code;
404
405 uint8_t tx[4],rx[4];
406 union
407 {
408 uint8_t byte[4];
409 uint32_t code;
410 } data;
411
412 // Combines the array
413 code += (uint32_t)hex[0];
414 code += ((uint32_t)hex[1])<<4;
415 code += ((uint32_t)hex[2])<<8;
416 code += ((uint32_t)hex[3])<<12;
417 code += ((uint32_t)hex[4])<<16;
418
419 // Load the tx array with the write command and HEX code
420 data.code = code<<6;
421 tx[3] = LTC2756_WRITE_CODE;
422 tx[2] = data.byte[2];
423 tx[1] = data.byte[1];
424 tx[0] = data.byte[0];
425
426 LTC2756_transfer_4bytes(LTC2756_CS, tx, rx);
427
428 // Loads the tx array with the update DAC command
429 tx[3] = LTC2756_UPDATE;
430 tx[2] = 0x00;
431 tx[1] = 0x00;
432 tx[0] = 0x00;
433
434 LTC2756_transfer_4bytes(LTC2756_CS, tx, rx);
435 }
volts
static int8_t volts[5]
Definition: Precision_Voltage_Source.ino:74
D7
const int16_t D7
Definition: Precision_Voltage_Source.ino:60
sign
bool sign
Definition: Precision_Voltage_Source.ino:77
LTC2756_offset
static int32_t LTC2756_offset
Definition: Precision_Voltage_Source.ino:72
LTC2756_BIPOLAR_N5_P5
#define LTC2756_BIPOLAR_N5_P5
Definition: LTC2756.h:160
BUTTON_PIN
const int16_t BUTTON_PIN
Definition: Precision_Voltage_Source.ino:61
Linduino.h
Header File for Linduino Libraries and Demo Code.
LTC2756_WRITE_CODE
#define LTC2756_WRITE_CODE
Definition: LTC2756.h:146
demo_board_connected
static int8_t demo_board_connected
Definition: Precision_Voltage_Source.ino:68
E
const int16_t E
Definition: Precision_Voltage_Source.ino:56
display_hex
static void display_hex()
Definition: Precision_Voltage_Source.ino:318
setup
static void setup()
Definition: Precision_Voltage_Source.ino:82
HEX_DEC
static uint8_t HEX_DEC
Definition: Precision_Voltage_Source.ino:76
data
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
pos
static int16_t pos
Definition: Precision_Voltage_Source.ino:73
LTC2756_UPDATE
#define LTC2756_UPDATE
Definition: LTC2756.h:147
loop
static void loop()
Definition: Precision_Voltage_Source.ino:125
init_dac
static void init_dac()
Definition: Precision_Voltage_Source.ino:155
D6
const int16_t D6
Definition: Precision_Voltage_Source.ino:59
set_voltage_hex
static void set_voltage_hex()
Definition: Precision_Voltage_Source.ino:400
LTC2756_lsb
static float LTC2756_lsb
Definition: Precision_Voltage_Source.ino:71
D4
const int16_t D4
Definition: Precision_Voltage_Source.ino:57
lcd
LiquidCrystal lcd(RS, E, D4, D5, D6, D7)
QuikEval_EEPROM.h
QuikEval EEPROM Library.
input
#define input(pin)
Return the state of pin "pin".
Definition: Linduino.h:79
LTC2756.h
LTC2756: Serial 18-Bit SoftSpan IOUT DAC.
quikeval_SPI_init
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
discover_demo_board
int8_t discover_demo_board(char *demo_name)
Read the ID string from the EEPROM and determine if the correct board is connected.
Definition: QuikEval_EEPROM.cpp:141
UP
const int8_t UP
Definition: Precision_Voltage_Source.ino:62
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
hex
static int8_t hex[5]
Definition: Precision_Voltage_Source.ino:75
LEFT
const int8_t LEFT
Definition: Precision_Voltage_Source.ino:64
set_voltage
static void set_voltage()
Definition: Precision_Voltage_Source.ino:185
LT_I2C.h
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
LTC2756_voltage_to_code
uint32_t LTC2756_voltage_to_code(float dac_voltage, float LTC2756_lsb, int32_t LTC2756_offset)
Converts voltage to code.
Definition: LTC2756.cpp:81
LTC2756_CS
#define LTC2756_CS
Define the CS pin.
Definition: LTC2756.h:138
SELECT
const int8_t SELECT
Definition: Precision_Voltage_Source.ino:66
demo_name
char demo_name[]
Demo Board Name stored in QuikEval EEPROM.
Definition: DC1880A.ino:97
quikeval_SPI_connect
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
UserInterface.h
DOWN
const int8_t DOWN
Definition: Precision_Voltage_Source.ino:63
quikeval_I2C_init
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
D5
const int16_t D5
Definition: Precision_Voltage_Source.ino:58
LTC2756_transfer_4bytes
void LTC2756_transfer_4bytes(uint8_t cs, uint8_t *tx, uint8_t *rx)
Transfers four bytes to the LTC2756.
Definition: LTC2756.cpp:74
voltage
static float voltage
Definition: DC2289AA.ino:71
RS
const int16_t RS
Definition: Precision_Voltage_Source.ino:55
display_decimal
static void display_decimal()
Definition: Precision_Voltage_Source.ino:226
LTC2756_WRITE_SPAN
#define LTC2756_WRITE_SPAN
Definition: LTC2756.h:145
read_switches
static int8_t read_switches()
Definition: Precision_Voltage_Source.ino:136
RIGHT
const int8_t RIGHT
Definition: Precision_Voltage_Source.ino:65