Serial Print makes code work. Why?

I have a TFT and a Temp sensor that I'm putting into my sketch, I have separate sketches for each component and they work as coded.

I have married the two sketches together into one sketch and when I uploaded it to my Arduino the touch events with the TFT would not register to flip the on screen buttons from red to green.

I added a serial.print underneath the touchRead(&tx, &ty); (in the Void GFXbuttonswitch) and it now works as coded.
Why would that make a difference?
I'm trying to get a better understanding what's going when I write code.

#include <Wire.h>
#include <SparkFun_TMP117.h>

TMP117 sensor;    //inialize sensor  (I2C 0x48)
byte AlertFlag = 0; //variable to hold high and low alert flags from configuration register
boolean H_AlertFlag = 0;  //variable to hold state of high alert flag
boolean L_AlertFlag = 0;  //variable to hold state of low alert flag

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1500;

unsigned long startMillis2;
unsigned long currentMillis2;
const unsigned long period2 = 500;

const int fanControl = 13;
/////////////////////////////////////////////////////////////////
//TFT SCREEN GLOBALS
#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_RA8875.h"

#define RA8875_CS 10
#define RA8875_RESET 9

Adafruit_RA8875 tft = Adafruit_RA8875(RA8875_CS, RA8875_RESET);
uint16_t tx, ty;

byte rotation = 0;
int x, y;
const byte row = 4;
const byte col = 3;
byte lastHit = 0;
byte currentHit = 0;
Adafruit_GFX_Button btn[row * col];
const int TS_MAXX = 980, TS_MINX = 60, TS_MAXY = 920, TS_MINY = 80;

////////////////////////////////////////////////////////////////////////////
//FOOT SWITCH GLOBALS

const int footswitch = 2;
int footswitchState = 0;

////////////////////////////////////////////////////////////////////////////

void setup() {

  Serial.begin(115200);
  pinMode(fanControl, OUTPUT);            //Fan cooling control
  digitalWrite(fanControl, HIGH);         // turn fans off on startup(logic reversed from Mosfet)

  pinMode(footswitch, INPUT),       //program start switch

          pinMode(18, INPUT_PULLUP);        //front proximity sensor(stapler in position)
  pinMode(19, INPUT_PULLUP);        //back proximity sensor (stapler in start position)

  Wire.begin();
  Wire.setClock(400000);   // Set clock speed to be the fastest for better communication (fast mode)

  if (sensor.begin() == true) // Function to check if the sensor will correctly self-identify with the proper Device ID/Address
  {
    Serial.println("Begin");
  }
  else
  {
    Serial.println("Device failed to setup- Freezing code.");
    while (1);
  }
  sensor.setHighLimit(35); //set high limit
  sensor.setLowLimit(60);  //set low limit
  sensor.setAlertFunctionMode(0);//set to alert mode

  if (!tft.begin(RA8875_800x480)) {
    Serial.println("RA8875 Not Found!");
    while (1);
  }

  Serial.println("Found RA8875");
  tft.displayOn(true);
  tft.GPIOX(true);      // Enable TFT - display enable tied to GPIOX
  tft.PWM1config(true, RA8875_PWM_CLK_DIV1024); // PWM output for backlight
  tft.PWM1out(255);
  tft.fillScreen(RA8875_BLACK);
  tft.textMode();
  tft.textSetCursor(20, 15);
  tft.textEnlarge(2);
  tft.textColor(RA8875_WHITE, RA8875_RED);
  tft.textWrite("Choose how many petals you need.");
  tft.graphicsMode();

  tft.touchEnable(true);
  btnGrid();

}

