Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
fast_telemetry.ino
Go to the documentation of this file.
1 /*!
2 Linear Technology LTC3887 Telemetry
3 LTC3887: Power Management Solution for Application Processors
4 
5 @verbatim
6 
7 Demonstrates Fast Telemetry
8 
9 NOTES
10  Setup:
11  Set the terminal baud rate to 115200 and select the newline terminator.
12 
13 @endverbatim
14 
15 http://www.linear.com/product/LTC3887
16 
17 
18 Copyright 2018(c) Analog Devices, Inc.
19 
20 All rights reserved.
21 
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions are met:
24  - Redistributions of source code must retain the above copyright
25  notice, this list of conditions and the following disclaimer.
26  - Redistributions in binary form must reproduce the above copyright
27  notice, this list of conditions and the following disclaimer in
28  the documentation and/or other materials provided with the
29  distribution.
30  - Neither the name of Analog Devices, Inc. nor the names of its
31  contributors may be used to endorse or promote products derived
32  from this software without specific prior written permission.
33  - The use of this software may or may not infringe the patent rights
34  of one or more patent holders. This license does not release you
35  from the requirement that you obtain separate licenses from these
36  patent holders to use this software.
37  - Use of the software either in source or binary form, must be run
38  on or directly connected to an Analog Devices Inc. component.
39 
40 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
41 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
42 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
44 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
46 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
49 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51 
52 /*! @file
53  @ingroup LTC3887
54 */
55 
56 #include <Arduino.h>
57 #include <stdint.h>
58 #include "Linduino.h"
59 #include "UserInterface.h"
60 #include "LT_I2CBus.h"
61 #include "LT_SMBusNoPec.h"
62 #include "LT_SMBusPec.h"
63 #include "LT_PMBus.h"
64 
65 #define LTC3887_I2C_ADDRESS 0x4E
66 #define MFR_ADC_CONTROL 0xD8
67 #define ADC_MFR_TELEMETRY_STATUS 0xDA
68 #define MFR_REAL_TIME 0xFB
69 #define NUM_MEAS 10
70 // Global variables
71 static uint8_t ltc3887_i2c_address;
72 static LT_SMBus *smbus = new LT_SMBusNoPec();
73 static LT_PMBus *pmbus = new LT_PMBus(smbus);
74 
75 //! Initialize Linduino
76 //! @return void
77 void setup()
78 {
79  Serial.begin(115200); //! Initialize the serial port to the PC
80  print_title();
82  print_prompt();
83 
84  pmbus->setPage(ltc3887_i2c_address, 0);
85  pmbus->setVout(ltc3887_i2c_address, 5.0);
86  smbus->writeByte(ltc3887_i2c_address, 0xD8, 0x00); // Slow
87 }
88 
89 //! Repeats Linduino loop
90 //! @return void
91 void loop()
92 {
93  uint8_t user_command;
94  uint8_t model[7];
95  uint8_t *addresses = NULL;
96  float voltage0[NUM_MEAS], voltage1[NUM_MEAS];
97  float current0[NUM_MEAS], current1[NUM_MEAS];
98  float meas[NUM_MEAS];
99  uint64_t start_time, current_time;
100  uint64_t max_time = 2^64-1; // Suspect
101  uint16_t voltage0_time[NUM_MEAS], voltage1_time[NUM_MEAS];
102  uint16_t current0_time[NUM_MEAS], current1_time[NUM_MEAS];
103  int i,j;
104  uint8_t b;
105 
106  if (Serial.available()) //! Checks for user input
107  {
108  user_command = read_int(); //! Reads the user command
109  if (user_command != 'm')
110  Serial.println(user_command);
111  uint8_t b;
112 
113  switch (user_command) //! Prints the appropriate submenu
114  {
115  case 0:
116  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x0D); // Fast
117  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0F); // Clear status
118  start_time = micros();
119  for (i = 0; i < NUM_MEAS; i++)
120  {
121  pmbus->setPage(ltc3887_i2c_address, 0);
122  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x01) == 0);
123  current_time = micros();
124  voltage0[i] = pmbus->readVout(ltc3887_i2c_address, false);
125  voltage0_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
126  start_time = current_time;
127  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0E); // Clear remaining status
128  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x02) == 0);
129  current_time = micros();
130  current0[i] = pmbus->readIout(ltc3887_i2c_address, false);
131  current0_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
132  start_time = current_time;
133  pmbus->setPage(ltc3887_i2c_address, 1);
134  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x04) == 0);
135  current_time = micros();
136  voltage1[i] = pmbus->readVout(ltc3887_i2c_address, false);
137  voltage1_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
138  start_time = current_time;
139  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x08) == 0);
140  current_time = micros();
141  current1[i] = pmbus->readIout(ltc3887_i2c_address, false);
142  current1_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
143  start_time = current_time;
144 
145  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0F); // Clear status
146  }
147  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
148  delay(110);
149 
150  for (i = 0; i < NUM_MEAS; i++)
151  {
152  Serial.print(voltage0_time[i]);
153  Serial.print(F("us\t"));
154  Serial.print(voltage0[i]);
155  Serial.print(F("\t"));
156  Serial.print(current0_time[i]);
157  Serial.print(F("us\t"));
158  Serial.print(current0[i]);
159  Serial.print(F("\t"));
160  Serial.print(voltage1_time[i]);
161  Serial.print(F("us\t"));
162  Serial.print(voltage1[i]);
163  Serial.print(F("\t"));
164  Serial.print(current1_time[i]);
165  Serial.print(F("us\t"));
166  Serial.println(current1[i]);
167  }
168  break;
169  case 1:
170  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0F); // Clear status
171  start_time = micros();
172  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x01); // Vin
173  for (i = 0; i < NUM_MEAS; i++)
174  {
175  meas[i] = pmbus->readVin(ltc3887_i2c_address, false);
176  }
177  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
178  delay(110);
179 
180  for (i = 0; i < NUM_MEAS; i++)
181  {
182  Serial.println(meas[i]);
183  }
184  break;
185  case 2:
186  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x05); // Vout0
187  pmbus->setPage(ltc3887_i2c_address, 0);
188 
189  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0F); // Clear status
190  start_time = micros();
191  for (i = 0; i < NUM_MEAS; i++)
192  {
193  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x01) == 0);
194  current_time = micros();
195  voltage0[i] = pmbus->readVout(ltc3887_i2c_address, false);
196  voltage0_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
197  start_time = current_time;
199  }
200  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
201  delay(110);
202 
203  for (i = 0; i < NUM_MEAS; i++)
204  {
205  Serial.print(voltage0_time[i]);
206  Serial.print("us\t");
207  Serial.println(voltage0[i]);
208  }
209  break;
210  case 3:
211  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x09); // Vout1
212  pmbus->setPage(ltc3887_i2c_address, 1);
213 
214  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0F); // Clear status
215  start_time = micros();
216  for (i = 0; i < NUM_MEAS; i++)
217  {
218  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x04) == 0);
219  current_time = micros();
220  voltage1[i] = pmbus->readVout(ltc3887_i2c_address, false);
221  voltage1_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
222  start_time = current_time;
224  }
225  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
226  delay(110);
227 
228  for (i = 0; i < NUM_MEAS; i++)
229  {
230  Serial.print(voltage1_time[i]);
231  Serial.print("us\t");
232  Serial.println(voltage1[i]);
233  }
234  break;
235  case 4:
236  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x06); // Iout0
237  pmbus->setPage(ltc3887_i2c_address, 0);
238 
239  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0F); // Clear status
240  start_time = micros();
241  for (i = 0; i < NUM_MEAS; i++)
242  {
243  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x02) == 0);
244  current_time = micros();
245  current0[i] = pmbus->readIout(ltc3887_i2c_address, false);
246  current0_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
247  start_time = current_time;
249  }
250  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
251  delay(110);
252 
253  for (i = 0; i < NUM_MEAS; i++)
254  {
255  Serial.print(current0_time[i]);
256  Serial.print("us\t");
257  Serial.println(current0[i]);
258  }
259  break;
260  case 5:
261  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x0A); // Iout1
262  pmbus->setPage(ltc3887_i2c_address, 1);
263 
264  smbus->writeByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS, 0x0F); // Clear status
265  start_time = micros();
266  for (i = 0; i < NUM_MEAS; i++)
267  {
268  while ((smbus->readByte(ltc3887_i2c_address, ADC_MFR_TELEMETRY_STATUS) & 0x08) == 0);
269  current_time = micros();
270  current1[i] = pmbus->readIout(ltc3887_i2c_address, false);
271  current1_time[i] = current_time > start_time ? current_time - start_time : max_time - start_time + current_time;
272  start_time = current_time;
274  }
275  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
276  delay(110);
277 
278  for (i = 0; i < NUM_MEAS; i++)
279  {
280  Serial.print(current1_time[i]);
281  Serial.print("us\t");
282  Serial.println(current1[i]);
283  }
284  break;
285  case 6:
286  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x08); // Temp Ext 0
287  pmbus->setPage(ltc3887_i2c_address, 0);
288  for (i = 0; i < NUM_MEAS; i++)
289  {
290  meas[i] = pmbus->readExternalTemperature(ltc3887_i2c_address, false);
291  }
292  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
293 
294  for (i = 0; i < NUM_MEAS; i++)
295  {
296  Serial.println(meas[i]);
297  }
298  break;
299  case 7:
300  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x0C); // Temp Ext 1
301  pmbus->setPage(ltc3887_i2c_address, 1);
302  for (i = 0; i < NUM_MEAS; i++)
303  {
304  meas[i] = pmbus->readExternalTemperature(ltc3887_i2c_address, false);
305  }
306  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
307  delay(110);
308 
309  for (i = 0; i < NUM_MEAS; i++)
310  {
311  Serial.println(meas[i]);
312  }
313  break;
314  case 8:
315  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x04); // Temp Int
316  for (i = 0; i < NUM_MEAS; i++)
317  {
318  meas[i] = pmbus->readInternalTemperature(ltc3887_i2c_address, false);
319  }
320  smbus->writeByte(ltc3887_i2c_address, MFR_ADC_CONTROL, 0x00); // Standard
321  delay(110);
322 
323  for (i = 0; i < NUM_MEAS; i++)
324  {
325  Serial.println(meas[i]);
326  }
327  break;
328  case 9:
329  addresses = smbus->probe(0);
330  while (*addresses != 0)
331  {
332  Serial.print(F("ADDR 0x"));
333  Serial.println(*addresses++, HEX);
334  }
335  break;
336  default:
337  Serial.println("Incorrect Option");
338  break;
339  }
340  print_prompt();
341  }
342 }
343 
344 // Function Definitions
345 
346 //! Prints the title block when program first starts.
347 //! @return void
349 {
350  Serial.print(F("\n***************************************************************\n"));
351  Serial.print(F("* LTC3887 Fast Telemetry Program *\n"));
352  Serial.print(F("* *\n"));
353  Serial.print(F("* This program demonstrates how program fast telemetry *\n"));
354  Serial.print(F("* *\n"));
355  Serial.print(F("* Set the baud rate to 115200 and select the newline terminator.*\n"));
356  Serial.print(F("* *\n"));
357  Serial.print(F("*****************************************************************\n"));
358 }
359 
360 //! Prints main menu.
361 //! @return void
363 {
364  Serial.print(F("\n 0-Loop Fast Out\n"));
365  Serial.print(F(" 1-Loop Fast Vin 0\n"));
366  Serial.print(F(" 2-Loop Fast Vout 0\n"));
367  Serial.print(F(" 3-Loop Fast Vout 1\n"));
368  Serial.print(F(" 4-Loop Fast Iout 0\n"));
369  Serial.print(F(" 5-Loop Fast Iout 1\n"));
370  Serial.print(F(" 6-Loop Fast Temp Ext 0\n"));
371  Serial.print(F(" 7-Loop Fast Temp Ext 1\n"));
372  Serial.print(F(" 8-Loop Fast Temp Int\n"));
373  Serial.print(F(" 9-Bus Probe\n"));
374  Serial.print(F("\nEnter a command:"));
375 }
376 
unsigned char user_command
LTC SMBus Support: Implementation for a shared SMBus layer.
Header File for Linduino Libraries and Demo Code.
float readIout(uint8_t address, bool polling)
Get the measured output current.
Definition: LT_PMBus.cpp:1898
static void print_prompt()
Prints main menu.
static uint8_t ltc3887_i2c_address
float readVout(uint8_t address, bool polling)
Get the measured output voltage.
Definition: LT_PMBus.cpp:1598
LT_I2CBus: Routines to communicate to I2C by Wire Library.
static void setup()
Initialize Linduino.
static void print_title()
Prints the title block when program first starts.
virtual void writeByte(uint8_t address, uint8_t command, uint8_t data)=0
SMBus write byte command.
virtual uint8_t readByte(uint8_t address, uint8_t command)=0
SMBus read byte command.
void setPage(uint8_t address, uint8_t page)
Set the page.
Definition: LT_PMBus.cpp:3156
static void loop()
Repeats Linduino loop.
float readExternalTemperature(uint8_t address, bool polling)
Get the measured external temperature.
Definition: LT_PMBus.cpp:2052
static LT_SMBus * smbus
virtual uint8_t * probe(uint8_t command)=0
SMBus bus probe.
float readInternalTemperature(uint8_t address, bool polling)
Get the measured internal temperature.
Definition: LT_PMBus.cpp:2077
LTC SMBus Support: Implementation for a shared SMBus layer.
int32_t read_int()
float readVin(uint8_t address, bool polling)
Get the input voltage.
Definition: LT_PMBus.cpp:1487
void setVout(uint8_t address, float voltage)
Set output voltage.
Definition: LT_PMBus.cpp:239
static LT_PMBus * pmbus
#define MFR_ADC_CONTROL
LTC PMBus Support.
#define ADC_MFR_TELEMETRY_STATUS
static int i
Definition: DC2430A.ino:184
#define NUM_MEAS
#define LTC3887_I2C_ADDRESS
PMBus communication.
Definition: LT_PMBus.h:370