Toggle control from a touch screen button

I'm making a bike speedometer using a UNO, a NEO-6M GPS and a Adafruit 3.5 TFT display. I have most of it working including a way to log my position as I ride in a CSV file to the SD card that is on the display. Right now the logging starts as soon as I power the UNO up.

I'd like to be able to start and stop the logging using a button on the display. I want to toggle it on and off with the same button. I've tried to use the examples I have found that use a hardware pushbutton but obviously I can't get it to work or I wouldn't be here asking for help. Right now I'm just trying to work out the toggle function and turn a LED on and off.

Here's the code I have to toggle the LED


// Start/Stop logging file with Log PB
if ((p.x>=725) && (p.x<=890) && (p.y>=810) && (p.y<=890)) {
   if(RunLogger == 0){
    RunLogger = 1;
    delay(500);
  } // end RunLogger == 0
}
if ((p.x>=725) && (p.x<=890) && (p.y>=810) && (p.y<=890)) {
   if(RunLogger == 1){
    RunLogger = 0;
    delay(500);
  } // end RunLogger == 1
 
} // end Start/Stop logging

Serial.print("logger = ");
Serial.println(RunLogger);

if(RunLogger == 0){
   digitalWrite(recLED, LOW);
}
else {
   digitalWrite(recLED, HIGH);
}

And here is the main part of the code, I have the logging function on another tab but didn't think that would be useful. If you think it is I will send it on a later reply

/*
  Changed to Uno
  with Adafruit 3.5 TFT display
  Rev 6 Added touch, made 2 pages for displaing info and separated logging to it's own tab
  
  GPS Position Logger
  code from
  DroneBot Workshop 2021
  https://dronebotworkshop.com
*/

// Include required libraries
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>         // Core graphics library
#include <Adafruit_HX8357.h>      // Hardware-specific library
#include "TouchScreen.h"


// GPS Connections
static const int RXPin = 6, TXPin = 7;

// GPS Baud rate (change if required)
static const uint32_t GPSBaud = 9600;

// SD Card Select pin
const int chipSelect = 5;

// Write LED
const int recLED = 8;

// String to hold GPS data
String gpstext;

// GPS write delay counter variables
// Change gpsttlcount as required
int gpscount = 0;
int gpsttlcount = 30;
int fileMade = 0; // check to see if a new file was made on SD card

// TinyGPS++ object
TinyGPSPlus gps;

// SoftwareSerial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

// display
#define TFT_CS   10
#define TFT_DC   9
Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC);

// These are the four touchscreen analog pins
#define YP A2  // must be an analog pin, use "An" notation!
#define XM A3  // must be an analog pin, use "An" notation!
#define YM 3   // can be a digital pin
#define XP 4   // can be a digital pin

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 110
#define TS_MINY 80
#define TS_MAXX 900
#define TS_MAXY 940

#define MINPRESSURE 10
#define MAXPRESSURE 1000

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// Color definitions
#define BLACK    0x0000
#define BLUE     0x001F
#define RED      0xF800
#define GREEN    0x07E0
#define CYAN     0x07FF
#define MAGENTA  0xF81F
#define YELLOW   0xFFE0 
#define WHITE    0xFFFF

bool newData = false;
float distance = 0.0;
unsigned long int scan_time = millis();
int currentPage = 1;
int SD_Status = 0;
int GPS_Status = 0;
float Heading = 0.0;
String RideTime = "";
int RideHr = 0;
int RideMin = 0;
int RideSec = 0;
int StartHr = 0;
int StartMin = 0;
int StartSec = 0;
int readStartTime = 0;
char RideTm[80];

// the logging file
File logfile;
char logFileName[20] = " "; // current log file name
int errorNumb = 0; // system error number to display message
int RunLogger = 0; // run logging file