void loop() {
  GFXbuttonswitch();
  EnclosureCooling();

}
void EnclosureCooling() {
  if (sensor.dataReady() == true) // Function to make sure that there is data ready to be printed, only prints temperature values when data is ready

    unsigned long currentMillis = millis();
  {
    currentMillis = millis();
    if (currentMillis - startMillis >= period)
      startMillis = currentMillis;

    AlertFlag = sensor.getHighLowAlert(); //read the alert flags from the configuration register
    H_AlertFlag = bitRead(AlertFlag, 1); //grab the high alert field using bitwise operator and save current to H_AlertFlag
    L_AlertFlag = bitRead(AlertFlag, 0); //grab the low alert field using bitwise operator and save current L_AlertFlag

    if (H_AlertFlag == true)
    {
      digitalWrite(13, LOW);        //Logic is reversed from Mosfet
    }
    else if (L_AlertFlag == true)
    {
      digitalWrite(13, HIGH);       //logic is reversed Mosfet
    }
    unsigned long currentMillis2 = millis();
    {
      currentMillis2 = millis();
      if (currentMillis2 - startMillis2 >= period2)
        startMillis2 = currentMillis2;
    }
  }

}
void GFXbuttonswitch() {

  if (tft.touched()) {
    tft.touchRead(&tx, &ty);
    Serial.print(tx); Serial.print(", "); Serial.println(ty);
    switch (rotation) {
      case 0:
        tx = map(tx, TS_MINX, TS_MAXX, 0, tft.width());
        ty = map(ty, TS_MINY, TS_MAXY, 0, tft.height());
        break;
      case 1:
        // p.x, p.y reversed //
        tx = map(ty, TS_MINY, TS_MAXY, 0, tft.width());
        ty = map(tx, TS_MAXX, TS_MINX, 0, tft.height());
        break;
      case 2:
        tx = map(tx, TS_MAXX, TS_MINX, 0, tft.width());
        ty = map(ty, TS_MAXY, TS_MINY, 0, tft.height());
        break;
      case 3:
        // p.x, p.y reversed //
        tx = map(ty, TS_MAXY, TS_MINY, 0, tft.width());
        ty = map(tx, TS_MINX, TS_MAXX, 0, tft.height());
        break;
    }
  }
  if (tft.touched()) {
    for (uint8_t b = 0; b < row * col; b++) {
      if (btn[b].contains(tx, ty)) {
        btn[b].press(true);
        btn[b].drawButton(true);
        currentHit = b;
      }
      else if (btn[b].contains(tx, ty) == false) {
        btn[b].press(false);
        if (b == lastHit) {
          btn[b].drawButton(false);
        }
      } else {
        return;
      }
    }
    lastHit = currentHit;
    //delay(100);
  }
}

void btnGrid() {

  int left, top;
  int l = 50;
  int t = 90;
  int w = 200;
  int h = 60;
  byte hgap = 40;
  byte vgap = 40;
  byte id = 0;
  char *titleStr[row * col] = {"4", "6", "8", "9", "12", "16", "Load", "1"};
  for (byte j = 0; j < row; j++) {
    for (byte i = 0; i < col; i++) {
      left = l + i * (w + vgap);
      top = t + j * (h + hgap);
      btn[id].initButtonUL( &tft, left, top, w, h, RA8875_WHITE, RA8875_RED, RA8875_GREEN, titleStr[id], 3 );
      if (id == currentHit) {
        // inverted
        btn[id].drawButton(true);
      } else {
        btn[id].drawButton(false);
      }
      id++;
    }
  }
}

Random behavior when you add or remove code is often linked to memory corruption and debugging starts by looking at all the arrays and if you do something out of bounds and look also at all pointers.

I’ve noticed this

You are not passing in 12 values and because it’s a local variable, the missing 4 pointers are not initialized to 0 (which would be the null pointer) and so you can get 4 pointers to random places in the array.

This might have bad consequences when you use those random pointers in

btn[id].initButtonUL( &tft, left, top, w, h, RA8875_WHITE, RA8875_RED, RA8875_GREEN, titleStr[id], 3 );
3 Likes

Thanks J-M-L

Too say I'm a novice at coding is a huge overstatement so I appreciate the tip. I found this bit of code on the web and modified it to work the way I needed to.

I did add in title's to the remaining 4 buttons but that didn't make it work without having to add the serial.print() to the code.

