Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC934A.ino
Go to the documentation of this file.
1 /*!
2 Linear Technology DC934 Demonstration Board.
3 LTC2607: 16-Bit, Dual Rail-to-Rail DACs with I2C Interface
4 
5 Linear Technology DC936 Demonstration Board.
6 LTC2609: Quad 16-/14-/12-Bit Rail-to-Rail DACs with I²C Interface.
7 
8 Linear Technology DC812 Demonstration Board.
9 LTC2606: 16-Bit Rail-to-Rail DACs with I²C Interface.
10 
11 @verbatim
12 
13 NOTES
14  Setup:
15  Set the terminal baud rate to 115200 and select the newline terminator.
16  Calibration requires a precision voltmeter.
17  No external power supply is required.
18 
19 USER INPUT DATA FORMAT:
20  decimal : 1024
21  hex : 0x400
22  octal : 02000 (leading 0 "zero")
23  binary : B10000000000
24  float : 1024.0
25 
26 @endverbatim
27 
28 http://www.linear.com/product/LTC2607
29 http://www.linear.com/product/LTC2609
30 http://www.linear.com/product/LTC2606
31 
32 http://www.linear.com/product/LTC2607#demoboards
33 http://www.linear.com/product/LTC2609#demoboards
34 http://www.linear.com/product/LTC2606#demoboards
35 
36 
37 Copyright 2018(c) Analog Devices, Inc.
38 
39 All rights reserved.
40 
41 Redistribution and use in source and binary forms, with or without
42 modification, are permitted provided that the following conditions are met:
43  - Redistributions of source code must retain the above copyright
44  notice, this list of conditions and the following disclaimer.
45  - Redistributions in binary form must reproduce the above copyright
46  notice, this list of conditions and the following disclaimer in
47  the documentation and/or other materials provided with the
48  distribution.
49  - Neither the name of Analog Devices, Inc. nor the names of its
50  contributors may be used to endorse or promote products derived
51  from this software without specific prior written permission.
52  - The use of this software may or may not infringe the patent rights
53  of one or more patent holders. This license does not release you
54  from the requirement that you obtain separate licenses from these
55  patent holders to use this software.
56  - Use of the software either in source or binary form, must be run
57  on or directly connected to an Analog Devices Inc. component.
58 
59 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
60 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
61 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
63 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
64 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
65 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
66 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
67 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
68 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 */
70 
71 /*! @file
72  @ingroup LTC2607
73 */
74 
75 #include <Arduino.h>
76 #include <stdint.h>
77 #include "Linduino.h"
78 #include "UserInterface.h"
79 //#include "LT_I2C.h"
80 #include "LT_SPI.h"
81 #include "LTC2607.h"
82 #include "LTC2422.h"
83 //#include "QuikEval_EEPROM.h"
84 #include <Wire.h>
85 #include <SPI.h>
86 #include "USE_WIRE.h"
87 
88 #ifdef USEWIRE
89 #include "LT_I2C_Wire.h"
90 #include "QuikEval_EEPROM_Wire.h"
91 #else
92 #include "LT_I2C.h"
93 #include "QuikEval_EEPROM.h"
94 #endif
95 
96 // Function Declaration
97 void print_title();
98 void print_prompt(int16_t selected_dac);
99 int16_t prompt_voltage_or_code();
100 uint16_t get_voltage(float LTC2607_lsb, int32_t LTC2607_offset);
101 uint16_t get_code();
102 
103 uint8_t menu_1_select_dac(int16_t *selected_dac);
104 uint8_t menu_2_write_to_input_register(int16_t selected_dac);
105 uint8_t menu_3_write_and_update_dac(int16_t selected_dac);
106 uint8_t menu_4_update_power_up_dac(int16_t selected_dac);
107 uint8_t menu_5_power_down_dac(int16_t selected_dac);
108 uint8_t menu_6_read_adc();
109 uint8_t menu_7_sweep();
110 uint8_t menu_8_calibrate_all();
111 
112 //! Used to keep track to print voltage or print code
113 enum prompt
114 {
115  PROMPT_VOLTAGE = 0, /**< 0 */
116  PROMPT_CODE = 1 /**< 1 */
117 };
118 
119 // Global Constants
120 const uint16_t LTC2422_TIMEOUT= 1000; //!< Configures the maximum timeout (ms) allowed for an LTC2607 read.
121 
122 //! Look-up table for DAC_A, DAC_B, or both command byte option
123 const uint8_t address_map[3] = {LTC2607_DAC_A, LTC2607_DAC_B, LTC2607_ALL_DACS}; //!< Builds the command for dac address
124 
125 const uint16_t MISO_TIMEOUT = 1000; //!< The MISO timout in ms
126 
127 // ***Global Variables***
128 
129 //! The LTC2607 least significant bit value with 5V full-scale.
130 //! Initialized to typical value from datasheet. Can be calibrated through option menu.
131 static float LTC2607_lsb[3] = {LTC2607_TYPICAL_lsb, LTC2607_TYPICAL_lsb, LTC2607_TYPICAL_lsb}; //!< Builds the lsb. Index 2 is used for All DACs
132 
133 //! The LTC2422 least significant bit value with 5V full-scale.
134 //! Initialized to typical value from datasheet. Can be calibrated through option menu.
136 
137 //! The LTC2422 offset variable.
138 //! Initialized to typical value from datasheet. Can be calibrated through option menu.
139 static int32_t LTC2607_offset[3] = {LTC2607_TYPICAL_OFFSET, LTC2607_TYPICAL_OFFSET, LTC2607_TYPICAL_OFFSET}; //!< Builds the offset. Index 2 is used for All DACs
140 
141 static int8_t demo_board_connected; //!< Set to 1 if the board is connected
142 
143 //! Initialize Linduino
144 void setup()
145 // Setup the Program
146 {
147  char demo_name[] = "DC934"; // Demo Board Name stored in QuikEval EEPROM
148 
149  output_high(LTC2422_CS); //! Pulls LTC2442 Chip Select High
150 
151  quikeval_I2C_init(); //! Initializes Linduino I2C port.
152 
153  quikeval_SPI_init(); //! Configures the SPI port for 4MHz SCK
154  quikeval_SPI_connect(); //! Connects SPI to QuikEval port
155 
156  Serial.begin(115200); //! Initializes the serial port to the PC
157  print_title(); //! Displays the title
158 
159  demo_board_connected = discover_demo_board(demo_name); //! Checks if correct demo board is connected.
160 
161  if (demo_board_connected) //! Prints the prompt if the correct demo board is connected
162  {
163  print_prompt(0); // Prints prompt and indicates that "A" is selected.
164  }
165 }
166 
167 //! Repeats Linduino loop
168 void loop()
169 {
170  uint8_t i2c_ack = 0;
171  uint8_t spi_error_code = 0;
172  static int16_t selected_dac = 0; // The selected DAC to be updated (0=A, 1=B, 2=All). Initialized to "A".
173 
174  // The main control loop
175  if (demo_board_connected) //! Does nothing if the demo board is not connected.
176  {
177  if (Serial.available()) //! Checks if user input is available.
178  {
179  int16_t user_command; // User input command
180 
181  user_command = read_int(); //! Reads the user command (if available).
182  Serial.println(user_command);
183  Serial.flush();
184  switch (user_command)
185  {
186  case 1:
187  menu_1_select_dac(&selected_dac); // Select a DAC to update
188  break;
189 
190  case 2:
191  i2c_ack |= menu_2_write_to_input_register(selected_dac); // Write to input register only
192  break;
193 
194  case 3:
195  i2c_ack |= menu_3_write_and_update_dac(selected_dac);
196  break;
197 
198  case 4:
199  i2c_ack |= menu_4_update_power_up_dac(selected_dac); // Update/Power up DAC
200  break;
201 
202  case 5:
203  i2c_ack |= menu_5_power_down_dac(selected_dac); // Power down DAC
204  break;
205 
206  case 6:
207  spi_error_code = menu_6_read_adc();
208  break;
209 
210  case 7:
211  i2c_ack |= menu_7_sweep();
212  spi_error_code |= i2c_ack;
213  break;
214 
215  case 8:
216  i2c_ack |= menu_8_calibrate_all();
217  spi_error_code |= i2c_ack;
218  break;
219 
220  default:
221  Serial.println("Incorrect Option");
222  break;
223  }
224 
225  if (i2c_ack != 0) Serial.println(F("Error: No Acknowledge. Check I2C Address."));
226  if (spi_error_code != 0) Serial.println(F("Error: SPI communication error."));
227 
228  Serial.println();
229  Serial.println(F("*************************"));
230  print_prompt(selected_dac);
231  }
232  }
233 }
234 
235 // Function Definitions
236 
237 //! Prompts user to find out if they want to enter DAC code as a "voltage" or a "code"
238 //! @return PROMPT_CODE or PROMPT_VOLTAGE that indicates whether the user requested for the next entry to be a CODE or VOLTAGE
240 {
241  int16_t user_input;
242  Serial.print(F("Type 1 to enter voltage, 2 to enter code:"));
243  Serial.flush();
244  user_input = read_int();
245  Serial.println(user_input);
246 
247  if (user_input != 2)
248  return(PROMPT_VOLTAGE);
249  else
250  return(PROMPT_CODE);
251 }
252 
253 //! Read desired DAC output voltage from user input.
254 //! @return the code that can be written to the LTC2607 DAC
255 uint16_t get_voltage(float LTC2607_lsb, //!< lsb weight of the LTC2607 (possibly calibrated)
256  int32_t LTC2607_offset) //!< offset of LTC2607 (possibly calibrated)
257 {
258  float dac_voltage;
259 
260  Serial.print(F("Enter Desired DAC output voltage: ")); //! Prompt user to enter a voltage
261  dac_voltage = read_float(); //! Read a float from the serial terminal
262  Serial.print(dac_voltage);
263  Serial.println(F(" V"));
264  Serial.flush();
265  return(LTC2607_voltage_to_code(dac_voltage, LTC2607_lsb, LTC2607_offset)); //! Return the DAC code that results in that voltage.
266 }
267 
268 //! @todo Review this file.
269 //! Reads desired DAC code from user input.
270 //! @return the adc CODE entered by the user. (Note, this is a CODE not a VOLTAGE.)
271 uint16_t get_code()
272 {
273  uint16_t returncode;
274  Serial.println(F("Enter Desired DAC Code"));
275  Serial.print(F("(Format 32768, 0x8000, 0100000, or B1000000000000000): "));
276  returncode = (uint16_t) read_int();
277  Serial.print(F("0x"));
278  Serial.println(returncode, HEX);
279  Serial.flush();
280  return(returncode);
281 }
282 
283 //! Prints the title block
285 {
286  Serial.println(F("*****************************************************************"));
287  Serial.println(F("* DC934A Demonstration Program *"));
288  Serial.println(F("* *"));
289  Serial.println(F("* This program demonstrates communication with the LTC2607 *"));
290  Serial.println(F("* 16-Bit Dual Rail-to-Rail DAC with I2C Interface. This board *"));
291  Serial.println(F("* also features an LTC2422 2-Channel 20-Bit uPower No Latency *"));
292  Serial.println(F("* Delta Sigma ADC for readback. *"));
293  Serial.println(F("* *"));
294  Serial.println(F("* Set the baud rate to 115200 select the newline terminator. *"));
295  Serial.println(F("*****************************************************************"));
296 }
297 
298 //! Prints the main menu, and prompts the user for an input command
299 void print_prompt(int16_t selected_dac) //!< this parameter is passed so that it can be printed at the bottom of the menu.
300 {
301  Serial.println(F("\nCommand Summary:"));
302 
303  Serial.println(F(" 1-Select DAC"));
304  Serial.println(F(" 2-Write to input register (no update)"));
305  Serial.println(F(" 3-Write and update DAC"));
306  Serial.println(F(" 4-Update/Power up DAC"));
307  Serial.println(F(" 5-Power Down DAC"));
308  Serial.println(F(" 6-Read ADC"));
309  Serial.println(F(" 7-Sweep"));
310  Serial.println(F(" 8-Calibrate ALL"));
311  Serial.println();
312  Serial.print(F(" Selected DAC: "));
313  if (selected_dac != 2)
314  Serial.println((char) (selected_dac + 0x41));
315  else
316  Serial.println(F("All"));
317  Serial.println();
318  Serial.print(F("Enter a command:"));
319 }
320 
321 //! Menu 1: Select DAC to update.
322 //! Prompts user for DAC A, DAC B, or both. This is only a user menu. This function does not communicate with the LTC2607.
323 //! @return always returns 0. Fail return code is not implemented.
324 uint8_t menu_1_select_dac(int16_t *selected_dac) //!< Overwritten with 0, 1, or 2 to indicate whether the user wants commands to act upon DAC A, DAC B, or both DACs respectively.
325 {
326  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
327  Serial.print(F("Select DAC to be updated (0=A, 1=B, 2=All)"));
328  *selected_dac = read_int();
329  if (*selected_dac > 2) *selected_dac=2; // If user enters and invalid option, default to ALL.
330  if (*selected_dac == 2)
331  Serial.println(F("All"));
332  else
333  Serial.println(*selected_dac);
334  return(0); // Always returns success, consider adding a fail code later.
335 }
336 
337 //! Menu 2: Write to input register only. Does not update the output voltage.
338 //! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
339 uint8_t menu_2_write_to_input_register(int16_t selected_dac) //!< DAC to be updated. 0=A, 1=B, 2=All
340 {
341  uint16_t dac_code;
342  uint8_t ack = 0;
343  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
344 
345  //! Read voltage or DAC code from user
347  dac_code = get_voltage(LTC2607_lsb[selected_dac], LTC2607_offset[selected_dac]);
348  else
349  dac_code = get_code();
350 
351  //! Write a code to the LTC2607 internal register. Output voltage is not updated by the "write" command.
353  return(ack);
354 }
355 
356 //! Menu 3: Write to input register and update output voltage.
357 //! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
358 uint8_t menu_3_write_and_update_dac(int16_t selected_dac) //!< DAC to be updated. 0=A, 1=B, 2=All
359 {
360  uint8_t ack;
361  uint16_t dac_code;
362  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
363 
364  //! Read voltage or DAC code from user
366  dac_code = get_voltage(LTC2607_lsb[selected_dac], LTC2607_offset[selected_dac]);
367  else
368  dac_code = get_code();
369 
370  //! Write a code to the LTC2607 internal register and update the output voltage.
371  ack = LTC2607_write(LTC2607_I2C_GLOBAL_ADDRESS, LTC2607_WRITE_UPDATE_COMMAND, address_map[selected_dac], dac_code); // Write a code to the LTC2607
372  return(ack);
373 }
374 
375 //! Menu 4: Update/Power Up DAC
376 //! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
377 uint8_t menu_4_update_power_up_dac(int16_t selected_dac) //!< DAC to be updated. 0=A, 1=B, 2=All
378 {
379  uint8_t ack;
380 
381  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
382  ack = LTC2607_write(LTC2607_I2C_GLOBAL_ADDRESS, LTC2607_UPDATE_COMMAND, address_map[selected_dac], 0); //! Update output voltage from internal register. Data is ignored.
383  return(ack);
384 }
385 
386 //! Menu 5: Power Down DAC
387 //! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
388 uint8_t menu_5_power_down_dac(int16_t selected_dac)
389 {
390  uint8_t ack;
391  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
392  ack = LTC2607_write(LTC2607_I2C_GLOBAL_ADDRESS, LTC2607_POWER_DOWN_COMMAND, address_map[selected_dac], 0); //! Power down selected DAC. Data is ignored.
393  return(ack);
394 }
395 
396 //! Menu 6: Read voltage from the ADC
397 //! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
399 {
400  float adc_voltage;
401  int32_t adc_code;
402  uint8_t adc_channel;
403  uint32_t adc_code_array[2]; // Array for ADC data. Useful because you don't know which channel until the LTC2422 tells you.
404  uint8_t acknowledge;
405 
406  // Read ADC
407  quikeval_SPI_connect(); //! Connect SPI to QuikEval connector
408 
409  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code); //! Throw out the stale data
410 
411  if (acknowledge = LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
412  return(1);
413  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code); //! Read both channels from the ADC. The ADC channel will toggle with each reading.
414  adc_code_array[adc_channel] = adc_code; //! Note that we're not sure which channel is first prior to reading.
415 
416  if (acknowledge = LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
417  return(1);
418  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code); //! Therefore, we use adc_channel (reported by LTC2422 during read operation) as index into two element array.
419  adc_code_array[adc_channel] = adc_code; //! One element holds channel A ADC code and the other holds the channel B ADC code.
420 
421  //! Print ADC A voltage.
422  Serial.println();
423  Serial.print(F(" ADC A : Code: 0x"));
424  Serial.println(adc_code_array[1], HEX);
425  Serial.print(F(" Voltage: "));
426  adc_voltage = LTC2422_code_to_voltage(adc_code_array[1], LTC2422_lsb);
427  Serial.println(adc_voltage, 6);
428 
429  //! Print ADC B voltage.
430  Serial.println();
431  Serial.print(F(" ADC B : Code: 0x"));
432  Serial.println(adc_code_array[0], HEX);
433  Serial.print(F(" Voltage: "));
434  adc_voltage = LTC2422_code_to_voltage(adc_code_array[0], LTC2422_lsb);
435  Serial.println(adc_voltage, 6);
436  return(0);
437 }
438 
439 //! Menu 7: Voltage Sweep
440 //! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
441 uint8_t menu_7_sweep()
442 {
443  uint8_t ack = 0;
444  Serial.print(F("Enter the desired number of sample points: "));
445 
446  //! Reads number of sample points from user.
447  uint16_t sample;
448  sample = read_int();
449  if (sample == 0)
450  sample = 1;
451  Serial.println(sample);
452  if (sample > 65535)
453  sample = 65535;
454 
455  //! Calculates size of each step.
456  uint16_t sample_code;
457  sample_code = 65535/sample;
458 
459  int32_t adc_code;
460  uint8_t adc_channel;
461  quikeval_SPI_connect(); //! Connect SPI to QuikEval connector
462 
463  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
464  return(1);
465  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code); //! Take one ADC reading. Throw away the data, but check the channel.
466  //! If the data was from channel 1, take another reading so that the next reading will be channel 0.
467  if (adc_channel == 1)
468  {
469  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
470  return(1);
471  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code); // IF we just read channel 1 (DAC A),
472  // a conversion on channel B has just started. We want the FIRST reading in the table to be DAC A, so flush
473  // this conversion, starting another conversion on DAC A. The Autozero phase takes 4/60 of a second (66.7ms) so there
474  // is some time to print the header and set the DAC outputs.
475  }
476  Serial.println(F("Code, DAC A,DAC B"));
477 
478  float adc_voltage;
479  uint16_t dac_code;
480  uint16_t i;
481  //! For loop steps one voltage step at a time.
482  for (i = 0; i <= sample; i++)
483  {
484  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
485  dac_code = (sample_code*i);
486  if (dac_code > 65535)
487  dac_code = 65535;
488 
489  //! Write DAC code to both channels.
491 
492  quikeval_SPI_connect(); //! Connect SPI to QuikEval connector
493 
494  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
495  return(1);
496  //! Read ADC channel 0 (DAC A) voltage and print it.
497  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code);
498 
499  Serial.print(dac_code);
500  Serial.print(F(","));
501  adc_voltage = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
502  Serial.print(adc_voltage, 6);
503  Serial.print(F(","));
504 
505  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
506  return(1);
507  //! Read ADC channel 1 (DAC B) voltage and print it.
508  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code);
509  adc_voltage = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
510  Serial.println(adc_voltage, 6);
511  Serial.flush();
512 
513  //! If they get out of sync, print "Out of sync!". This only happens if something bad occurs.
514  if (adc_channel == 1)
515  {
516  Serial.println(F("Out of sync!!"));
519  return(1);
520  }
521  }
524  Serial.println();
525  Serial.println(F("Copy and save data points to a .csv file"));
526  Serial.println(F("and open in Excel to plot points."));
527  return(ack);
528 }
529 
530 //! Menu 8: Calibrate All
531 //! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
533 {
534  uint8_t ack = 0;
535  float voltage1[2]; // Calibration voltage 1
536  float voltage2[2]; // Calibration voltage 2
537  const uint16_t CAL_LOW_DAC_CODE = 0x00FF; // LTC2607 calibration code used for low-side force/measure.
538  const uint16_t CAL_HIGH_DAC_CODE = 0xFF00; // LTC2607 calibration code used for high-side force/measure.
539 
540  // Calibrate All
541  Serial.println(F("Measure and Enter Reference "));
542  Serial.print(F("Voltage for The ADC: "));
543 
544  float ref_voltage;
545  ref_voltage = read_float();
546  Serial.println(ref_voltage, 6);
547  LTC2422_calculate_lsb(ref_voltage, &LTC2422_lsb);
548 
549  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
550 
553  Serial.println();
554  Serial.print(F("Calibrating DACs ... "));
555  delay(2000);
556 
557  quikeval_SPI_connect(); //! Connect SPI to QuikEval connector
558 
559  delay(50);
560 
561  int32_t adc_code;
562  uint8_t adc_channel;
563  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
564  return(1);
565  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code); // Throw away last reading
566  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
567  return(1);
568  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code);
569  if (adc_channel == 0)
570  voltage1[1] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
571  if (adc_channel == 1)
572  voltage1[0] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
573  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
574  return(1);
575  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code);
576  if (adc_channel == 0)
577  voltage1[1] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
578  if (adc_channel == 1)
579  voltage1[0] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
580 
581  quikeval_I2C_connect(); //! Connects I2C port to the QuikEval connector
582 
583  ack |= LTC2607_write(LTC2607_I2C_GLOBAL_ADDRESS, LTC2607_WRITE_UPDATE_COMMAND, LTC2607_DAC_A, CAL_HIGH_DAC_CODE); // Set DAC to Full Scale
584  ack |= LTC2607_write(LTC2607_I2C_GLOBAL_ADDRESS, LTC2607_WRITE_UPDATE_COMMAND, LTC2607_DAC_B, CAL_HIGH_DAC_CODE); // Set DAC to Full Scale
585 
586  delay(2000);
587  quikeval_SPI_connect(); //! Connect SPI to QuikEval connector
588 
589  delay(50);
590 
591  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
592  return(1);
593  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code); // Throw away last reading
594  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
595  return(1);
596  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code);
597  if (adc_channel == 0)
598  voltage2[1] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
599  if (adc_channel == 1)
600  voltage2[0] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
601  if (LTC2422_EOC_timeout(LTC2422_CS, MISO_TIMEOUT)) // Check for EOC
602  return(1);
603  LTC2422_adc_read(LTC2422_CS, &adc_channel, &adc_code);
604  if (adc_channel == 0)
605  voltage2[1] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
606  if (adc_channel == 1)
607  voltage2[0] = LTC2422_code_to_voltage(adc_code, LTC2422_lsb);
608 
609  LTC2607_calibrate(CAL_LOW_DAC_CODE, CAL_HIGH_DAC_CODE, voltage1[0], voltage2[0], &LTC2607_lsb[0], &LTC2607_offset[0]);
610  LTC2607_calibrate(CAL_LOW_DAC_CODE, CAL_HIGH_DAC_CODE, voltage1[1], voltage2[1], &LTC2607_lsb[1], &LTC2607_offset[1]);
611  // Store All DACs lsb and offset from LTC2607_lsb[0] and LTC2607_offset[0]
612  LTC2607_lsb[2] = LTC2607_lsb[0];
614  Serial.println(F("Calibration Complete"));
615 
616  Serial.print(F("lsb DAC A: "));
617  Serial.print(LTC2607_lsb[0], 6);
618  Serial.print(F(" V offset: "));
619  Serial.println(LTC2607_offset[0]);
620 
621  Serial.print(F("lsb DAC B: "));
622  Serial.print(LTC2607_lsb[1], 6);
623  Serial.print(F(" V offset: "));
624  Serial.println(LTC2607_offset[1]);
625 
626  Serial.print(F("All DACs: "));
627  Serial.print(LTC2607_lsb[2], 6);
628  Serial.print(F(" V offset: "));
629  Serial.println(LTC2607_offset[2]);
630  return(ack);
631 }
static int32_t LTC2607_offset[3]
The LTC2422 offset variable.
Definition: DC934A.ino:139
LTC2422: 1-/2-Channel 20-Bit uPower No Latency Delta-Sigma ADC in MSOP-10.
#define LTC2607_WRITE_COMMAND
Command to write to internal register of LTC2607, but not update output voltage yet.
Definition: LTC2607.h:151
unsigned char user_command
static void loop()
Repeats Linduino loop.
Definition: DC934A.ino:168
const uint16_t MISO_TIMEOUT
The MISO timout in ms.
Definition: DC934A.ino:125
QuikEval EEPROM Library.
float LTC2422_code_to_voltage(int32_t adc_code, float LTC2422_lsb)
Calculates the voltage given the ADC code and lsb weight.
Definition: LTC2422.cpp:119
uint16_t LTC2607_voltage_to_code(float dac_voltage, float LTC2607_lsb, int32_t LTC2607_offset)
Calculates an LTC2607 DAC code for the desired output voltage.
Definition: LTC2607.cpp:110
const float LTC2422_TYPICAL_lsb
The LTC2422 typical least significant bit value with 5V full-scale.
Definition: LTC2422.h:107
void LTC2607_calibrate(uint16_t dac_code1, uint16_t dac_code2, float voltage1, float voltage2, float *LTC2607_lsb, int32_t *LTC2607_offset)
Calculates the LTC2607 offset and lsb voltage given two measured voltages and their corresponding DAC...
Definition: LTC2607.cpp:127
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
const float LTC2607_TYPICAL_OFFSET
The LTC2607 typical offset voltage.
Definition: LTC2607.h:168
static float LTC2607_lsb[3]
The LTC2607 least significant bit value with 5V full-scale.
Definition: DC934A.ino:131
static void setup()
Initialize Linduino.
Definition: DC934A.ino:144
Header File for Linduino Libraries and Demo Code.
static int8_t demo_board_connected
Set to 1 if the board is connected.
Definition: DC934A.ino:141
const uint16_t LTC2422_TIMEOUT
Configures the maximum timeout (ms) allowed for an LTC2607 read.
Definition: DC934A.ino:120
const float LTC2607_TYPICAL_lsb
The LTC2607 typical least significant bit value with 5V full-scale.
Definition: LTC2607.h:167
#define LTC2607_ALL_DACS
Command (and DAC code) will modify both DAC A and DAC B.
Definition: LTC2607.h:163
static uint8_t menu_3_write_and_update_dac(int16_t selected_dac)
Menu 3: Write to input register and update output voltage.
Definition: DC934A.ino:358
static void print_title()
Prints the title block.
Definition: DC934A.ino:284
static uint8_t menu_2_write_to_input_register(int16_t selected_dac)
Menu 2: Write to input register only.
Definition: DC934A.ino:339
void LTC2422_adc_read(uint8_t cs, uint8_t *adc_channel, int32_t *code)
Read ADC code from the LTC2422.
Definition: LTC2422.cpp:98
#define LTC2607_WRITE_UPDATE_COMMAND
Command to write and update (and power up) the LTC2607.
Definition: LTC2607.h:153
static float adc_voltage
Definition: DC2071AA.ino:115
static uint16_t get_code()
Definition: DC934A.ino:271
static uint8_t menu_7_sweep()
Menu 7: Voltage Sweep.
Definition: DC934A.ino:441
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
static uint8_t menu_8_calibrate_all()
Menu 8: Calibrate All.
Definition: DC934A.ino:532
static uint8_t menu_5_power_down_dac(int16_t selected_dac)
Menu 5: Power Down DAC.
Definition: DC934A.ino:388
QuikEval EEPROM Library.
#define LTC2607_UPDATE_COMMAND
Command to update (and power up) LTC2607.
Definition: LTC2607.h:152
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.
static void print_prompt(int16_t selected_dac)
Prints the main menu, and prompts the user for an input command.
Definition: DC934A.ino:299
const uint8_t address_map[3]
Look-up table for DAC_A, DAC_B, or both command byte option.
Definition: DC934A.ino:123
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
static int16_t prompt_voltage_or_code()
Prompts user to find out if they want to enter DAC code as a "voltage" or a "code".
Definition: DC934A.ino:239
#define LTC2607_POWER_DOWN_COMMAND
Command to power down the LTC2607.
Definition: LTC2607.h:154
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
#define LTC2607_DAC_B
Command (and DAC code) will modify DAC B.
Definition: LTC2607.h:162
static uint8_t menu_6_read_adc()
Menu 6: Read voltage from the ADC.
Definition: DC934A.ino:398
void LTC2422_calculate_lsb(float LTC2422_reference_voltage, float *LTC2422_lsb)
Calculates the lsb weight from the given reference voltage.
Definition: LTC2422.cpp:128
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
int32_t read_int()
float read_float()
#define LTC2607_I2C_GLOBAL_ADDRESS
LTC2607 Global I2C Address.
Definition: LTC2607.h:145
prompt
Used to keep track to print voltage or print code.
Definition: DC934A.ino:113
#define LTC2422_CS
Define the SPI CS pin.
Definition: LTC2422.h:104
long sample
static uint8_t menu_1_select_dac(int16_t *selected_dac)
Menu 1: Select DAC to update.
Definition: DC934A.ino:324
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
void quikeval_I2C_connect(void)
Switch MUX to connect I2C pins to QuikEval connector.
Definition: LT_I2C.cpp:401
LTC2607: 16-Bit, Dual Rail-to-Rail DACs with I2C Interface.
static int i
Definition: DC2430A.ino:184
int8_t LTC2607_write(uint8_t i2c_address, uint8_t dac_command, uint8_t dac_address, uint16_t dac_code)
Writes command, DAC address, and DAC code to the LTC2607.
Definition: LTC2607.cpp:100
#define LTC2607_DAC_A
Command (and DAC code) will modify DAC A.
Definition: LTC2607.h:161
static float LTC2422_lsb
The LTC2422 least significant bit value with 5V full-scale.
Definition: DC934A.ino:135
uint8_t LTC2422_EOC_timeout(uint8_t cs, uint16_t miso_timeout)
Checks for EOC with a specified timeout.
Definition: LTC2422.cpp:76
static uint32_t adc_code
Definition: DC2071AA.ino:113
static uint16_t get_voltage(float LTC2607_lsb, int32_t LTC2607_offset)
Read desired DAC output voltage from user input.
Definition: DC934A.ino:255
static uint8_t menu_4_update_power_up_dac(int16_t selected_dac)
Menu 4: Update/Power Up DAC.
Definition: DC934A.ino:377