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
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 
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 
174 
175  // Update DAC
176  tx[3] = LTC2756_UPDATE;
177  tx[2] = 0x00;
178  tx[1] = 0x00;
179  tx[0] = 0x00;
180 
182 }
183 
184 // Converts decimal to 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;
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 
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 
225 }
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 }
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
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 
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 
435 }
static int8_t volts[5]
const int16_t D7
static int32_t LTC2756_offset
#define LTC2756_BIPOLAR_N5_P5
Definition: LTC2756.h:160
const int16_t BUTTON_PIN
Header File for Linduino Libraries and Demo Code.
#define LTC2756_WRITE_CODE
Definition: LTC2756.h:146
static int8_t demo_board_connected
const int16_t E
static void display_hex()
static void setup()
static uint8_t HEX_DEC
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
static int16_t pos
#define LTC2756_UPDATE
Definition: LTC2756.h:147
static void loop()
static void init_dac()
const int16_t D6
static void set_voltage_hex()
static float LTC2756_lsb
const int16_t D4
LiquidCrystal lcd(RS, E, D4, D5, D6, D7)
QuikEval EEPROM Library.
#define input(pin)
Return the state of pin "pin".
Definition: Linduino.h:79
LTC2756: Serial 18-Bit SoftSpan IOUT DAC.
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
int8_t discover_demo_board(char *demo_name)
Read the ID string from the EEPROM and determine if the correct board is connected.
const int8_t UP
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
static int8_t hex[5]
const int8_t LEFT
static void set_voltage()
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
uint32_t LTC2756_voltage_to_code(float dac_voltage, float LTC2756_lsb, int32_t LTC2756_offset)
Converts voltage to code.
Definition: LTC2756.cpp:81
#define LTC2756_CS
Define the CS pin.
Definition: LTC2756.h:138
const int8_t SELECT
char demo_name[]
Demo Board Name stored in QuikEval EEPROM.
Definition: DC1880A.ino:97
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
const int8_t DOWN
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
const int16_t D5
void LTC2756_transfer_4bytes(uint8_t cs, uint8_t *tx, uint8_t *rx)
Transfers four bytes to the LTC2756.
Definition: LTC2756.cpp:74
static float voltage
Definition: DC2289AA.ino:71
const int16_t RS
static void display_decimal()
#define LTC2756_WRITE_SPAN
Definition: LTC2756.h:145
static int8_t read_switches()
const int8_t RIGHT