after searching some more I found a post that said to look at the compiler warning and it might give you clue at what might be giving you the problem.

Something is deprecated but I don't have the knowledge to understand it, can anyone point me in the right direction.

/Users/admin/Documents/Arduino/Petal_Stapler/Petal_Stapler.ino:189:101: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
   char *titleStr[row * col] = {"4", "6", "8", "9", "12", "16", "Load", "1", "x", "xx", "xxx", "xxxx"};
                                                                                                     ^

In the above you are putting Strings into a char array.

Arduino link to some words on the char data type you might want to read.

Also, take the String Load it's several char long 'L' 'o' 'a' 'd'.

Might be better off if you posted the code.

C-strings, not Strings. Big difference

The array holds constant cString so that definition should be

const char *titleStr[row * col] = {"4", "6", "8", "9", "12", "16", "Load", "1", nullptr, nullptr, nullptr, nullptr};`

Or

const char *titleStr[row * col] = {"4", "6", "8", "9", "12", "16", "Load", "1", "x", "xx", "xxx", "xxxx"};

If the library you are using does not deal well with null pointers. It would be necessary to understand what the library does with the information since the titles pointers are technically temporary (scope of the array is not global)

I tried that late last night and got an error and haven't had time to research the error the compiler gave me.

Arduino: 1.8.15 (Mac OS X), Board: "Arduino Due (Programming Port)"











/Users/admin/Documents/Arduino/Petal_Stapler/Petal_Stapler.ino: In function 'void btnGrid()':
Petal_Stapler:194:103: error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
       btn[id].initButtonUL( &tft, left, top, w, h, RA8875_WHITE, RA8875_RED, RA8875_GREEN, titleStr[id], 3 );
                                                                                                       ^
In file included from /Users/admin/Documents/Arduino/Petal_Stapler/Petal_Stapler.ino:21:0:
/Users/admin/Documents/Arduino/libraries/Adafruit_GFX_Library/Adafruit_GFX.h:262:8: error:   initializing argument 9 of 'void Adafruit_GFX_Button::initButtonUL(Adafruit_GFX*, int16_t, int16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, char*, uint8_t)' [-fpermissive]
   void initButtonUL(Adafruit_GFX *gfx, int16_t x1, int16_t y1, uint16_t w,
        ^
exit status 1
invalid conversion from 'const char*' to 'char*' [-fpermissive]


This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

OK seems the Adafruit_GFX_Library expects modifiable data. I'm not sure they modify it and it's likely a mistake from them not to have declared the parameter as const, but that's what is there...

so go for either

char *titleStr[row * col] = {"4", "6", "8", "9", "12", "16", "Load", "1", nullptr, nullptr, nullptr, nullptr};`

Or (wasting memory)

char *titleStr[row * col] = {"4", "6", "8", "9", "12", "16", "Load", "1", "x", "xx", "xxx", "xxxx"};

I have done the Null for the last four buttons for now, if I need them I will add them back.

The only thing this code does is add text on top of the GFX button image so it really doesn't do anything else.

The original problem of the touch events not working without the serial.print below the tft.touchRead(&tx, &ty) is still there even with the change I have made.

can you post the code you are using now?

Serial.print could be acting as a delay. Did you try to comment out the serial print and put in a delay() in its place?

I will try the delay() for debugging but it will need to be millis() so it doesn't block.

Code as written now for J-M-L

#include <Wire.h>
#include <SparkFun_TMP117.h>

TMP117 sensor;    //inialize sensor  (I2C 0x48)
byte AlertFlag = 0; //variable to hold high and low alert flags from configuration register
boolean H_AlertFlag = 0;  //variable to hold state of high alert flag
boolean L_AlertFlag = 0;  //variable to hold state of low alert flag

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1500;

unsigned long startMillis2;
unsigned long currentMillis2;
const unsigned long period2 = 500;

const int fanControl = 13;
/////////////////////////////////////////////////////////////////
//TFT SCREEN GLOBALS
#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_RA8875.h"