void setup()
{

    // Set all chip selects high to avoid bus contention during initialisation of each peripheral
 // digitalWrite(21, HIGH); // Touch controller chip select (if used)
  digitalWrite(10, HIGH); // TFT screen chip select
  digitalWrite( 5, HIGH); // SD card chips select, must use GPIO 5 (ESP32 SS)
  
  // Set LED pin as output
  pinMode(recLED, OUTPUT);

  // Start Serial Monitor for debugging
  Serial.begin(115200);

  // Start SoftwareSerial
  ss.begin(GPSBaud);

  // start display driver
  tft.begin();          // Initialize screen
  //tft.fillScreen(BLACK); //clears screen, sets to Black
  tft.setRotation(0);  // rotates screen 90' for landscape mode
 
  // Prints the title on the screen
 // tft.setCursor(65, 20);
 // tft.setTextColor(WHITE);
 // tft.setTextSize(3);
 // tft.print("GPS Status"); 

  // Draws the red line under the title
//  tft.drawFastHLine(10, 60, 320, RED);

// load Speedometer page
  tft.fillScreen(BLACK); //clears screen, sets to Black
  SpeedometerPage();

  // Initialize SD card
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    //don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");



  // Blink LED so we know we are ready
  digitalWrite(recLED, HIGH);
  delay(500);
  digitalWrite(recLED, LOW);
  delay(500);
  digitalWrite(recLED, HIGH);
  delay(500);
  digitalWrite(recLED, LOW);
  delay(500);
  digitalWrite(recLED, HIGH);
  delay(500);
  digitalWrite(recLED, LOW);

scan_time = millis(); // reset scan time




} // end setup

