Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
EasySMU_IOpanel.cpp
Go to the documentation of this file.
1 /*!
2 EasySMU_IOpanel Library to Enable Touchscreen Control of EasySMU
3 
4 [User Guide](http://www.linear.com/docs/58670 "EasySMU User Guide") \n
5 [Schematic](http://www.linear.com/docs/58671 "Schematic") \n
6 [Top-Level Linduino Firmware for EasySMU](file:EasySMU__Run_8ino.html "Top-Level Linduino Firmware for EasySMU") \n
7 [EasySMU Class Reference](file:classEasySMU.html "EasySMU Class Reference") \n
8 [EasySMU_IOpanel Class Reference](file:classEasySMU__IOpanel.html "EasySMU_IOpanel Class Reference") \n
9 [EasySMU Webpage](http://www.linear.com/solutions/7943 "EasySMU Webpage") \n
10 
11 @verbatim
12 
13 EasySMU: I2C Address Translator Demonstration and a Simple Multi-Channel Source Measurement Unit
14 
15 LTC4316: Single I2C/SMBus Address Translator
16 LT1970A: Power Op Amp with Adjustable Precision Current Limit
17 LT5400: Quad Matched Resistor Network
18 LTC2655: Quad I2C 16-/12-Bit Rail-to-Rail DACs with 10ppm/°C Max Reference
19 LTC3265: Low Noise Dual Supply with Boost and Inverting Charge Pumps
20 LTC2051: Dual Zero-Drift Operational Amplifier
21 LT3010: 50mA, 3V to 80V Low Dropout Micropower Linear Regulator
22 LT1991: Precision, 100µA Gain Selectable Amplifier
23 LTC6655: 0.25ppm Noise, Low Drift Precision Reference
24 LTC2485: 24-Bit ΔΣ ADC with Easy Drive Input Current Cancellation and I2C Interface
25 
26 EasySMU is a single-channel ±12V/40mA programmable-voltage/programmable-current
27 source with accurate voltage/current measurement capability. The LTC4316 I2C
28 Address Translator enables up to eight independent EasySMUs to be controlled
29 by a single I2C master.
30 
31 In this demonstration, each EasySMU board contains four I2C slaves and the
32 associated components to implement a single-channel ±12V/40mA programmable-
33 voltage/programmable-current source. The LTC4316 translates the I2C addresses
34 of each EasySMU to a unique set of addresses, enabling up to eight EasySMU
35 boards to be stacked on a single Linduino (I2C master). In this form, it
36 resembles a multi-channel automated test system. Alternatively, an optional
37 touchscreen allows the user to interactively control up to four channels,
38 forming a compact multi-channel programmable-voltage/programmable-current
39 bench source for lab testing, powered from a single 12V AC wall adapter.
40 
41 The primary purpose of the EasySMU is to demonstrate the LTC4316 I2C Address
42 Translator. The programmable-voltage/programmable-current source and meter
43 also provide a convenient demonstration of the associated components: LT1970A,
44 LT5400-3, LTC2655-H, LTC3265, LTC2051, LT3010, LT1991, LTC6655, and LTC2485.
45 While the EasySMU is not designed to demonstrate the ultimate performance that
46 can be obtained from each of those components, the EasySMU does provide
47 impressive results from a reasonably simple circuit.
48 
49 @endverbatim
50 
51 
52 Copyright 2018(c) Analog Devices, Inc.
53 
54 All rights reserved.
55 
56 Redistribution and use in source and binary forms, with or without
57 modification, are permitted provided that the following conditions are met:
58  - Redistributions of source code must retain the above copyright
59  notice, this list of conditions and the following disclaimer.
60  - Redistributions in binary form must reproduce the above copyright
61  notice, this list of conditions and the following disclaimer in
62  the documentation and/or other materials provided with the
63  distribution.
64  - Neither the name of Analog Devices, Inc. nor the names of its
65  contributors may be used to endorse or promote products derived
66  from this software without specific prior written permission.
67  - The use of this software may or may not infringe the patent rights
68  of one or more patent holders. This license does not release you
69  from the requirement that you obtain separate licenses from these
70  patent holders to use this software.
71  - Use of the software either in source or binary form, must be run
72  on or directly connected to an Analog Devices Inc. component.
73 
74 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
75 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
76 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
77 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
78 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
79 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
80 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
81 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
82 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
83 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
84 */
85 
86 /*! @file
87  @ingroup EasySMU
88  EasySMU_IOpanel Library to Enable Touchscreen Control of EasySMU
89 */
90 
91 #include <Adafruit_ILI9341.h>
92 #include <Adafruit_GFX.h>
93 #include "EasySMU_IOpanel.h"
94 #include <Anonymous_Pro6pt7b.h>
96 
97 #ifdef ADAFRUIT_TFT_TOUCHSHIELD_1947
98 #include <Adafruit_FT6206.h>
99 #endif
100 
101 //#include guard not implemented properly in SeeedTouchScreen.h so it was not included here.
102 //#ifdef SEEEDSTUDIO_TFT_TOUCHSHIELD_V2
103 //#include <SeeedTouchScreen.h>
104 //#endif
105 
107 {
110  //init Display
111  lcd.begin();
112  lcd.setRotation(1);
113 
114  //init Touch-Controller
115 #ifdef ADAFRUIT_TFT_TOUCHSHIELD_1947
116  if (! touchp.begin(40)) // pass in 'sensitivity' coefficient
117  {
118  enabled_ = 0;
119  Serial.println("No touchscreen present.");
120  return;
121  }
122 
123 #endif // ADAFRUIT_TFT_TOUCHSHIELD_1947
124 
125  enabled_ = 1;
126 
128 
129  int16_t lcdWidth, lcdHeight;
130 
131  lcdWidth=lcd.width();
132 
133  lcdHeight=lcd.height();
134 
140  lcd.setFont(&Anonymous_Pro6pt7b);
141 
142  DisplaySMULabel();
143 
152 
154  lcd.setFont(&Anonymous_Pro_B14pt7b);
155 
157  lcd.print("V+");
159  lcd.print("V-");
161  lcd.print("I+");
163  lcd.print("I-");
165  lcd.print("V++");
167  lcd.print("V--");
169  lcd.print("I++");
171  lcd.print("I--");
172 
173  lcd.setFont(&Anonymous_Pro6pt7b);
174 
175 }
176 
178 {
179  int16_t x, y;
180 
181  int16_t previous_button_pressed=button_pressed_;
183  if (enabled_==0)
184  {
185  return (button_pressed_);
186  }
187 #ifdef ADAFRUIT_TFT_TOUCHSHIELD_1947
188  if (touchp.touched())
189 #endif // ADAFRUIT_TFT_TOUCHSHIELD_1947
190 
191 #ifdef SEEEDSTUDIO_TFT_TOUCHSHIELD_V2
192  if (touchp.isTouching())
193 #endif // SEEEDSTUDIO_TFT_TOUCHSHIELD_V2
194  {
195 #ifdef ADAFRUIT_TFT_TOUCHSHIELD_1947
196  TS_Point p = touchp.getPoint();
197  y = map(p.x, 0, 240, 0, 240);
198  x = map(p.y, 0, 320, 320, 0);
199 #endif // ADAFRUIT_TFT_TOUCHSHIELD_1947
200 
201 #ifdef SEEEDSTUDIO_TFT_TOUCHSHIELD_V2
202  Point p = touchp.getPoint();
203  y = map(p.x, 1700, 300, 0, 240);
204  x = map(p.y, 1800, 200, 320, 0);
205 #endif // SEEEDSTUDIO_TFT_TOUCHSHIELD_V2
206 
207 
208  /* Serial.print("pX:");
209  Serial.print(p.x);
210  Serial.print(" pY:");
211  Serial.print(p.y);
212  Serial.print(" pZ:");
213  Serial.println(p.z);
214  Serial.print("X:");
215  Serial.print(x);
216  Serial.print(" Y:");
217  Serial.println(y);*/
218 
219  if ((x >= _SMU0_LEFT) && (x <= _SMU0_RIGHT) && (y >= _SMU0_TOP) && (y <= _SMU0_BOTTOM))
220  {
222  }
223  else if ((x >= _SMU1_LEFT) && (x <= _SMU1_RIGHT) && (y >= _SMU1_TOP) && (y <= _SMU1_BOTTOM))
224  {
226  }
227  else if ((x >= _SMU2_LEFT) && (x <= _SMU2_RIGHT) && (y >= _SMU2_TOP) && (y <= _SMU2_BOTTOM))
228  {
230  }
231  else if ((x >= _SMU3_LEFT) && (x <= _SMU3_RIGHT) && (y >= _SMU3_TOP) && (y <= _SMU3_BOTTOM))
232  {
234  }
235  else if ((x >= _VPLUS_LEFT) && (x <= _VPLUS_RIGHT) && (y >= _VPLUS_TOP) && (y <= _VPLUS_BOTTOM))
236  {
238  }
239  else if ((x >= _VMINUS_LEFT) && (x <= _VMINUS_RIGHT) && (y >= _VMINUS_TOP) && (y <= _VMINUS_BOTTOM))
240  {
242  }
243  else if ((x >= _IPLUS_LEFT) && (x <= _IPLUS_RIGHT) && (y >= _IPLUS_TOP) && (y <= _IPLUS_BOTTOM))
244  {
246  }
247  else if ((x >= _IMINUS_LEFT) && (x <= _IMINUS_RIGHT) && (y >= _IMINUS_TOP) && (y <= _IMINUS_BOTTOM))
248  {
250  }
251  else if ((x >= _VPLUSPLUS_LEFT) && (x <= _VPLUSPLUS_RIGHT) && (y >= _VPLUSPLUS_TOP) && (y <= _VPLUSPLUS_BOTTOM))
252  {
254  }
255  else if ((x >= _VMINUSMINUS_LEFT) && (x <= _VMINUSMINUS_RIGHT) && (y >= _VMINUSMINUS_TOP) && (y <= _VMINUSMINUS_BOTTOM))
256  {
258  }
259  else if ((x >= _IPLUSPLUS_LEFT) && (x <= _IPLUSPLUS_RIGHT) && (y >= _IPLUSPLUS_TOP) && (y <= _IPLUSPLUS_BOTTOM))
260  {
262  }
263  else if ((x >= _IMINUSMINUS_LEFT) && (x <= _IMINUSMINUS_RIGHT) && (y >= _IMINUSMINUS_TOP) && (y <= _IMINUSMINUS_BOTTOM))
264  {
266  }
267 
268  }
269 
270  if (button_pressed_!=previous_button_pressed) start_button_pressed_=millis();
273  {
275  DisplaySMULabel();
276  }
277  return button_pressed_;
278 }
279 
281 {
282  if (enabled_== 0) return;
285  lcd.print("CH0");
288  lcd.print("CH1");
291  lcd.print("CH2");
294  lcd.print("CH3");
295  lcd.setTextColor(ILI9341_WHITE,ILI9341_BLUE);
296 }
297 
298 void EasySMU_IOpanel::OverwriteOldString(uint16_t fg_color, uint16_t bg_color, char *old_string, const char *new_string)
299 {
300  //lcd.setCursor(x, y);
301  if (enabled_== 0) return;
302  uint16_t new_x, new_y;
303  for (int8_t i=0; (i < 16) && (old_string[i] != '\0') && (new_string[i] != '\0'); i++)
304  {
305 
306  new_x=lcd.getCursorX();
307  new_y=lcd.getCursorY();
308 
309  lcd.setTextColor(bg_color,bg_color);
310  lcd.print(old_string[i]);
311 
312  lcd.setCursor(new_x, new_y);
313  lcd.setTextColor(fg_color,bg_color);
314  lcd.print(new_string[i]);
315  }
316 }
317 
318 void EasySMU_IOpanel::DisplayVoltageSourceSetting(int16_t channel, float flt_old, float flt_new)
319 {
320 
321  if (enabled_== 0) return;
322  switch (channel)
323  {
324  case _CH0:
326  break;
327  case _CH1:
329  break;
330  case _CH2:
332  break;
333  case _CH3:
335  break;
336  }
337 
338  char str_old[16], str_new[16];
339  dtostrf(flt_old,8,4,str_old);
340  strcat(str_old,"V");
341  dtostrf(flt_new,8,4,str_new);
342  strcat(str_new,"V");
343  OverwriteOldString(ILI9341_WHITE,ILI9341_BLUE,str_old,str_new);
344 
345 
346 }
347 
348 void EasySMU_IOpanel::DisplayMeasuredVoltage(int16_t channel, float flt_old, float flt_new)
349 {
350  if (enabled_== 0) return;
351 
352  switch (channel)
353  {
354  case _CH0:
356  break;
357  case _CH1:
359  break;
360  case _CH2:
362  break;
363  case _CH3:
365  break;
366  }
367  char str_old[16], str_new[16];
368  dtostrf(flt_old,8,4,str_old);
369  strcat(str_old,"V");
370  dtostrf(flt_new,8,4,str_new);
371  strcat(str_new,"V");
372  OverwriteOldString(ILI9341_WHITE,ILI9341_BLUE,str_old,str_new);
373 
374 }
375 
376 void EasySMU_IOpanel::DisplayTemperatureOfIadc(int16_t channel, float flt_old, float flt_new)
377 {
378  if (enabled_== 0) return;
379  switch (channel)
380  {
381  case _CH0:
383  break;
384  case _CH1:
386  break;
387  case _CH2:
389  break;
390  case _CH3:
392  break;
393  }
394  char str_old[16], str_new[16];
395  dtostrf(flt_old,3,1,str_old);
396  strcat(str_old,"C");
397  dtostrf(flt_new,3,1,str_new);
398  strcat(str_new,"C");
399  OverwriteOldString(ILI9341_WHITE,ILI9341_BLUE,str_old,str_new);
400 
401 }
402 
403 void EasySMU_IOpanel::DisplayTemperatureOfVadc(int16_t channel, float flt_old, float flt_new)
404 {
405  if (enabled_== 0) return;
406  switch (channel)
407  {
408  case _CH0:
410  break;
411  case _CH1:
413  break;
414  case _CH2:
416  break;
417  case _CH3:
419  break;
420  }
421  char str_old[16], str_new[16];
422  dtostrf(flt_old,3,1,str_old);
423  strcat(str_old,"C");
424  dtostrf(flt_new,3,1,str_new);
425  strcat(str_new,"C");
426  OverwriteOldString(ILI9341_WHITE,ILI9341_BLUE,str_old,str_new);
427 
428 }
429 
430 void EasySMU_IOpanel::AddLeadingSign(char chrSign, char *string,int8_t strlen)
431 {
432  int8_t i;
433  for (i=0; (i<strlen) && (string[i+1]==' '); i++);
434  if (string[i]==' ')
435  {
436  string[i]=chrSign;
437  }
438 }
439 
440 void EasySMU_IOpanel::DisplayCurrentSourceSetting(int16_t channel, float flt_old, float flt_new, int8_t source_both_sink)
441 {
442  if (enabled_== 0) return;
443  switch (channel)
444  {
445  case _CH0:
447  break;
448  case _CH1:
450  break;
451  case _CH2:
453  break;
454  case _CH3:
456  break;
457  }
458  char str_old[16], str_new[16];
459  dtostrf(flt_old*1000,7,3,str_old);
460  strcat(str_old,"mA");
461  AddLeadingSign('+',str_old,16);
462  dtostrf(flt_new*1000,7,3,str_new);
463  strcat(str_new,"mA");
464  if (source_both_sink==_SOURCE_ONLY)
465  {
466  AddLeadingSign('+',str_new,16);
467  }
468  else if (source_both_sink==_SINK_ONLY)
469  {
470  AddLeadingSign('-',str_new,16);
471  }
472  OverwriteOldString(ILI9341_WHITE,ILI9341_BLUE,str_old,str_new);
473 }
474 
475 void EasySMU_IOpanel::DisplayMeasuredCurrent(int16_t channel, float flt_old, float flt_new)
476 {
477  if (enabled_== 0) return;
478  switch (channel)
479  {
480  case _CH0:
482  break;
483  case _CH1:
485  break;
486  case _CH2:
488  break;
489  case _CH3:
491  break;
492  }
493  char str_old[16], str_new[16];
494  dtostrf(flt_old*1000,7,3,str_old);
495  strcat(str_old,"mA");
496  dtostrf(flt_new*1000,7,3,str_new);
497  strcat(str_new,"mA");
498  OverwriteOldString(ILI9341_WHITE,ILI9341_BLUE,str_old,str_new);
499 }
500 
void DisplayTemperatureOfVadc(int16_t channel, float flt_old, float flt_new)
Draw the measured temperature from the voltage ADC. Presently, not used as it clutters up the screen...
#define _BUTTON_WIDTH
#define _VMINUSMINUS_LEFT
#define _IMINUS_BOTTOM
int16_t x
#define _SINK_ONLY
Definition: EasySMU.h:113
#define _SMU1_RIGHT
#define _SMU2_BOTTOM
int SMUselected_
stores which SMU channel is selected on the TFT display
int16_t height(void) const
#define _IPLUSPLUS_BOTTOM
#define _SMU0_TOP
#define _IMINUS_TOP
void setFont(const GFXfont *f=NULL)
#define _TEXT_TOP
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color)
int16_t getCursorY(void) const
#define _VPLUS_RIGHT
void setCursor(int16_t x, int16_t y)
#define _SMU2_LEFT
#define _SMU3_LEFT
void DisplayMeasuredVoltage(int16_t channel, float flt_old, float flt_new)
Draw the measured voltage for a single channel.
int16_t width(void) const
#define _SMU_TEXT_LEFT
static uint8_t channel
LTC2305 Channel selection.
Definition: DC1444A.ino:127
#define _VPLUSPLUS_TOP
int CheckButton()
check if a button is pressed
#define _IMINUS_LEFT
#define ILI9341_WHITE
uint32_t start_button_pressed_
keep track of when the button was pressed to later calculate the duration it has been held ...
int16_t getCursorX(void) const
#define _VPLUS_TOP
#define _VMINUS_LEFT
void DisplayMeasuredCurrent(int16_t channel, float flt_old, float flt_new)
Draw the measured current for a single channel.
#define _BUTTON_HEIGHT
void DisplaySMULabel()
Draw the SMU labels. The selected channel will be green.
int16_t y
#define _CH0
Definition: EasySMU.h:72
#define _IMINUSMINUS_LEFT
#define _BUTTON_TEXT_PLUSPLUS_LEFT
#define _IPLUSPLUS_TOP
#define _IPLUSPLUS_LEFT
#define _SMU1_BOTTOM
void DisplayVoltageSourceSetting(int16_t channel, float flt_old, float flt_new)
Draw the voltage source setting for a single channel.
#define _IPLUSPLUS_RIGHT
#define _SMU_HEIGHT
#define _VMINUSMINUS_BOTTOM
#define _SMU0_BOTTOM
#define _SMU3_TOP
void setTextColor(uint16_t c)
#define _IPLUS_BOTTOM
#define _TEXT_TOP_MID
boolean begin(uint8_t thresh=FT6206_DEFAULT_THRESSHOLD)
Setups the HW.
void setRotation(uint8_t r)
#define _BUTTON_RADIUS
void DisplayTemperatureOfIadc(int16_t channel, float flt_old, float flt_new)
Draw the measured temperature from the current ADC. Presently, not used as it clutters up the screen...
#define _BUTTON_TEXT_TOP
#define _TEXT_LEFT_MID
Adafruit_FT6206 touchp
#define _IPLUS_TOP
uint8_t enabled_
indicates if the TFT is enabled.
#define ILI9341_BLUE
#define _IPLUS_LEFT
#define _CH1
Definition: EasySMU.h:73
#define _IPLUS_RIGHT
#define ILI9341_GREEN
#define _VMINUS_RIGHT
void Init()
Initialize the IO panel, including drawing buttons, etc.
#define _VPLUSPLUS_RIGHT
#define _SMU_TEXT_TOP
#define _VPLUS_LEFT
#define _SOURCE_ONLY
Definition: EasySMU.h:111
#define _SMU1_TOP
uint32_t duration_button_pressed_
stores a value corresponding to how long the button has been pressed
void fillScreen(uint16_t color)
#define _SMU1_LEFT
#define _TEXT_LEFT
TS_Point getPoint(void)
#define _IMINUSMINUS_BOTTOM
#define _VPLUSPLUS_LEFT
#define _VMINUSMINUS_TOP
#define _SMU2_RIGHT
int button_pressed_
stores the value of the button pressed (from enum)
void DisplayCurrentSourceSetting(int16_t channel, float flt_old, float flt_new, int8_t source_both_sink)
Draw the current source setting for a single channel.
#define _VMINUSMINUS_RIGHT
#define _VPLUS_BOTTOM
static int i
Definition: DC2430A.ino:184
#define _VPLUSPLUS_BOTTOM
#define _VMINUS_BOTTOM
#define _SMU2_TOP
#define _IMINUS_RIGHT
#define _SMU0_RIGHT
#define _VMINUS_TOP
#define _SMU3_BOTTOM
#define _IMINUSMINUS_TOP
Adafruit_ILI9341 lcd
#define _CH2
Definition: EasySMU.h:74
boolean touched(void)
#define _BUTTON_TEXT_LEFT
Header File for EasySMU_IOpanel Library That Enables Touchscreen Control of EasySMU.
#define _SMU3_RIGHT
#define _IMINUSMINUS_RIGHT
#define _SMU0_LEFT
#define _CH3
Definition: EasySMU.h:75
#define _SMU_WIDTH