#define RA8875_CS 10
#define RA8875_RESET 9

Adafruit_RA8875 tft = Adafruit_RA8875(RA8875_CS, RA8875_RESET);
uint16_t tx, ty;

byte rotation = 0;
int x, y;
const byte row = 4;
const byte col = 3;
byte lastHit = 0;
byte currentHit = 0;
Adafruit_GFX_Button btn[row * col];
const int TS_MAXX = 980, TS_MINX = 60, TS_MAXY = 920, TS_MINY = 80;

////////////////////////////////////////////////////////////////////////////
//FOOT SWITCH GLOBALS

const int footswitch = 2;
int footswitchState = 0;

////////////////////////////////////////////////////////////////////////////

void setup() {

  Serial.begin(115200);
  pinMode(fanControl, OUTPUT);            //Fan cooling control
  digitalWrite(fanControl, HIGH);         // turn fans off on startup(logic reversed from Mosfet)

  pinMode(footswitch, INPUT),       //program start switch

          pinMode(18, INPUT_PULLUP);        //front proximity sensor(stapler in position)
  pinMode(19, INPUT_PULLUP);        //back proximity sensor (stapler in start position)

  Wire.begin();
  Wire.setClock(400000);   // Set clock speed to be the fastest for better communication (fast mode)

  if (sensor.begin() == true) // Function to check if the sensor will correctly self-identify with the proper Device ID/Address
  {
    Serial.println("Begin");
  }
  else
  {
    Serial.println("Device failed to setup- Freezing code.");
    while (1);
  }
  sensor.setHighLimit(35); //set high limit
  sensor.setLowLimit(60);  //set low limit
  sensor.setAlertFunctionMode(0);//set to alert mode

  if (!tft.begin(RA8875_800x480)) {
    Serial.println("RA8875 Not Found!");
    while (1);
  }

  Serial.println("Found RA8875");
  tft.displayOn(true);
  tft.GPIOX(true);      // Enable TFT - display enable tied to GPIOX
  tft.PWM1config(true, RA8875_PWM_CLK_DIV1024); // PWM output for backlight
  tft.PWM1out(255);
  tft.fillScreen(RA8875_BLACK);
  tft.textMode();
  tft.textSetCursor(20, 15);
  tft.textEnlarge(2);
  tft.textColor(RA8875_WHITE, RA8875_RED);
  tft.textWrite("Choose how many petals you need.");
  tft.graphicsMode();

  tft.touchEnable(true);
  btnGrid();

}

void loop() {
  GFXbuttonswitch();
  EnclosureCooling();

}
void EnclosureCooling() {
  if (sensor.dataReady() == true) // Function to make sure that there is data ready to be printed, only prints temperature values when data is ready

    unsigned long currentMillis = millis();
  {
    currentMillis = millis();
    if (currentMillis - startMillis >= period)
      startMillis = currentMillis;

    AlertFlag = sensor.getHighLowAlert(); //read the alert flags from the configuration register
    H_AlertFlag = bitRead(AlertFlag, 1); //grab the high alert field using bitwise operator and save current to H_AlertFlag
    L_AlertFlag = bitRead(AlertFlag, 0); //grab the low alert field using bitwise operator and save current L_AlertFlag

    if (H_AlertFlag == true)
    {
      digitalWrite(13, LOW);        //Logic is reversed from Mosfet
    }
    else if (L_AlertFlag == true)
    {
      digitalWrite(13, HIGH);       //logic is reversed Mosfet
    }
    unsigned long currentMillis2 = millis();
    {
      currentMillis2 = millis();
      if (currentMillis2 - startMillis2 >= period2)
        startMillis2 = currentMillis2;
    }
  }

}
void GFXbuttonswitch() {

  if (tft.touched()) {
    tft.touchRead(&tx, &ty);
    Serial.print(tx); Serial.print(", "); Serial.println(ty);
    switch (rotation) {
      case 0:
        tx = map(tx, TS_MINX, TS_MAXX, 0, tft.width());
        ty = map(ty, TS_MINY, TS_MAXY, 0, tft.height());
        break;
      case 1:
        // p.x, p.y reversed //
        tx = map(ty, TS_MINY, TS_MAXY, 0, tft.width());
        ty = map(tx, TS_MAXX, TS_MINX, 0, tft.height());
        break;
      case 2:
        tx = map(tx, TS_MAXX, TS_MINX, 0, tft.width());
        ty = map(ty, TS_MAXY, TS_MINY, 0, tft.height());
        break;
      case 3:
        // p.x, p.y reversed //
        tx = map(ty, TS_MAXY, TS_MINY, 0, tft.width());
        ty = map(tx, TS_MINX, TS_MAXX, 0, tft.height());
        break;
    }
  }
  if (tft.touched()) {
    for (uint8_t b = 0; b < row * col; b++) {
      if (btn[b].contains(tx, ty)) {
        btn[b].press(true);
        btn[b].drawButton(true);
        currentHit = b;
      }
      else if (btn[b].contains(tx, ty) == false) {
        btn[b].press(false);
        if (b == lastHit) {
          btn[b].drawButton(false);
        }
      } else {
        return;
      }
    }
    lastHit = currentHit;
  }
}