void loop()
{

  // Turn off LED
  digitalWrite(recLED, LOW);
  
  // Retrieve a point on touch screen
  TSPoint p = ts.getPoint();
  // See if GPS data available
  while (ss.available() > 0)
    if (gps.encode(ss.read()))




//Heading = (gps.course.deg(), gps.course.isValid(), 7, 2);

// If we press the Speedometer Button 
  if ((p.x>=130) && (p.x<=290) && (p.y>=810) && (p.y<=890)) {
    currentPage = 1; // Indicates that we are the first example
    tft.fillScreen(BLACK); //clears screen, sets to Black
    Serial.println("Speed pressed");
    SpeedometerPage(); // It is called only once, because in the next iteration of the loop, this above if statement will be false so this funtion won't be called. This function will draw the graphics of the first example.
  
  } // end if for Speedometer button pressed


// If we press the GPS Info Button 
  if ((p.x>=420) && (p.x<=600) && (p.y>=810) && (p.y<=890)) {
    currentPage = 2;
    tft.fillScreen(BLACK); //clears screen, sets to Black
    Serial.println("GPS Pressed");
    GPS_Info_Page();
  } // end if for GPS Info page  

// Start/Stop logging file with Log PB
if ((p.x>=725) && (p.x<=890) && (p.y>=810) && (p.y<=890)) {
   if(RunLogger == 0){
    RunLogger = 1;
    delay(500);
  } // end RunLogger == 0
}
if ((p.x>=725) && (p.x<=890) && (p.y>=810) && (p.y<=890)) {
   if(RunLogger == 1){
    RunLogger = 0;
    delay(500);
  } // end RunLogger == 1
 
} // end Start/Stop logging

Serial.print("logger = ");
Serial.println(RunLogger);

if(RunLogger == 0){
   digitalWrite(recLED, LOW);
}
else {
   digitalWrite(recLED, HIGH);
}
// Update variables

// display GPS and SD card status
if(GPS_Status == 1){
  tft.fillCircle(290, 30, 10, GREEN);
}
if(GPS_Status == 0) {
  tft.fillCircle(290, 30, 10, RED);
}

newData = true;
     
  if (((millis() - scan_time) > 1000)) {

   //if (gps.location.isValid())
    if(newData == true)
  {
      newData = false;

      // ride start time
      if(readStartTime == 0){
      StartHr = gps.time.hour();
      StartMin = gps.time.minute();
      StartSec = gps.time.second();
      readStartTime = 1;
      } // end if(readStartTime == 0)

   // calculate ride time

    RideSec = (RideSec + 1);
     
   if(RideHr  >= 24){
    RideHr = 0;
   }
   if(RideMin >= 60){
    RideMin = 0;
    RideHr = (RideHr + 1);
   }
   if(RideSec >= 60){
    RideSec = 0;
    RideMin = (RideMin + 1);
   }

  
  /* 
      RideHr  = (gps.time.hour() - StartHr);
      RideMin = (gps.time.minute() - StartMin);
      RideSec = (gps.time.second() - StartSec);
      RideTime = (String(RideHr) + ":" + String(RideMin) + ":" + String(RideSec));
 */        
      Serial.println(F("VALID"));
      Serial.print("Lat = ");
      Serial.print(gps.location.lat(), 4);
      Serial.print(F("\t"));
      Serial.print("Lon = ");
      Serial.print(gps.location.lng(), 4);
      Serial.print(F("\t"));
      Serial.print("Speed = ");
      Serial.println(gps.speed.mph()); // Speed in miles per hour (double)

      Serial.print("Hour = ");
      Serial.print(RideHr);
      Serial.print(F("\t"));
      Serial.print("Minute = ");
      Serial.print(RideMin);
      Serial.print(F("\t"));
      Serial.print("Seconds = ");
      Serial.println(RideSec); 
      Serial.print("Ride Time = ");
      Serial.println(RideTime);
      
      // Show green circle when GPS connected
    //  tft.setCursor(190, 25);
    //    tft.fillCircle(290, 30, 10, GREEN);

   // calculate distance
   if(gps.speed.mph() > 0.5){
    distance = distance+(gps.speed.mph()/3600); 

 
   } // end if(GPS.speed.mph() > 0.5)


   
   
  }
  else
  {
      Serial.println(F("INVALID"));
      
      // Show red circle when GPS disconnected
    //  tft.setCursor(185, 25);
     //   tft.fillCircle(290, 30, 10, RED);
  }

  // Update screen variables

if(currentPage == 1){
    tft.setCursor(50, 120);
    tft.setTextColor(WHITE, BLACK);
    tft.setTextSize(6);
    tft.print(gps.speed.mph(), 1);

// Display Distance
    tft.setCursor(50, 230);
    tft.setTextColor(WHITE, BLACK);
    tft.setTextSize(6);
    tft.print(distance, 1);

// Display Ride Time
    tft.setCursor(50, 340);
    tft.setTextColor(WHITE, BLACK);
    tft.setTextSize(4);
    //tft.print(RideHr);
    //tft.setCursor(75, 340);
    //tft.print(":");
    //tft.setCursor(100, 340);
    //tft.print(RideMin);
    //tft.setCursor(125, 340);
    //tft.print(":");
    //tft.setCursor(150, 340);
    sprintf(RideTm, "%02d:%02d:%02d", RideHr, RideMin, RideSec);
    tft.print(RideTm);
} // end if current page =1

if(currentPage == 2){
   tft.setCursor(50, 110);
   tft.setTextColor(WHITE, BLACK);
   tft.setTextSize(4);
   tft.print(gps.location.lng(), 4);

// Display Latitude
    tft.setCursor(50, 190);
    tft.setTextColor(WHITE, BLACK);
    tft.setTextSize(4);
    tft.print(gps.location.lat(), 4);  
} // end if current page = 2

  if(millis() > 5000 && gps.charsProcessed() > 10){
    GPS_Status = 1;
  }
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
      Serial.println(F("No GPS detected: check wiring."));
      GPS_Status = 0;
    //while(true);
  }

  scan_time = millis(); // reset scan time
  
  } // end (((millis() - scan_time) > 1000)
  
   
} // end loop()

