Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC2839A.ino
Go to the documentation of this file.
1 /*!
2 Analog Devices DC2839A Demonstration Board.
3 LTC6115: High Voltage High Side Current and Voltage Sense.
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.
11  Ensure all jumpers on the demo board are installed in their default positions
12  from the factory. Refer to Demo Manual for LTC6115.
13 
14  How to test:
15  The voltage source should be connected to input AIN+/AIN-. Ensure the
16  input is within its specified absolute input voltage range. (It is easiest
17  to tie the voltage source negative terminal to COM.) Ensure the voltage
18  source is set within the range of 0V to +5.00V.
19 
20 USER INPUT DATA FORMAT:
21  decimal : 1024
22  hex : 0x400
23  octal : 02000 (leading 0 "zero")
24  binary : B10000000000
25  float : 1024.0
26 
27 @endverbatim
28 
29 https://www.analog.com/en/products/ltc6115.html
30 
31 Copyright (c) 2018, Analog Devices Inc. (ADI)
32 All rights reserved.
33 
34 Redistribution and use in source and binary forms, with or without
35 modification, are permitted provided that the following conditions are met:
36 
37 1. Redistributions of source code must retain the above copyright notice, this
38  list of conditions and the following disclaimer.
39 2. Redistributions in binary form must reproduce the above copyright notice,
40  this list of conditions and the following disclaimer in the documentation
41  and/or other materials provided with the distribution.
42 
43 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
44 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
46 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
47 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
52 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 
54 The views and conclusions contained in the software and documentation are those
55 of the authors and should not be interpreted as representing official policies,
56 either expressed or implied, of Analog Devices Inc.
57 
58 The Analog Devices Linduino is not affiliated with the official Arduino team.
59 However, the Linduino is only possible because of the Arduino team's commitment
60 to the open-source community. Please, visit http://www.arduino.cc and
61 http://store.arduino.cc , and consider a purchase that will help fund their
62 ongoing work.
63 */
64 
65 /*! @file
66  @ingroup LTC6115
67 */
68 
69 #include <Arduino.h>
70 #include <stdint.h>
71 #include "Linduino.h"
72 #include "LT_SPI.h"
73 #include "UserInterface.h"
74 #include "LT_I2C.h"
75 #include "QuikEval_EEPROM.h"
76 #include "LTC6115.h"
77 #include <SPI.h>
78 #include <Wire.h>
79 
80 
81 #ifndef LTC6115_GPIO
82 #define LTC6115_GPIO QUIKEVAL_GPIO //!< Linduino QuikEval GPIO pin (QuikEval connector pin 14) connects to Arduino pin 9
83 #endif
84 
85 
86 // Function Declaration
87 void print_title(); // Print the title block
88 void print_prompt(); // Prompt the user for an input command
89 
90 
91 // Global variables
92 volatile float start_millis; //!< Start time when menu 4 function is called
93 volatile float current_millis; //!< Number of elapsed milliseconds since the program started running
94 volatile float globaltime_ms; //!< Number of elapsed milliseconds since menu 4 function is called
95 volatile int ISR_flag; //!< Set to 1 when interrupt service routine is running
96 volatile int samples_counter; //!< Counts the number of samples taken
97 volatile int num_samples; //!< Total number of samples that the user desires
98 int update_interval; //!< Sampling interval(ms) to update to
99 int compare_reg; //!< Value to set compare match register to get desired interrupt frequency (Hz)
100 volatile int print_flag; //!< Set to 1 to print sampling data for menu option 4
101 volatile int ISR_prompt_flag; //!< Set to 1 to print prompt after interrupt service completes
102 volatile uint32_t readV; //!< Stores voltage reading
103 volatile uint32_t readI; //!< Stores current reading
104 
105 //! Initialize Linduino
106 //! @return void
107 void setup()
108 {
109  char demo_name[]="DC2839A"; // Demo Board Name stored in QuikEval EEPROM
110  int8_t demo_board_connected; // Set to 1 if the board is connected
111 
112  quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz
113  Serial.begin(115200); // Initialize the serial port to the PC
114 
115  print_title();
116  demo_board_connected = discover_demo_board(demo_name);
117 
118  if (!demo_board_connected)
119  {
120  Serial.println(F("EEPROM not detected, will attempt to proceed"));
121  demo_board_connected = 1;
122  }
123 
124  LTC6115_initialize(); // Initialize the 6115 variables
125  print_prompt();
126 
127  pinMode (LTC6115_VIN, INPUT); // Analog input: voltage sense
128  pinMode (LTC6115_IIN, INPUT); // Analog input: current sense
129  pinMode (LTC6115_GPIO, OUTPUT); // Chip select needs to be an output
130 
131  // Initialize global variables
132  start_millis = 0;
133  current_millis = 0;
134  globaltime_ms = 0;
135  ISR_flag = 0;
136  samples_counter = 0;
137  num_samples = 0;
138  update_interval = 1000;
139  compare_reg = 15624;
140  print_flag = 0;
141  ISR_prompt_flag = 0;
142  readV = 0;
143  readI = 0;
144 
145  // Initialize timer1
146 
147  noInterrupts(); // Disable all interrupts
148 
149  // Set timer1 interrupt at 1Hz
150  TCCR1A = 0; // Set entire TCCR1A register to 0
151  TCCR1B = 0; // Same for TCCR1B
152  TCNT1 = 0; // Initialize counter value to 0
153 
154  // Set compare match register for 1hz increments
155  // OCR1A = compare_reg;
156  // compare_reg = (16*10^6) / (1*1024) - 1 (must be <65536)
158 
159  TCCR1B |= (1 << WGM12); // Turn on CTC mode
160  TCCR1B |= (1 << CS12) | (1 << CS10); // Set CS12 and CS10 bits for 1024 prescaler
161  TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt
162 
163  interrupts(); // Enable all interrupts
164 }
165 
166 
167 //! Repeats Linduino loop
168 //! @return void
169 void loop()
170 {
171  if (print_flag == 1) // Prints data for menu option 4
172  {
173  float VinVolts;
174  float IinAmps;
175  VinVolts = LTC6115ToVolts(readV);
176  IinAmps = LTC6115ToAmps(readI);
177  Serial.println();
178  Serial.print(globaltime_ms);
179  Serial.print(", ");
180  Serial.print(VinVolts,3);
181  Serial.print(", ");
182  Serial.print(IinAmps,3);
183  print_flag = 0;
184  }
185 
186  if (ISR_prompt_flag == 1) // Prints prompt after completion of menu 4 function
187  {
188  Serial.println();
189  print_prompt();
190  Serial.println();
191  ISR_prompt_flag = 0;
192  }
193 
194  if (ISR_flag == 0) // If Service Routine is not running
195  {
196  uint16_t user_command;
197  if (Serial.available())
198  {
199  user_command = read_int(); // Read the user command
200 
201  Serial.println(user_command); // Prints the user command to com port
202  switch (user_command)
203  {
204  case 1:
206  break;
207  case 2:
209  break;
210  case 3:
212  break;
213  case 4:
215  break;
216  case 5:
218  break;
219  case 6:
221  break;
222  default:
223  Serial.println("Invalid Option");
224  break;
225  }
226 
227  if (ISR_flag == 0)
228  {
229  print_prompt();
230  Serial.println();
231  }
232  }
233  }
234  else // If Service Routine is running, stop sampling if user enters 6
235  {
236  if (Serial.available())
237  {
238  if (read_int() == 6)
239  {
240  ISR_flag = 0;
241  ISR_prompt_flag = 1;
243  }
244  }
245  }
246 
247 }
248 
249 // Function Definitions
250 
251 //! Read channel
252 //! @return void
254 {
255  uint32_t readV;
256  uint32_t readI;
257 
258  float VinVolts;
259  float IinAmps;
260 
261  pinMode(LTC6115_VIN, INPUT); // Make sure pins configured as inputs
262  pinMode(LTC6115_IIN, INPUT);
263 
264  readV = analogRead(LTC6115_VIN);
265  readI = analogRead(LTC6115_IIN);
266 
267 // // Debug
268 // Serial.print("Raw Voltage Code: ");
269 // Serial.println(readV);
270 // Serial.print("Raw Current Code: ");
271 // Serial.println(readI);
272 // Serial.println();
273 
274  VinVolts = LTC6115ConvertToVolts(readV);
275  IinAmps = LTC6115ConvertToAmps(readI);
276 
277  // Print the ADC result
278  Serial.println();
279  Serial.print("VIN Input Voltage, Isense Current: ");
280  Serial.print(VinVolts, 4);
281  Serial.print("V , ");
282  Serial.print(IinAmps, 4);
283  Serial.print("A");
284  Serial.println();
285 }
286 
287 
288 //! @return void
290 {
291  float user_command;
292 
293  Serial.println();
294  Serial.print(F(" Enter Voltage Gain (V/V): "));
295 
296  user_command = read_float();
297  Serial.println(user_command); // Prints the user command to com port
298  if (user_command < 0 || user_command > 199) // ?????????????????????????????????????????????????????
299  Serial.println(F(" Input should be from 0 to 199."));
300  else
301  {
302  LTC6115ChangeVGain(user_command);
303  Serial.print(F(" Voltage gain has been set to "));
304  Serial.println(user_command);
305  }
306 }
307 
308 
309 //! Select current channel transimpedance gain (V/A)
310 //! @return void
312 {
313  float user_command;
314 
315  Serial.println();
316  Serial.print(F(" Enter Transimpedance Gain (V/A): "));
317 
318  user_command = read_float();
319  Serial.println(user_command); // Prints the user command to com port
320  if (user_command < 0 || user_command > 20000) // Adjust max allowable gain ???????????????????????????????????????????/
321  Serial.println(F(" Input should be from 0 to 20000."));
322  else
323  {
324  LTC6115ChangeIGain(user_command);
325  Serial.print(F(" Transimpedance has been set to "));
326  Serial.println(user_command);
327  }
328 }
329 
330 
331 //! Changes the sampling frequency (ms)
332 //! @return void
334 {
335  // Get and store user input for sampling interval
336  Serial.print("Enter desired sample interval between 10 and 1000(ms): ");
338  Serial.println(update_interval);
339  Serial.println();
340 
341  while (update_interval < 10 || update_interval > 1000) // Prompt user until valid number is entered
342  {
343  Serial.println("Invalid sampling interval.");
344  Serial.print("Enter desired sample interval between 10 and 1000(ms): ");
346  Serial.println(update_interval);
347  Serial.println();
348  }
349 
350  // Convert milliseconds to Hz
351  int frequency;
352  frequency = millsToHz(update_interval);
353 
354  // Calculate value to set the compare match register
355  compare_reg = (int) ((16000000.0/((float)frequency * 1024.0)) - 1.0);
357 }
358 
359 //! Updates the compare match register
360 //! @return void
361 void update_compare_reg(uint32_t regVal)
362 {
363  noInterrupts();
364  OCR1A = regVal;
365  interrupts();
366 }
367 
368 //! Pipes voltage and current reading results to a file
369 //! @return void
371 {
372  samples_counter = 0; // Reset the counter to 0
373  num_samples = 0; // Reset the sample size to 0
374 
375  // Get and store user input for # of samples
376  Serial.println();
377  Serial.print("Enter desired number of samples: ");
378  num_samples = read_int();
379  Serial.println(num_samples);
380  Serial.println();
381  Serial.println();
382  Serial.println("Elapsed ms, V, I");
383 
384  ISR_flag = 1; //Set flag to 1 to allow interrupts to start service
385 }
386 
387 
388 //! Stops the sampling from menu 5
389 //! @return void
391 {
393 }
394 
395 //! Timer Compare Interrupt Service Routine
396 ISR(TIMER1_COMPA_vect)
397 {
398  if (ISR_flag == 1)
399  {
400  // Update milliseconds elapsed since menu 5 is called
401  if (samples_counter == 0) // Reset time variable to 0 at the start of each sample session
402  {
403  start_millis = millis();
404  current_millis = millis();
406  }
407  else // Calculate elapsed time between current sample and start time
408  {
409  current_millis = millis();
411  }
412 
413 
414  if (samples_counter < num_samples) // Continue sampling if sampling is incomplete
415  {
416  readV = analogRead(LTC6115_VIN);
417  readI = analogRead(LTC6115_IIN);
418  print_flag = 1;
419  samples_counter += 1;
420  }
421  else if (samples_counter >= num_samples && samples_counter != 0) // Sampling is complete, end ISR and print prompt
422  {
423  ISR_flag = 0;
424  ISR_prompt_flag = 1;
425  }
426  }
427 }
428 
429 
430 //! Prints the title block when program first starts
431 //! @return void
433 {
434  Serial.println();
435  Serial.println(F("*****************************************************************"));
436  Serial.println(F("* LTC6115 *"));
437  Serial.println(F("* *"));
438  Serial.println(F("* This program demonstrates how to work with the LTC6115. *"));
439  Serial.println(F("* *"));
440  Serial.println(F("* Set the baud rate to 115200 and select the newline terminator.*"));
441  Serial.println(F("* *"));
442  Serial.println(F("*****************************************************************"));
443 }
444 
445 
446 //! Prints main menu
447 //! @return void
449 {
450  Serial.println(F("\n\n"));
451  Serial.println(F("*************************"));
452  Serial.println(F("1 - Convert and Read V and I (Single Sample)"));
453  Serial.print(F("2 - Change V Gain (Current setting: "));
454  Serial.print(getVGain());
455  Serial.println(F(" V/V)"));
456  Serial.print(F("3 - Change I Gain (Current setting: "));
457  Serial.print(getIGain());
458  Serial.println(F(" V/A, divide by Rsense for V/V)"));
459  Serial.print(F("4 - Change Sampling Period (Current setting: "));
460  Serial.print(update_interval);
461  Serial.println(F("ms)"));
462  Serial.println(F("5 - Begin Continuous V and I Sampling Conversion Readings (For Specified # of Samples)"));
463  Serial.println(F("6 - Stop Sampling"));
464  Serial.print(F("\nEnter a command: "));
465 }
466 
467 
static void menu_4_changeSampleFreq()
Changes the sampling frequency (ms)
Definition: DC2839A.ino:333
static void menu_3_changeIGain()
Select current channel transimpedance gain (V/A)
Definition: DC2839A.ino:311
static void menu_2_changeVGain()
Definition: DC2839A.ino:289
volatile float current_millis
Number of elapsed milliseconds since the program started running.
Definition: DC2839A.ino:93
unsigned char user_command
#define LTC6115_IIN
Maps to DC2026 J7.1, ADC channel 1.
Definition: LTC6115.h:77
void LTC6115ChangeIGain(float val)
This function changes the Current gain.
Definition: LTC6115.cpp:162
Header File for Linduino Libraries and Demo Code.
float LTC6115ToVolts(uint32_t val)
This function converts ADC code to Voltage without the converted voltage print statement.
Definition: LTC6115.cpp:128
float LTC6115ConvertToVolts(uint32_t val)
This function converts ADC code to Voltage.
Definition: LTC6115.cpp:118
void LTC6115_initialize()
This function will initialize 6115 variables.
Definition: LTC6115.cpp:92
float LTC6115ToAmps(uint32_t val)
This function converts ADC code to Current without the converted current print statement.
Definition: LTC6115.cpp:146
volatile int ISR_prompt_flag
Set to 1 to print prompt after interrupt service completes.
Definition: DC2839A.ino:101
static int update_interval
Sampling interval(ms) to update to.
Definition: DC2839A.ino:98
volatile float globaltime_ms
Number of elapsed milliseconds since menu 4 function is called.
Definition: DC2839A.ino:94
float getIGain()
This function returns the current gain (V/A).
Definition: LTC6115.cpp:109
#define LTC6115_VIN
Pin Mapping.
Definition: LTC6115.h:76
volatile int num_samples
Total number of samples that the user desires.
Definition: DC2839A.ino:97
QuikEval EEPROM Library.
volatile int print_flag
Set to 1 to print sampling data for menu option 4.
Definition: DC2839A.ino:100
#define LTC6115_GPIO
Linduino QuikEval GPIO pin (QuikEval connector pin 14) connects to Arduino pin 9. ...
Definition: DC2839A.ino:82
static void update_compare_reg(uint32_t regVal)
Updates the compare match register.
Definition: DC2839A.ino:361
int8_t discover_demo_board(char *demo_name)
Read the ID string from the EEPROM and determine if the correct board is connected.
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
uint32_t millsToHz(uint32_t val)
This function converts milliseconds to frequency (Hz).
Definition: LTC6115.cpp:169
static void print_title()
Prints the title block when program first starts.
Definition: DC2839A.ino:432
static void loop()
Repeats Linduino loop.
Definition: DC2839A.ino:169
volatile int ISR_flag
Set to 1 when interrupt service routine is running.
Definition: DC2839A.ino:95
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
volatile uint32_t readI
Stores current reading.
Definition: DC2839A.ino:103
char demo_name[]
Demo Board Name stored in QuikEval EEPROM.
Definition: DC1880A.ino:97
int32_t read_int()
float getVGain()
This function returns the voltage gain (V/V).
Definition: LTC6115.cpp:100
float read_float()
void LTC6115ChangeVGain(float val)
This function changes the Voltage gain.
Definition: LTC6115.cpp:155
LTC6115 High Voltage High Side Current and Voltage Sense.
static void print_prompt()
Prints main menu.
Definition: DC2839A.ino:448
volatile uint32_t readV
Stores voltage reading.
Definition: DC2839A.ino:102
volatile float start_millis
Start time when menu 4 function is called.
Definition: DC2839A.ino:92
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
volatile int samples_counter
Counts the number of samples taken.
Definition: DC2839A.ino:96
static void setup()
Initialize Linduino.
Definition: DC2839A.ino:107
static int compare_reg
Value to set compare match register to get desired interrupt frequency (Hz)
Definition: DC2839A.ino:99
static void menu_6_stopSampling()
Stops the sampling from menu 5.
Definition: DC2839A.ino:390
ISR(TIMER1_COMPA_vect)
Timer Compare Interrupt Service Routine.
Definition: DC2839A.ino:396
static void menu_5_pipeToFile()
Pipes voltage and current reading results to a file.
Definition: DC2839A.ino:370
static float menu_1_convert_read()
Read channel.
Definition: DC2839A.ino:253
float LTC6115ConvertToAmps(uint32_t val)
This function converts ADC code to Current.
Definition: LTC6115.cpp:137
static uint8_t demo_board_connected
Set to 1 if the board is connected.