/* DISPLAYING ACTIVE MEASUREMENT CHANGES OF VACUUM PRESSURE
// file: TFT_Display_ongoing_vacuum_changes_20200828.ino
// FOR TEENSY 4.0 (NOT AUDIO BOARD VERSION) See "connections" chart at https://www.pjrc.com/store/display_ili9341_touch.html for differences in pins
// e: steve.bull@gmail.com
// last edit: 20200819
// Goal: Touch TFT display on Teensy 4.0 to active changes of vacuum pressure
// Assumptions / needs:
// 0) use Teensy 4.0 in final deployment (currently working with Teensy 3.2)
// 1) take pressure readings at 1/second with SparkFunMPL3115A2
// 2) display #1 pressure as a vacuum readings with negative float number in Pascals (Pa)
// 3) display #2 provide a pulsing progress bar as the pressure changes 10 times/minute.
// 3a) Example subject to change: (2 sec vacuum motor on + 4 sec no motor) * 10 cycles = 1 minute
// 3b) Touch TFT display+sensor is remote from the vacuum motor micro-controller
// 4) display #3 average a baseline negative number (the closest to 0) that were read with a 1 minute sampling
// 5) display #4 average greatest vacuum achieved within the same 1 minute sampling as 4)
// 6) put screen asleep after 20 seconds
// 7) wake up screen by simple touch anywhere
// 8) battery power recommendation to keep the display working with intermittent user touches (~15/day) for minimum of 15 days
// 9) need low power warning to support 8) to notify user to change the batteries
// On my own I'll discover how to rotate screen for horizontal display
*/
// about the sensor
#include <Wire.h>
#include "SparkFunMPL3115A2.h"
#include <ILI9341_t3.h>
#include <font_Arial.h> // from ILI9341_t3
#include <XPT2046_Touchscreen.h>
//Create an instance of the object
MPL3115A2 myPressure;
//
const int SDApin = 18; // identify SDA pin (BLUE wire)
const int SCLpin = 19; // identify SCL pin (YELLOW wire)
// about the screen
// VIN = Vin (3.6 tto 5.5 volts)
#define TFT_DC 9
#define TFT_CS 10
#define TFT_RST 255 // 255 = unused, connect to 3.3V
#define TFT_MOSI 11
#define TFT_SCLK 13
#define TFT_MISO 12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
//T_CLK 13
//T_CS 8
//T_DIN 11
//T_DO 12
//T_IRQ 2
//////////////////////MISSING DEFINES //////////////////////////////////////////
uint32_t g_tft_backlight_timer; // When was the last time the touch screen was touched.
uint16_t g_backlight_value = 0; // what is the current backlight 0-255
// Note: Dim 0-255 where 0 is full on and 255 full off
#define TFT_DIM_INTERVAL_MILLIS 10000 // How fast to dim
#define TFT_DIM_AMOUNT 16 // How much to dim
#define TFT_DIM_MIN 0 // Full On....
#define TFT_DIM_MAX (256-16) // MAX value
#define TFT_BACKLIGHT 6
#define TFT_TCS 8 // SPI Touch CS
#define TFT_TIRQ 3 // Touch screen IRQ pin
XPT2046_Touchscreen ts(TFT_TCS, TFT_TIRQ);
//====================================================================================
// Touch screen calibrations.
//====================================================================================
// This is calibration data for the raw touch data to the screen coordinates
// Warning, These are WIP
#define SCREEN_ORIENTATION_1
#define TS_MINX 260
#define TS_MINY 350
#define TS_MAXX 3825
#define TS_MAXY 3825
// Note: Dim 0-255 where 0 is full on and 255 full off
#define TFT_DIM_INTERVAL_MILLIS 10000 // How fast to dim
#define TFT_DIM_AMOUNT 16 // How much to dim
#define TFT_DIM_MIN 0 // Full On....
#define TFT_DIM_MAX (256-16) // MAX value
void setup() {
// set up for pressure sensor
pinMode(SDApin, SDA); // set pin to SDA mode
pinMode(SCLpin, SCL);// set pin to SCL mode
//
Wire.begin(); // Join i2c bus for pressure sensor
Serial.begin(9600);
// Get sensor online
myPressure.begin();
//Configure sensor
//myPressure.setModeAltimeter(); // Measure altitude above sea level in meters
myPressure.setModeBarometer(); // Measure pressure in Pascals from 20 to 110 kPa
myPressure.setOversampleRate(7); // Set Oversample to the recommended 128
myPressure.enableEventFlags(); // Enable all three pressure and temp event flags
// setup for touch sensor screen
tft.begin();
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setFont(Arial_14);
tft.setCursor(36, 8);
tft.println("breathe.global"); // branding
tft.setCursor(36, 30);
tft.println("CUIRASS VACUUM"); // identify purpose of screen
tft.setCursor(36, 52);
tft.setFont(Arial_12);
tft.println("Touch screen to wakeup"); // user interface info
if (!ts.begin()) {
Serial.println("Couldn't start touchscreen controller");
}
}
//====================================================================================
// SetFullTFTBacklight - Turn to max brightness... May change later...
//====================================================================================
void SetFullTFTBacklight()
{
if (g_backlight_value != TFT_DIM_MIN) {
g_backlight_value = TFT_DIM_MIN;
analogWrite(TFT_BACKLIGHT, g_backlight_value);
}
g_tft_backlight_timer = millis(); // remember last time touched.
}
//====================================================================================
// GetTouchPoint - Return true if touched and convert touch point to X and Y values
//====================================================================================
TS_Point g_pt; // currently global for debug stuff
bool GetTouchPoint(int16_t *px, int16_t *py)
{
if (!ts.touched()) // only process when touched. empty is just a timer...
return false;
g_pt = ts.getPoint();
// Scale from ~0->4000 to tft.width using the calibration #'s
#ifdef SCREEN_ORIENTATION_1
*px = map(g_pt.x, TS_MINX, TS_MAXX, 0, tft.width());
*py = map(g_pt.y, TS_MINY, TS_MAXY, 0, tft.height());
#else
*px = map(g_pt.x, TS_MINX, TS_MAXX, tft.width(), 0);
*py = map(g_pt.y, TS_MAXY, TS_MINY, 0, tft.height());
#endif
return true;
}
//====================================================================================
// ProcessTouchScreen - Process input from Touch Screen.
//====================================================================================
bool ProcessTouchScreen()
{
if (!ts.touched()) { // only process when touched. empty is just a timer...
if ((g_backlight_value < TFT_DIM_MAX) && (millis() - g_tft_backlight_timer) >= TFT_DIM_INTERVAL_MILLIS) {
g_backlight_value += TFT_DIM_AMOUNT;
if ( g_backlight_value > TFT_DIM_MAX) g_backlight_value = TFT_DIM_MAX;
analogWrite(TFT_BACKLIGHT, g_backlight_value);
g_tft_backlight_timer = millis();
}
return false;
}
SetFullTFTBacklight(); // Make sure it is on...
int16_t x, y, x_prev = 0xffff, y_prev = 0xffff;
while (GetTouchPoint(&x, &y)) {
if ((x != x_prev) || (y != y_prev)) {
x_prev = x;
y_prev = y;
}
}
g_tft_backlight_timer = millis(); // remember last time touched.
return true;
}
// elapsedMillis msecs; // I've a feeling this might be useful later
void loop() {
ProcessTouchScreen();
/**** I GOT THIS WORKING ****/
/** Q: what is the most efficient way to set the pressure delivery update 1/sec?" **/
float pressure = myPressure.readPressure();
Serial.print("Pressure(Pa): ");
Serial.print(pressure, 2);
Serial.println();
/**** GOT THIS WORKING ****/
tft.setFont(Arial_14);
tft.fillRect(10, 80, 240, 16, ILI9341_BLACK);
tft.setCursor(10, 80);
tft.print("Pressure(Pa):");
tft.setCursor(140, 80);
tft.print(pressure);
delay(1000); // my newbie attempt to take readings every second
/*** BELOW: portion of code lifted from tutorial associated Part_3_03_TFT_Display.ino
that I was noodling - thank you Paul
***/
/* if (msecs > 145) {
if (peak1.available() && peak2.available()) {
msecs = 0;
float leftNumber = peak1.read();
float rightNumber = peak2.read();
Serial.print(leftNumber);
Serial.print(", ");
Serial.print(rightNumber);
Serial.println();
// draw the verticle bars
// int height = leftNumber * 240;
int height = leftNumber * 40;
tft.fillRect(60, 280 - height, 40, height, ILI9341_GREEN);
tft.fillRect(60, 280 - 240, 40, 240 - height, ILI9341_BLACK);
height = rightNumber * 240;
tft.fillRect(140, 280 - height, 40, height, ILI9341_GREEN);
tft.fillRect(140, 280 - 240, 40, 240 - height, ILI9341_BLACK);
// a smarter approach would redraw only the changed portion...
// draw numbers underneath each bar
tft.setFont(Arial_14);
tft.fillRect(60, 284, 40, 16, ILI9341_BLACK);
tft.setCursor(60, 284);
//tft.print(leftNumber);
tft.print(leftNote);
tft.fillRect(140, 284, 40, 16, ILI9341_BLACK);
tft.setCursor(140, 284);
//tft.print(rightNumber);
tft.print(rightNote);
}
}
// draw the verticle bars
// int height = leftNumber * 240;
int height = leftNumber * 40;
tft.fillRect(60, 280 - height, 40, height, ILI9341_GREEN);
tft.fillRect(60, 280 - 240, 40, 240 - height, ILI9341_BLACK);
height = rightNumber * 240;
tft.fillRect(140, 280 - height, 40, height, ILI9341_GREEN);
tft.fillRect(140, 280 - 240, 40, 240 - height, ILI9341_BLACK);
// a smarter approach would redraw only the changed portion...
*/
}