void SpeedometerPage(){

 // Prints the title on the screen
  tft.setCursor(65, 20);
  tft.setTextColor(WHITE);
  tft.setTextSize(3);
  tft.print("Speedometer"); 
  tft.drawFastHLine(10, 60, 320, RED);
  
// Display Speed
    tft.setCursor(50, 90); 
    tft.setTextColor(WHITE);
    tft.setTextSize(2);
    tft.print("Speed"); 
 
// Display Distance
    tft.setCursor(50, 190); 
    tft.setTextColor(WHITE);
    tft.setTextSize(2);
    tft.print("Distance"); 
  
// Display Distance
    tft.setCursor(50, 300); 
    tft.setTextColor(WHITE);
    tft.setTextSize(2);
    tft.print("Time"); 
    
// Draw buttons
// fillRoundRect(X, Y, width, height, radius, color);
// Speedometer page select PB
  tft.fillRoundRect(10, 410, 70, 50, 10, BLUE);
  tft.setCursor(16, 427);
  tft.setTextColor(WHITE, BLUE);
  tft.setTextSize(2);
  tft.print("Speed");

// GPS Info Page select PB
  tft.fillRoundRect(126, 410, 70, 50, 10, MAGENTA);
  tft.setCursor(143, 427);
  tft.setTextColor(BLACK, MAGENTA);
  tft.setTextSize(2);
  tft.print("GPS");

// Data logger control PB
  tft.fillRoundRect(240, 410, 70, 50, 10, RED);
  tft.setCursor(257, 427);
  tft.setTextColor(WHITE, RED);
  tft.setTextSize(2);
  tft.print("LOG");

} // end Speedometer page

void GPS_Info_Page(){

// Prints the title on the screen
  tft.setCursor(65, 20);
  tft.setTextColor(WHITE);
  tft.setTextSize(3);
  tft.print("GPS Info"); 
  tft.drawFastHLine(10, 60, 320, RED);
  
// Display Longitude
    tft.setCursor(50, 80); 
    tft.setTextColor(WHITE);
    tft.setTextSize(2);
    tft.print("Longitude"); 
  
// Display Latitude
    tft.setCursor(50, 160); 
    tft.setTextColor(WHITE);
    tft.setTextSize(2);
    tft.print("Latitude"); 
    

// Draw buttons
// fillRoundRect(X, Y, width, height, radius, color);
// Speedometer page select PB
  tft.fillRoundRect(10, 410, 70, 50, 10, BLUE);
  tft.setCursor(16, 427);
  tft.setTextColor(WHITE, BLUE);
  tft.setTextSize(2);
  tft.print("Speed");

// GPS Info Page select PB
  tft.fillRoundRect(126, 410, 70, 50, 10, MAGENTA);
  tft.setCursor(143, 427);
  tft.setTextColor(BLACK, MAGENTA);
  tft.setTextSize(2);
  tft.print("GPS");

// Data logger control PB
  tft.fillRoundRect(240, 410, 70, 50, 10, RED);
  tft.setCursor(257, 427);
  tft.setTextColor(WHITE, RED);
  tft.setTextSize(2);
  tft.print("LOG");

  
} // GPS_Info_Page

Thanks for all help, suggestions and comments
John

if ((p.x>=725) && (p.x<=890) && (p.y>=810) && (p.y<=890)) {
   if(RunLogger == 0){
    RunLogger = 1;
    delay(500);
  } // end RunLogger == 0
}
if ((p.x>=725) && (p.x<=890) && (p.y>=810) && (p.y<=890)) {
   if(RunLogger == 1){
    RunLogger = 0;
    delay(500);
  } // end RunLogger == 1
 
} // end Start/Stop logging

Shouldn't that second if be an else if ?

It would be neater to do

if ((p.x >= 725) && (p.x <= 890) && (p.y >= 810) && (p.y <= 890))
{
  RunLogger = !RunLogger;
  delay(500);
}

LedState=0

Void toggle (){
LedState = !LedState
}

Digitalwrite (ledPin, LedState);

Pseudocode

@UKHeliBob it's really neat because it works and much similar code, sometimes I over think things.

@pmagowan your code will also work and I thank you both for the help

John

I do my way because I often have multiple things to toggle and you can do an array easily with the function. You just need to pass the led as an argument to the function (not included in the code above).

It then reads in your code as
Toggle(led1);

Helibobs is the same but integrated to your specific example ie using the ! To toggle

Do you understand why your original version did not work ?

I believe I do, it was turning Runlogger on, then the next if statement said if it's on turn it off. So it never really came on. I tried putting some other flags around it but wasn't getting any where and it was getting to complicated, I knew it shouldn't be that complicated. Obviously the way both of you have explained it's not complicated.

Thanks for asking

Looks like you got it

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.