| 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)
157 update_compare_reg(compare_reg);
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:
205 menu_1_convert_read();
206 break;
207 case 2:
208 menu_2_changeVGain();
209 break;
210 case 3:
211 menu_3_changeIGain();
212 break;
213 case 4:
214 menu_4_changeSampleFreq();
215 break;
216 case 5:
217 menu_5_pipeToFile();
218 break;
219 case 6:
220 menu_6_stopSampling();
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;
242 samples_counter = num_samples;
243 }
244 }
245 }
246
247 }
248
249 // Function Definitions
250
251 //! Read channel
252 //! @return void
253 float menu_1_convert_read()
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
289 void menu_2_changeVGain()
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
311 void menu_3_changeIGain()
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
333 void menu_4_changeSampleFreq()
334 {
335 // Get and store user input for sampling interval
336 Serial.print("Enter desired sample interval between 10 and 1000(ms): ");
337 update_interval = read_int();
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): ");
345 update_interval = read_int();
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);
356 update_compare_reg(compare_reg);
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
370 void menu_5_pipeToFile()
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
390 void menu_6_stopSampling()
391 {
392 samples_counter = num_samples;
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();
405 globaltime_ms = current_millis - start_millis;
406 }
407 else // Calculate elapsed time between current sample and start time
408 {
409 current_millis = millis();
410 globaltime_ms = current_millis - start_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
432 void print_title()
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
448 void print_prompt()
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
menu_4_changeSampleFreq
static void menu_4_changeSampleFreq()
Changes the sampling frequency (ms)
Definition: DC2839A.ino:333
menu_3_changeIGain
static void menu_3_changeIGain()
Select current channel transimpedance gain (V/A)
Definition: DC2839A.ino:311
menu_2_changeVGain
static void menu_2_changeVGain()
Definition: DC2839A.ino:289
current_millis
volatile float current_millis
Number of elapsed milliseconds since the program started running.
Definition: DC2839A.ino:93
user_command
unsigned char user_command
Definition: Serial_EEPROM_Test.ino:75
LTC6115_IIN
#define LTC6115_IIN
Maps to DC2026 J7.1, ADC channel 1.
Definition: LTC6115.h:77
LTC6115ChangeIGain
void LTC6115ChangeIGain(float val)
This function changes the Current gain.
Definition: LTC6115.cpp:162
Linduino.h
Header File for Linduino Libraries and Demo Code.
LTC6115ToVolts
float LTC6115ToVolts(uint32_t val)
This function converts ADC code to Voltage without the converted voltage print statement.
Definition: LTC6115.cpp:128
LTC6115ConvertToVolts
float LTC6115ConvertToVolts(uint32_t val)
This function converts ADC code to Voltage.
Definition: LTC6115.cpp:118
LTC6115_initialize
void LTC6115_initialize()
This function will initialize 6115 variables.
Definition: LTC6115.cpp:92
LTC6115ToAmps
float LTC6115ToAmps(uint32_t val)
This function converts ADC code to Current without the converted current print statement.
Definition: LTC6115.cpp:146
ISR_prompt_flag
volatile int ISR_prompt_flag
Set to 1 to print prompt after interrupt service completes.
Definition: DC2839A.ino:101
update_interval
static int update_interval
Sampling interval(ms) to update to.
Definition: DC2839A.ino:98
globaltime_ms
volatile float globaltime_ms
Number of elapsed milliseconds since menu 4 function is called.
Definition: DC2839A.ino:94
getIGain
float getIGain()
This function returns the current gain (V/A).
Definition: LTC6115.cpp:109
LTC6115_VIN
#define LTC6115_VIN
Pin Mapping.
Definition: LTC6115.h:76
num_samples
volatile int num_samples
Total number of samples that the user desires.
Definition: DC2839A.ino:97
QuikEval_EEPROM.h
QuikEval EEPROM Library.
print_flag
volatile int print_flag
Set to 1 to print sampling data for menu option 4.
Definition: DC2839A.ino:100
LTC6115_GPIO
#define LTC6115_GPIO
Linduino QuikEval GPIO pin (QuikEval connector pin 14) connects to Arduino pin 9. ...
Definition: DC2839A.ino:82
update_compare_reg
static void update_compare_reg(uint32_t regVal)
Updates the compare match register.
Definition: DC2839A.ino:361
discover_demo_board
int8_t discover_demo_board(char *demo_name)
Read the ID string from the EEPROM and determine if the correct board is connected.
Definition: QuikEval_EEPROM.cpp:141
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
millsToHz
uint32_t millsToHz(uint32_t val)
This function converts milliseconds to frequency (Hz).
Definition: LTC6115.cpp:169
print_title
static void print_title()
Prints the title block when program first starts.
Definition: DC2839A.ino:432
loop
static void loop()
Repeats Linduino loop.
Definition: DC2839A.ino:169
ISR_flag
volatile int ISR_flag
Set to 1 when interrupt service routine is running.
Definition: DC2839A.ino:95
LT_I2C.h
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
readI
volatile uint32_t readI
Stores current reading.
Definition: DC2839A.ino:103
demo_name
char demo_name[]
Demo Board Name stored in QuikEval EEPROM.
Definition: DC1880A.ino:97
UserInterface.h
read_int
int32_t read_int()
Definition: UserInterface.cpp:93
getVGain
float getVGain()
This function returns the voltage gain (V/V).
Definition: LTC6115.cpp:100
read_float
float read_float()
Definition: UserInterface.cpp:78
LTC6115ChangeVGain
void LTC6115ChangeVGain(float val)
This function changes the Voltage gain.
Definition: LTC6115.cpp:155
LTC6115.h
LTC6115 High Voltage High Side Current and Voltage Sense.
print_prompt
static void print_prompt()
Prints main menu.
Definition: DC2839A.ino:448
readV
volatile uint32_t readV
Stores voltage reading.
Definition: DC2839A.ino:102
start_millis
volatile float start_millis
Start time when menu 4 function is called.
Definition: DC2839A.ino:92
quikeval_I2C_init
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
samples_counter
volatile int samples_counter
Counts the number of samples taken.
Definition: DC2839A.ino:96
setup
static void setup()
Initialize Linduino.
Definition: DC2839A.ino:107
compare_reg
static int compare_reg
Value to set compare match register to get desired interrupt frequency (Hz)
Definition: DC2839A.ino:99
menu_6_stopSampling
static void menu_6_stopSampling()
Stops the sampling from menu 5.
Definition: DC2839A.ino:390
ISR
ISR(TIMER1_COMPA_vect)
Timer Compare Interrupt Service Routine.
Definition: DC2839A.ino:396
menu_5_pipeToFile
static void menu_5_pipeToFile()
Pipes voltage and current reading results to a file.
Definition: DC2839A.ino:370
menu_1_convert_read
static float menu_1_convert_read()
Read channel.
Definition: DC2839A.ino:253
LTC6115ConvertToAmps
float LTC6115ConvertToAmps(uint32_t val)
This function converts ADC code to Current.
Definition: LTC6115.cpp:137
demo_board_connected
static uint8_t demo_board_connected
Set to 1 if the board is connected.
Definition: _24xx_iso_spi_delay.ino:71