void btnGrid() {

  int left, top;
  int l = 50;
  int t = 90;
  int w = 200;
  int h = 60;
  byte hgap = 40;
  byte vgap = 40;
  byte id = 0;
  char *titleStr[row * col] = {"4", "6", "8", "9", "12", "16", "Load", "1", nullptr, nullptr, nullptr, nullptr};
  for (byte j = 0; j < row; j++) {
    for (byte i = 0; i < col; i++) {
      left = l + i * (w + vgap);
      top = t + j * (h + hgap);
      btn[id].initButtonUL( &tft, left, top, w, h, RA8875_WHITE, RA8875_RED, RA8875_GREEN, titleStr[id], 3 );
      if (id == currentHit) {
        // inverted
        btn[id].drawButton(true);
      } else {
        btn[id].drawButton(false);
      }
      id++;
    }
  }
}

try with this modified code for the function GFXbuttonswitch

void GFXbuttonswitch() {
  if (tft.touched()) {
    tft.touchRead(&tx, &ty);
    Serial.print(tx); Serial.print(", "); Serial.println(ty);
    switch (rotation) {
      case 0:
        tx = map(tx, TS_MINX, TS_MAXX, 0, tft.width());
        ty = map(ty, TS_MINY, TS_MAXY, 0, tft.height());
        break;
      case 1:
        // p.x, p.y reversed //
        tx = map(ty, TS_MINY, TS_MAXY, 0, tft.width());
        ty = map(tx, TS_MAXX, TS_MINX, 0, tft.height());
        break;
      case 2:
        tx = map(tx, TS_MAXX, TS_MINX, 0, tft.width());
        ty = map(ty, TS_MAXY, TS_MINY, 0, tft.height());
        break;
      case 3:
        // p.x, p.y reversed //
        tx = map(ty, TS_MAXY, TS_MINY, 0, tft.width());
        ty = map(tx, TS_MINX, TS_MAXX, 0, tft.height());
        break;
    }

    for (uint8_t b = 0; b < row * col; b++) {
      if (btn[b].contains(tx, ty)) {
        btn[b].press(true);
        btn[b].drawButton(true);
        currentHit = b;
        break;
      } else  {
        btn[b].press(false);
        if (b == lastHit) {
          btn[b].drawButton(false);
        }
      }
    }
    lastHit = currentHit;
  }
}

I tried this but the buttons didn't switch back from green to red when another button was pushed. The touch events were a little erratic making untouched GFX buttons changing when not touched.

I don’t know that library. Is that just dealing or do the buttons fire events when released?

You could envision to Modify the code to make all the buttons untouched when you get a hit, then check if one is touched.and press that one