Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC1009AA.ino
Go to the documentation of this file.
1 /*!
2 Linear Technology DC1009A-A Demonstration Board.
3 LTC2492: 24-Bit, 4-Channel Delta Sigma ADC with SPI interface
4 
5 @verbatim
6 
7 NOTES
8  Setup:
9  Set the terminal baud rate to 115200 and select the newline terminator. Equipment
10  required is a precision voltage source and a precision voltmeter. Ensure the COM
11  and REF- pins are connected to ground. The REF+ pin should be connected to +5V.
12 
13  How to test Single-Ended mode:
14  The voltage source should be connected to the ADC such that the negative lead is
15  connected to the COM(common) pin. The positive lead may be connected to any
16  channel input. Ensure voltage is within analog input voltage range -0.3 to 2.5V.
17 
18  How to test Differential Mode:
19  The voltage source should be connected with positive and negative leads to paired
20  channels. The voltage source negative output must also be connected to the COM
21  pin in order to provide a ground-referenced voltage. Ensure voltage is within
22  analog input voltage range -0.3V to +2.5V. Swapping input voltages results in a
23  reversed polarity reading.
24 
25 USER INPUT DATA FORMAT:
26  decimal : 1024
27  hex : 0x400
28  octal : 02000 (leading 0 "zero")
29  binary : B10000000000
30  float : 1024.0
31 
32 @endverbatim
33 
34 http://www.linear.com/product/LTC2492
35 
36 http://www.linear.com/product/LTC2492#demoboards
37 
38 
39 Copyright 2018(c) Analog Devices, Inc.
40 
41 All rights reserved.
42 
43 Redistribution and use in source and binary forms, with or without
44 modification, are permitted provided that the following conditions are met:
45  - Redistributions of source code must retain the above copyright
46  notice, this list of conditions and the following disclaimer.
47  - Redistributions in binary form must reproduce the above copyright
48  notice, this list of conditions and the following disclaimer in
49  the documentation and/or other materials provided with the
50  distribution.
51  - Neither the name of Analog Devices, Inc. nor the names of its
52  contributors may be used to endorse or promote products derived
53  from this software without specific prior written permission.
54  - The use of this software may or may not infringe the patent rights
55  of one or more patent holders. This license does not release you
56  from the requirement that you obtain separate licenses from these
57  patent holders to use this software.
58  - Use of the software either in source or binary form, must be run
59  on or directly connected to an Analog Devices Inc. component.
60 
61 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
62 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
63 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
64 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
65 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
66 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
67 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
68 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
69 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
70 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71 
72  */
73 
74 /*! @file
75  @ingroup LTC2492
76 */
77 
78 #include <Arduino.h>
79 #include <stdint.h>
80 #include "Linduino.h"
81 #include "LT_SPI.h"
82 #include <SPI.h>
83 #include "UserInterface.h"
84 #include "LT_I2C.h"
85 #include "QuikEval_EEPROM.h"
86 #include "LTC24XX_general.h"
87 #include "LTC2492.h"
88 
89 // Function Declaration
90 void print_title(); // Print the title block
91 void print_prompt(); // Prompt the user for an input command
92 void print_user_command(uint8_t menu); // Display selected differential channels
93 
94 uint8_t menu_1_read_single_ended();
95 uint8_t menu_2_read_differential();
96 void menu_3_set_1X2X();
97 
98 // Global variables
99 static uint8_t demo_board_connected; //!< Set to 1 if the board is connected
100 static uint8_t two_x_mode = LTC2492_SPEED_1X; //!< The LTC2492 2X Mode settings
101 static uint8_t rejection_mode = LTC2492_R50_R60; //!< The LTC2492 rejection mode settings
102 static float LTC2492_vref = 5.0; //!< The LTC2492 ideal reference voltage
103 static uint16_t eoc_timeout = 350; //!< timeout in ms
104 // Constants
105 
106 //! Lookup table to build the command for single-ended mode
108  }; //!< Builds the command for single-ended mode
109 
110 //! Lookup table to build the command for differential mode
112  }; //!< Build the command for differential mode
113 
114 //! Lookup table to build 1X / 2X bits
115 const uint8_t BUILD_1X_2X_COMMAND[2] = {LTC2492_SPEED_1X, LTC2492_SPEED_2X}; //!< Build the command for 1x or 2x mode
116 
117 //! Lookup table to build 1X / 2X bits
118 const uint8_t BUILD_FREQ_REJ_COMMAND[3] = {LTC2492_R50, LTC2492_R60, LTC2492_R50_R60}; //!< Build the command for 1x or 2x mode
119 
120 //! Initialize Linduino
121 void setup()
122 {
123  char demo_name[]="DC1009"; // Demo Board Name stored in QuikEval EEPROM
124  quikeval_SPI_init(); // Configure the spi port for 4MHz SCK
125  quikeval_SPI_connect(); // Connect SPI to main data port
126  quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz
127  Serial.begin(115200); // Initialize the serial port to the PC
128  print_title();
129 
132  {
133  print_prompt();
134  }
135  else
136  {
137  Serial.println(F("EEPROM not detected, will attempt to proceed"));
139  print_prompt();
140  }
141  quikeval_SPI_connect(); //Initialize for SPI
142 }
143 
144 //! Repeats Linduino loop
145 void loop()
146 {
147  int16_t user_command; // The user input command
148  uint8_t ack_EOC = 0; // Keeps track of the EOC timeout
150  {
151  if (Serial.available()) // Check for user input
152  {
153  user_command = read_int(); // Read the user command
154  if (user_command != 'm')
155  Serial.println(user_command); // Prints the user command to com port
156  Serial.flush();
157  switch (user_command)
158  {
159  case 1:
160  ack_EOC |= menu_1_read_single_ended();
161  break;
162  case 2:
163  ack_EOC |= menu_2_read_differential();
164  break;
165  case 3:
166  menu_3_set_1X2X();
167  break;
168  case 4:
170  break;
171  default:
172  Serial.println(F("Incorrect Option"));
173  }
174  if (ack_EOC)
175  Serial.println(F("\n******SPI ERROR******\n"));
176  Serial.print(F("\n*************************\n"));
177  print_prompt();
178  }
179  }
180 }
181 
182 // Function Definitions
183 
184 //! Prints the title block when program first starts.
186 {
187  Serial.print(F("\n*****************************************************************\n"));
188  Serial.print(F("* DC1009A-A Demonstration Program *\n"));
189  Serial.print(F("* *\n"));
190  Serial.print(F("* This program demonstrates how to send data and receive data *\n"));
191  Serial.print(F("* from the 24-bit ADC. *\n"));
192  Serial.print(F("* *\n"));
193  Serial.print(F("* *\n"));
194  Serial.print(F("* Set the baud rate to 115200 and select the newline terminator.*\n"));
195  Serial.print(F("* *\n"));
196  Serial.print(F("*****************************************************************\n"));
197 }
198 
199 //! Prints main menu.
201 {
202  Serial.print(F("\n1-Read Single-Ended\n"));
203  Serial.print(F("2-Read Differential\n"));
204  Serial.print(F("3-2X Mode Settings\n"));
205  Serial.print(F("4-Frequency Rejection Settings\n"));
206  Serial.print(F("Enter a Command: "));
207 }
208 
209 //! Display selected differential channels. Displaying single-ended channels is
210 //! straightforward; not so with differential because the inputs can take either polarity.
211 void print_user_command(uint8_t menu)
212 {
213  switch (menu)
214  {
215  case 0:
216  Serial.print(F("0P-1N"));
217  break;
218  case 1:
219  Serial.print(F("2P-3N"));
220  break;
221  case 2:
222  Serial.print(F("1P-0N"));
223  break;
224  case 3:
225  Serial.print(F("3P-2N"));
226  break;
227  }
228  Serial.print(F(": "));
229 }
230 
231 //! Read channels in single-ended mode
232 //! @return Returns 0=successful, 1=unsuccessful (exceeded timeout)
234 {
235  uint8_t adc_command_high; // The LTC2492 command high byte
236  uint8_t adc_command_low; // The LTC2492 command low byte
237  int16_t user_command; // The user input command
238  int32_t adc_code = 0; // The LTC2492 code
239  float adc_voltage = 0; // The LTC2492 voltage
240 
241  while (1)
242  {
243  Serial.print(F("*************************\n\n"));
244  Serial.print(F("0-CH0\n"));
245  Serial.print(F("1-CH1\n"));
246  Serial.print(F("2-CH2\n"));
247  Serial.print(F("3-CH3\n"));
248  Serial.print(F("4-ALL\n"));
249  Serial.print(F("m-Main Menu\n"));
250  Serial.print(F("Enter a Command: "));
251 
252  user_command = read_int(); // Read the single command
253  if (user_command == 'm')
254  break;
255  Serial.println(user_command);
256  if (user_command == 4)
257  {
258  Serial.print(F("ALL\n"));
259  adc_command_high = BUILD_COMMAND_SINGLE_ENDED[0]; // Build ADC command for channel 0
260  adc_command_low = rejection_mode | two_x_mode;
261  if (LTC2492_EOC_timeout(LTC2492_CS, eoc_timeout)) // Checks for EOC with a timeout
262  return 1;
263  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Throws out last reading
264 
265  for (int8_t x = 0; x <= 3; x++) // Read all channels in single-ended mode
266  {
267  if (two_x_mode)
268  {
270  return 1;
271  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Throws out an extra reading in 2x mode
272  }
273  adc_command_high = BUILD_COMMAND_SINGLE_ENDED[(x + 1) % 4];
275  return 1;
276  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code);
277  adc_voltage = LTC2492_code_to_voltage(adc_code, LTC2492_vref);
278 
279  Serial.print(F(" ****"));
280  Serial.print(F("CH"));
281  Serial.print(x);
282  Serial.print(F(": "));
283  Serial.print(adc_voltage, 4);
284  Serial.print(F("V\n\n"));
285  }
286  }
287  else
288  {
289  adc_command_high = BUILD_COMMAND_SINGLE_ENDED[user_command]; // Build ADC command
290  adc_command_low = rejection_mode | two_x_mode;
291  Serial.print(F("ADC Command: 0x"));
292  Serial.println((adc_command_high<<8) | adc_command_low, HEX);
293  if (LTC2492_EOC_timeout(LTC2492_CS, eoc_timeout)) // Checks for EOC with a timeout
294  return 1;
295  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Throws out last reading
296  if (two_x_mode)
297  {
299  return 1;
300  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Throws out an extra reading in 2x mode
301  }
303  return 1;
304  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Now we're ready to read the desired data
305 
306  Serial.print(F("Received Code: 0x"));
307  Serial.println(adc_code, HEX);
308  adc_voltage = LTC2492_code_to_voltage(adc_code, LTC2492_vref);
309  Serial.print(F(" ****"));
310  Serial.print(F("CH"));
311  Serial.print(user_command);
312  Serial.print(F(": "));
313  Serial.print(adc_voltage, 4);
314  Serial.print(F("V\n\n"));
315  }
316  }
317  return 0;
318 }
319 
320 //! Read channels in differential mode
321 //! @return Returns 0=successful, 1=unsuccessful (exceeded timeout)
323 {
324  int8_t y; // Offset into differential channel array to select polarity
325  uint8_t adc_command_high; // The LTC2492 command high byte
326  uint8_t adc_command_low; // The LTC2492 command low byte
327  int16_t user_command; // The user input command
328  int32_t adc_code = 0; // The LTC2492 code
329  float adc_voltage; // The LTC2492 voltage
330 
331  while (1)
332  {
333  Serial.print(F("\n*************************\n\n")); // Display differential menu
334  Serial.print(F("0-0P-1N\n"));
335  Serial.print(F("1-2P-3N\n"));
336  Serial.print(F("2-1P-0N\n"));
337  Serial.print(F("3-3P-2N\n"));
338  Serial.print(F("m-Main Menu\n"));
339 
340  user_command = read_int(); // Read the single command
341  if (user_command == 'm')
342  break;
343  Serial.println(user_command);
344 
345  // Reads and displays a selected channel
346  adc_command_high = BUILD_COMMAND_DIFF[user_command];
347  adc_command_low = rejection_mode | two_x_mode;
348  Serial.print(F("ADC Command: 0x"));
349  Serial.println((adc_command_high<<8) | adc_command_low, HEX);
350 
352  return 1;
353  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Throws out last reading
354  if (two_x_mode)
355  {
357  return 1;
358  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Throws out an extra reading in 2x mode
359  }
361  return 1;
362  LTC2492_read(LTC2492_CS, adc_command_high, adc_command_low, &adc_code); // Now we're ready to read the desired data
363 
364  Serial.print(F("Received Code: 0x"));
365  Serial.println(adc_code, HEX);
366  adc_voltage = LTC2492_code_to_voltage(adc_code, LTC2492_vref);
367  Serial.print(F("\n ****"));
368  print_user_command(user_command);
369  Serial.print(adc_voltage, 4);
370  Serial.print(F("V\n"));
371  }
372  return 0;
373 }
374 
375 //! Set 1X or 2X mode
377 {
378  int16_t user_command; // The user input command
379 
380  // 2X Mode
381  Serial.print(F("2X Mode Settings\n\n"));
382  Serial.print(F("0-Disable\n"));
383  Serial.print(F("1-Enable\n"));
384  Serial.print(F("Enter a Command: "));
385  user_command = read_int();
386  Serial.println(user_command);
387 
388  if (user_command == 0)
389  {
391  Serial.print(F("2X Mode Disabled\n"));
392  }
393  else
394  {
396  Serial.print(F("2X Mode Enabled\n"));
397  }
398 }
399 
400 
401 //! Set 1X or 2X mode
403 {
404  int16_t user_command; // The user input command
405 
406  // 2X Mode
407  Serial.print(F("Rejection Frequency\n\n"));
408  Serial.print(F("0-50 Hz\n"));
409  Serial.print(F("1-60 Hz\n"));
410  Serial.print(F("2-50/60 Hz\n"));
411  Serial.print(F("Enter a Command: "));
412  user_command = read_int();
413  Serial.println(user_command);
414 
415  if (user_command == 0)
416  {
418  Serial.print(F("50 Hz rejection\n"));
419  }
420  else if (user_command == 1)
421  {
423  Serial.print(F("60 Hz rejection\n"));
424  }
425  else
426  {
428  Serial.print(F("50/60 Hz rejection\n"));
429  }
430 }
#define LTC2492_R50
Definition: LTC2492.h:129
#define LTC2492_SPEED_1X
Definition: LTC2492.h:124
static uint16_t eoc_timeout
timeout in ms
Definition: DC1009AA.ino:103
#define LTC2492_R50_R60
Definition: LTC2492.h:131
unsigned char user_command
static uint8_t two_x_mode
The LTC2492 2X Mode settings.
Definition: DC1009AA.ino:100
Header File for Linduino Libraries and Demo Code.
#define LTC2492_CH3
Definition: LTC2492.h:141
#define LTC2492_P3_N2
Definition: LTC2492.h:150
static uint8_t menu_2_read_differential()
Read channels in differential mode.
Definition: DC1009AA.ino:322
#define LTC2492_P1_N0
Definition: LTC2492.h:147
static void print_title()
Prints the title block when program first starts.
Definition: DC1009AA.ino:185
static uint8_t menu_1_read_single_ended()
Read channels in single-ended mode.
Definition: DC1009AA.ino:233
LTC2492: 24-Bit, 4-Channel Delta Sigma ADCs with Easy Drive Input Current Cancellation.
static float adc_voltage
Definition: DC2071AA.ino:115
LTC24XX General Library: Functions and defines for all SINC4 Delta Sigma ADCs.
static void print_user_command(uint8_t menu)
Display selected differential channels.
Definition: DC1009AA.ino:211
float LTC2492_code_to_voltage(int32_t adc_code, float vref)
Calculates the voltage corresponding to an adc code, given the reference (in volts) ...
Definition: LTC2492.cpp:84
#define LTC2492_CH1
Definition: LTC2492.h:139
QuikEval EEPROM Library.
const uint8_t BUILD_FREQ_REJ_COMMAND[3]
Lookup table to build 1X / 2X bits.
Definition: DC1009AA.ino:118
static void menu_4_select_rejection_freq()
Set 1X or 2X mode.
Definition: DC1009AA.ino:402
#define LTC2492_CH2
Definition: LTC2492.h:140
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
int8_t LTC2492_EOC_timeout(uint8_t cs, uint16_t miso_timeout)
Checks for EOC with a specified timeout.
Definition: LTC2492.cpp:72
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 menu_3_set_1X2X()
Set 1X or 2X mode.
Definition: DC1009AA.ino:376
#define LTC2492_P0_N1
Definition: LTC2492.h:146
static void loop()
Repeats Linduino loop.
Definition: DC1009AA.ino:145
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
#define LTC2492_CS
Define the SPI CS pin.
Definition: LTC2492.h:116
static uint8_t demo_board_connected
Set to 1 if the board is connected.
Definition: DC1009AA.ino:99
#define LTC2492_CH0
Definition: LTC2492.h:138
#define LTC2492_P2_N3
Definition: LTC2492.h:149
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
static uint8_t rejection_mode
The LTC2492 rejection mode settings.
Definition: DC1009AA.ino:101
#define LTC2492_SPEED_2X
Definition: LTC2492.h:125
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()
void LTC2492_read(uint8_t cs, uint8_t adc_command_high, uint8_t adc_command_low, int32_t *adc_code)
Reads from LTC2492.
Definition: LTC2492.cpp:78
const uint8_t BUILD_COMMAND_DIFF[4]
Lookup table to build the command for differential mode.
Definition: DC1009AA.ino:111
static void setup()
Initialize Linduino.
Definition: DC1009AA.ino:121
#define LTC2492_R60
Definition: LTC2492.h:130
const uint8_t BUILD_COMMAND_SINGLE_ENDED[4]
Lookup table to build the command for single-ended mode.
Definition: DC1009AA.ino:107
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
static float LTC2492_vref
The LTC2492 ideal reference voltage.
Definition: DC1009AA.ino:102
static uint32_t adc_code
Definition: DC2071AA.ino:113
const uint8_t BUILD_1X_2X_COMMAND[2]
Lookup table to build 1X / 2X bits.
Definition: DC1009AA.ino:115
static void print_prompt()
Prints main menu.
Definition: DC1009AA.ino:200