Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC1186A.ino
Go to the documentation of this file.
1 /*!
2 Linear Technology DC1186A Demonstration Board.
3 LTC2308: 12-Bit, 8-Channel 500ksps SAR 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 voltage source (preferably low-noise) and a precision voltmeter. No
11  external power supply is required. Ensure all jumpers on the demo board are
12  installed in their default positions from the factory. Refer to Demo Manual
13  DC1186A.
14 
15  How to test Single-Ended mode:
16  Bipolar Mode:
17  The voltage source should be connected to one of the inputs CH0,...CH7. Ensure the input is
18  within its specified absolute input voltage range. (It is easiest
19  to tie the voltage source negative terminal to COM.) Ensure the voltage
20  source is set within the range of 0V to +4.096V.
21  (Swapping input voltages results in a reversed polarity reading.)
22 
23  Unipolar Mode:
24  The voltage source should be connected to one of the inputs CH0,...CH7. Ensure the input is
25  within its specified absolute input voltage range. (It is easiest
26  to tie the voltage source negative terminal to COM.) Ensure the voltage
27  source is set within the range of 0V to +4.096V.
28 
29  How to test Differential Mode:
30  Bipolar Mode:
31  The voltage source should be connected between paired channels. Ensure both
32  inputs are within their specified absolute input voltage range. (It is easiest
33  to tie the voltage source negative terminal to COM or GND.) Ensure the voltage
34  source is set within the range of 0 to +4.096V (differential voltage range).
35  (Swapping input voltages results in a reversed polarity reading.)
36 
37  Unipolar Mode:
38  The voltage source should be connected between paired channels. (It is easiest
39  to tie the voltage source negative terminal to COM or GND.) Ensure both inputs
40  are within their specified absolute input voltage range. (It is easiest to tie
41  the voltage source negative terminal to COM or GND.) Ensure the voltage source
42  is set within the range of 0 to +4.096V (differential voltage range).
43 
44 USER INPUT DATA FORMAT:
45  decimal : 1024
46  hex : 0x400
47  octal : 02000 (leading 0 "zero")
48  binary : B10000000000
49  float : 1024.0
50 
51 @endverbatim
52 
53 http://www.linear.com/product/LTC2308
54 
55 http://www.linear.com/product/LTC2308#demoboards
56 
57 
58 Copyright 2018(c) Analog Devices, Inc.
59 
60 All rights reserved.
61 
62 Redistribution and use in source and binary forms, with or without
63 modification, are permitted provided that the following conditions are met:
64  - Redistributions of source code must retain the above copyright
65  notice, this list of conditions and the following disclaimer.
66  - Redistributions in binary form must reproduce the above copyright
67  notice, this list of conditions and the following disclaimer in
68  the documentation and/or other materials provided with the
69  distribution.
70  - Neither the name of Analog Devices, Inc. nor the names of its
71  contributors may be used to endorse or promote products derived
72  from this software without specific prior written permission.
73  - The use of this software may or may not infringe the patent rights
74  of one or more patent holders. This license does not release you
75  from the requirement that you obtain separate licenses from these
76  patent holders to use this software.
77  - Use of the software either in source or binary form, must be run
78  on or directly connected to an Analog Devices Inc. component.
79 
80 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
81 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
82 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
83 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
84 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
85 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
86 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
87 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
88 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
89 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90 */
91 
92 /*! @file
93  @ingroup LTC2308
94 */
95 
96 #include <Arduino.h>
97 #include <stdint.h>
98 #include "Linduino.h"
99 #include "LT_SPI.h"
100 #include "UserInterface.h"
101 #include "LT_I2C.h"
102 #include "QuikEval_EEPROM.h"
103 #include "LTC2308.h"
104 #include <SPI.h>
105 #include <Wire.h>
106 
107 // Function Declaration
108 void print_title(); // Print the title block
109 void print_prompt(); // Prompt the user for an input command
110 uint8_t print_user_command_differential(); // Display selected differential channels
111 uint8_t print_user_command_single_ended(); // Display selected single ended channels
112 void print_channel_selection(uint8_t menu);
113 
114 void menu_1_read_input(); // Read channels
115 void menu_2_select_single_ended_differential(); // Sets LTC2308 to Single-Ended or Differential
116 void menu_3_select_uni_bipolar(); // Sets LTC2308 to Bipolar or Unipolar
117 void menu_4_sleep();
118 
119 // Global variables
120 static uint8_t uni_bipolar = LTC2308_UNIPOLAR_MODE; //!< Default set for unipolar mode
121 static uint8_t single_ended_differential = LTC2308_SINGLE_ENDED_MODE; //!< LTC2308 Unipolar or Bipolar mode selection
122 static uint8_t LTC2308_bits = 12; //!< Resolution (12 bits)
123 static float LTC2308_vref = 4.096;
124 
125 // Constants
126 //! Lookup table to build the command for single-ended mode, input with respect to GND
129  }; //!< Builds the command for single-ended mode, input with respect to GND
130 
131 //! Lookup table to build the command for differential mode with the selected uni/bipolar mode
134  }; //!< Build the command for differential mode
135 
136 
137 //! Initialize Linduino
138 void setup()
139 {
140  uint16_t adc_code;
141 
142  quikeval_SPI_init(); // Configure the spi port for 4MHz SCK
143  quikeval_SPI_connect(); // Connect SPI to main data port
144  Serial.begin(115200); // Initialize the serial port to the PC
145  print_title();
146  print_prompt();
147 }
148 
149 
150 //! Repeats Linduino loop
151 void loop()
152 {
153  uint16_t user_command;
154 
155  if (Serial.available()) // Check for user input
156  {
157  user_command = read_int(); // Read the user command
158  if (user_command != 'm')
159  Serial.println(user_command); // Prints the user command to com port
160  Serial.flush();
161  switch (user_command)
162  {
163  case 1:
165  break;
166  case 2:
168  break;
169  case 3:
171  break;
172  case 4:
173  menu_4_sleep();
174  break;
175  default:
176  Serial.println(F("Invalid Option"));
177  break;
178  }
179  Serial.println();
180  Serial.println(F("*************************"));
181  print_prompt();
182  }
183 }
184 
185 
186 // Function Definitions
187 //! Read channels
189 {
190  uint8_t user_command;
191  uint16_t adc_command; // The LTC2308 command byte
192  uint16_t adc_code = 0; // The LTC2308 code
193  uint16_t display_code;
194  uint8_t x, y, startcount, endcount;
195  float adc_voltage;
196 
198  {
200  {
201  Serial.println(F(" Read Input in Single-Ended, Unipolar mode:"));
202  Serial.println(F(" Note that in Unipolar mode, input voltages less than zero are reported as 0.0V"));
203  user_command = print_user_command_single_ended();
204  }
205  else
206  {
207  Serial.println(F(" Read Input in Differential, Unipolar mode:"));
208  Serial.println(F(" Note that in Unipolar mode, input voltages less than zero are reported as 0.0V"));
209  user_command = print_user_command_differential();
210  }
211  }
212  else
213  {
215  {
216  Serial.println(F(" Read Input in Single-Ended, Bipolar mode:"));
217  user_command = print_user_command_single_ended();
218  }
219  else
220  {
221  Serial.println(F(" Read Input in Differential, Bipolar mode:"));
222  user_command = print_user_command_differential();
223  }
224  }
225 
226  if (user_command == 8) //read all channels
227  {
228  startcount = 0;
229  endcount = 7;
230  }
231  else
232  {
233  startcount = user_command;
234  endcount = user_command;
235  }
236 
237  if (single_ended_differential == LTC2308_SINGLE_ENDED_MODE) //read single-ended
238  {
239  adc_command = BUILD_COMMAND_SINGLE_ENDED[0] | uni_bipolar;
240  LTC2308_read(LTC2308_CS, adc_command, &adc_code); // Throws out last reading and starts CH0 conversion
241  for (x = startcount; x <= endcount; x++)
242  {
243  adc_command = BUILD_COMMAND_SINGLE_ENDED[x % 8] | uni_bipolar; // Send channel config for the NEXT conversion to take place
244  LTC2308_read(LTC2308_CS, adc_command, &adc_code); // Throws out last reading and starts CH0 conversion
245  LTC2308_read(LTC2308_CS, adc_command, &adc_code); // Throws out last reading and starts CH0 conversion
246 
247  display_code = adc_code >> (16 - LTC2308_bits);
248  display_code = display_code & 0xFFF;
249 
250  Serial.print(F(" Received Code: b"));
251  Serial.println(display_code, BIN);
252 
253  adc_voltage = LTC2308_code_to_voltage(adc_code, LTC2308_vref, uni_bipolar);
254  Serial.print(F(" Voltage read on "));
255  Serial.print(F("Ch"));
256  Serial.print(x);
257  Serial.print(F(": "));
258  Serial.print(adc_voltage, 4);
259  Serial.println(F("V"));
260  Serial.println();
261  }
262  }
263 
264  else //read differential
265  {
266  adc_command = BUILD_COMMAND_SINGLE_ENDED[0] | uni_bipolar;
267  LTC2308_read(LTC2308_CS, adc_command, &adc_code); // Throws out last reading and starts CH0 conversion
268  for (x = startcount; x <= endcount; x++)
269  {
270  adc_command = BUILD_COMMAND_DIFF[x % 8] | uni_bipolar; // Send channel config for the NEXT conversion to take place
271  LTC2308_read(LTC2308_CS, adc_command, &adc_code); // Throws out last reading and starts CH0 conversion
272  LTC2308_read(LTC2308_CS, adc_command, &adc_code); // Read previous channel conversion (x-1) and start next one (x)
273 
274  display_code = adc_code >> (16 - LTC2308_bits);
275  display_code = display_code & 0xFFF;
276 
277  Serial.print(F(" Received Code: b"));
278  Serial.println(display_code, BIN);
279 
280  adc_voltage = LTC2308_code_to_voltage(adc_code, LTC2308_vref, uni_bipolar);
281  Serial.print(F(" Voltage read between Chs "));
283  Serial.print(adc_voltage, 4);
284  Serial.println(F("V"));
285  Serial.println();
286  }
287  }
288 }
289 
290 
291 //! Sets LTC2308 to Single-Ended or Differential
293 {
294  uint8_t user_command;
295 
296  Serial.println(F("\n 0 = Single-Ended"));
297  Serial.println(F(" 1 = Differential"));
298  Serial.print(F(" Enter a Command: "));
299 
300  user_command = read_int(); // Read user input for uni_bipolar
301  Serial.println(user_command);
302  switch (user_command)
303  {
304  case 0:
305  Serial.println(F(" Single-Ended mode selected"));
307  break;
308  case 1:
309  Serial.println(F(" Differential mode selected"));
311  break;
312  default:
313  {
314  Serial.println(" Invalid Option");
315  return;
316  }
317  break;
318  }
319 }
320 
321 
322 //! Select unipolar (0-REFCOMP) or bipolar (+/- 0.5 x REFCOMP) mode
323 //! @return void
325 {
326  uint8_t user_command;
327 
328  Serial.println(F("\n 0 = Bipolar"));
329  Serial.println(F(" 1 = Unipolar"));
330  Serial.print(F(" Enter a Command: "));
331 
332  user_command = read_int(); // Read user input for uni_bipolar
333  Serial.println(user_command);
334  switch (user_command)
335  {
336  case 0:
337  Serial.println(F(" Bipolar mode selected"));
339  break;
340  case 1:
341  Serial.println(F(" Unipolar mode selected"));
343  break;
344  default:
345  Serial.println(" Invalid Option");
346  return;
347  break;
348  }
349 }
350 
351 
352 //! Put LTC2308 to sleep (low power)
353 //! @return void
355 {
356  // Sleep Mode
357  uint16_t user_command;
358  uint16_t adc_code = 0; // The LTC2308 code
359  LTC2308_read(LTC2308_CS, LTC2308_SLEEP_MODE, &adc_code); // Build ADC command for sleep mode
360  Serial.println();
361  Serial.print(F(" ADC Command: B"));
362  Serial.println(LTC2308_SLEEP_MODE, BIN);
363  Serial.println(F(" LTC2308 Is Now In Sleep Mode"));
364  Serial.println(F(" Enter RETURN to exit Sleep Mode"));
365  user_command = read_int();
366  LTC2308_read(LTC2308_CS, LTC2308_NORMAL_MODE, &adc_code); // Exit Sleep Mode
367 }//! Prints the title block when program first starts.
369 {
370  Serial.println();
371  Serial.println(F("*****************************************************************"));
372  Serial.println(F("* DC1186A Demonstration Program *"));
373  Serial.println(F("* *"));
374  Serial.println(F("* This program demonstrates how to send data and receive data *"));
375  Serial.println(F("* from the LTC2308 12-bit ADC. *"));
376  Serial.println(F("* *"));
377  Serial.println(F("* Set the baud rate to 115200 and select the newline terminator.*"));
378  Serial.println(F("* *"));
379  Serial.println(F("*****************************************************************"));
380 }
381 
382 
383 //! Prints main menu.
385 {
386  Serial.println(F("1-Read ADC Input "));
387  Serial.println(F("2-Select Single-Ended / Differential measurement (default is Single_Ended)"));
388  Serial.println(F("3-Select Unipolar / Bipolar measurement (default is Unipolar)"));
389  Serial.println(F("4-Select Sleep Mode"));
390  Serial.println();
391  Serial.print(F("Enter a command: "));
392 }
393 
394 
395 //! Display selected differential channels. Displaying single-ended channels is
396 //! straightforward; not so with differential because the inputs can take either polarity.
398 {
399  uint8_t user_command;
400 
401  Serial.println(F(" *************************"));
402  Serial.println(F(" 0 = 0P-1N"));
403  Serial.println(F(" 1 = 2P-3N"));
404  Serial.println(F(" 2 = 4P-5N"));
405  Serial.println(F(" 3 = 6P-7N"));
406  Serial.println(F(" 4 = 1P-0N"));
407  Serial.println(F(" 5 = 3P-2N"));
408  Serial.println(F(" 6 = 5P_4N"));
409  Serial.println(F(" 7 = 7P = 6N"));
410  Serial.println(F(" 8 = ALL Even_P-Odd_N"));
411  Serial.println(F(" m = Main Menu"));
412  Serial.println();
413  Serial.print(F(" Enter a Command: "));
414 
415  user_command = read_int(); // Read the menu command
416  Serial.println(user_command);
417  if (user_command == 'm')
418  return(0);
419 
420  switch (user_command) //check for invalid selection
421  {
422  case 0:
423  Serial.println(F(" 0P-1N selected"));
424  break;
425  case 1:
426  Serial.println(F(" 2P-3N selected"));
427  break;
428  case 2:
429  Serial.println(F(" 4P-5N selected"));
430  break;
431  case 3:
432  Serial.println(F(" 6P-7N selected"));
433  break;
434  case 4:
435  Serial.println(F(" 1P-0N selected"));
436  break;
437  case 5:
438  Serial.println(F(" 3P-2N selected"));
439  break;
440  case 6:
441  Serial.println(F(" 5P-4N selected"));
442  break;
443  case 7:
444  Serial.println(F(" 7P-6N selected"));
445  break;
446  case 8:
447  Serial.println(F(" ALL Even_P-Odd_N selected"));
448  break;
449  default:
450  Serial.println(F(" Invalid Option"));
451  break;
452  }
453  return(user_command);
454 }
455 
456 
457 //! Display selected differential channels. Displaying single-ended channels is
458 //! straightforward; not so with differential because the inputs can take either polarity.
459 void print_channel_selection(uint8_t menu)
460 {
461  switch (menu)
462  {
463  case 0:
464  Serial.print(F(" 0P-1N:"));
465  break;
466  case 1:
467  Serial.print(F(" 2P-3N:"));
468  break;
469  case 2:
470  Serial.print(F(" 4P-5N:"));
471  break;
472  case 3:
473  Serial.print(F(" 6P-7N:"));
474  break;
475  case 4:
476  Serial.print(F(" 1P-0N:"));
477  break;
478  case 5:
479  Serial.print(F(" 3P-2N:"));
480  break;
481  case 6:
482  Serial.print(F(" 5P-4N:"));
483  break;
484  case 7:
485  Serial.print(F(" 7P-6N:"));
486  break;
487  }
488 }
489 
490 
491 //! Display selected single-ended channel.
493 {
494  uint8_t user_command;
495  Serial.println(F(" *************************"));
496  Serial.println(F(" 0 = CH0"));
497  Serial.println(F(" 1 = CH1"));
498  Serial.println(F(" 2 = CH2"));
499  Serial.println(F(" 3 = CH3"));
500  Serial.println(F(" 4 = CH4"));
501  Serial.println(F(" 5 = CH5"));
502  Serial.println(F(" 6 = CH6"));
503  Serial.println(F(" 7 = CH7"));
504  Serial.println(F(" 8 = ALL"));
505  Serial.println(F(" m = Main Menu"));
506  Serial.println();
507  Serial.print(F(" Enter a Command: "));
508 
509  user_command = read_int(); // Read the single-ended menu command
510  Serial.println(user_command);
511  if (user_command == 'm')
512  return(0);
513 
514  switch (user_command) //check for invalid selection
515  {
516  case 0:
517  Serial.println(F(" CH0 selected"));
518  break;
519  case 1:
520  Serial.println(F(" CH1 selected"));
521  break;
522  case 2:
523  Serial.println(F(" CH2 selected"));
524  break;
525  case 3:
526  Serial.println(F(" CH3 selected"));
527  break;
528  case 4:
529  Serial.println(F(" CH4 selected"));
530  break;
531  case 5:
532  Serial.println(F(" CH5 selected"));
533  break;
534  case 6:
535  Serial.println(F(" CH6 selected"));
536  break;
537  case 7:
538  Serial.println(F(" CH7 selected"));
539  break;
540  case 8:
541  Serial.println(F(" All selected"));
542  break;
543  default:
544  Serial.println(F(" Invalid Option"));
545  break;
546  }
547 
548  return(user_command);
549 }
550 
#define LTC2308_CH5
Definition: LTC2308.h:109
#define LTC2308_CH2
Definition: LTC2308.h:106
static uint8_t print_user_command_single_ended()
Display selected single-ended channel.
Definition: DC1186A.ino:492
unsigned char user_command
void LTC2308_read(uint8_t cs, uint8_t adc_command, uint16_t *adc_code)
Reads the ADC and returns 16-bit data.
Definition: LTC2308.cpp:77
static uint8_t adc_command
Definition: DC2071AA.ino:111
#define LTC2308_CH4
Definition: LTC2308.h:108
static void menu_4_sleep()
Put LTC2308 to sleep (low power)
Definition: DC1186A.ino:354
Header File for Linduino Libraries and Demo Code.
#define LTC2308_UNIPOLAR_MODE
Definition: LTC2308.h:133
#define LTC2308_P6_N7
Definition: LTC2308.h:126
#define LTC2308_CH7
Definition: LTC2308.h:111
static void print_channel_selection(uint8_t menu)
Display selected differential channels.
Definition: DC1186A.ino:459
#define LTC2308_P0_N1
Definition: LTC2308.h:117
static void setup()
Initialize Linduino.
Definition: DC1186A.ino:138
#define LTC2308_NORMAL_MODE
Definition: LTC2308.h:144
#define LTC2308_CH3
Definition: LTC2308.h:107
static float adc_voltage
Definition: DC2071AA.ino:115
static uint8_t single_ended_differential
LTC2308 Unipolar or Bipolar mode selection.
Definition: DC1186A.ino:121
#define LTC2308_CH6
Definition: LTC2308.h:110
#define LTC2308_P7_N6
Definition: LTC2308.h:127
static uint8_t LTC2308_bits
Resolution (12 bits)
Definition: DC1186A.ino:122
static uint8_t print_user_command_differential()
Display selected differential channels.
Definition: DC1186A.ino:397
#define LTC2308_SLEEP_MODE
Definition: LTC2308.h:143
static void print_prompt()
Prints main menu.
Definition: DC1186A.ino:384
#define LTC2308_DIFFERENTIAL_MODE
Definition: LTC2308.h:137
QuikEval EEPROM Library.
static void loop()
Repeats Linduino loop.
Definition: DC1186A.ino:151
#define LTC2308_P1_N0
Definition: LTC2308.h:118
const uint8_t BUILD_COMMAND_DIFF[8]
Lookup table to build the command for differential mode with the selected uni/bipolar mode...
Definition: DC1186A.ino:132
const uint8_t BUILD_COMMAND_SINGLE_ENDED[8]
Lookup table to build the command for single-ended mode, input with respect to GND.
Definition: DC1186A.ino:127
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
static void menu_1_read_input()
Read channels.
Definition: DC1186A.ino:188
#define LTC2308_P4_N5
Definition: LTC2308.h:123
#define LTC2308_CH1
Definition: LTC2308.h:105
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
#define LTC2308_BIPOLAR_MODE
Definition: LTC2308.h:134
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
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()
static int32_t display_code
Definition: DC2071AA.ino:114
static void print_title()
Prints the title block when program first starts.
Definition: DC1186A.ino:368
#define LTC2308_P3_N2
Definition: LTC2308.h:121
#define LTC2308_P5_N4
Definition: LTC2308.h:124
float LTC2308_code_to_voltage(uint16_t adc_code, float vref, uint8_t uni_bipolar)
Calculates the LTC2308 input&#39;s unipolar voltage given the binary data and lsb weight.
Definition: LTC2308.cpp:84
#define LTC2308_P2_N3
Definition: LTC2308.h:120
static float LTC2308_vref
Definition: DC1186A.ino:123
#define LTC2308_CH0
Definition: LTC2308.h:104
#define LTC2308_CS
Define the SPI CS pin.
Definition: LTC2308.h:98
static uint32_t adc_code
Definition: DC2071AA.ino:113
static void menu_2_select_single_ended_differential()
Sets LTC2308 to Single-Ended or Differential.
Definition: DC1186A.ino:292
#define LTC2308_SINGLE_ENDED_MODE
Definition: LTC2308.h:136
static void menu_3_select_uni_bipolar()
Select unipolar (0-REFCOMP) or bipolar (+/- 0.5 x REFCOMP) mode.
Definition: DC1186A.ino:324
static uint8_t uni_bipolar
Default set for unipolar mode.
Definition: DC1186A.ino:120
LTC2308: 16-bit 8-channel 100ksps ADC.