I need help again with MCUFRIEND_kbv

UNO TFT shied
Arduino Mega
DS3231
DS18B20

Hi, my DS3231 generates an interrupt every second (for now). When interrupt occurs, I call displayTemp();

In that routine, I get the temp from DS18b20 and display it on TFT. But every now and then, the screen goes blank or funny colors. This happens when in call showmsgXY(10, 245, 1, &SansSerif_bold_14, result, BLACK);

I tried to print a static string instead of 'result' with same bug. It also doesn't matter what font I'm using (tried system font). I've been working on this for hours now and I don't understand what is goint on...
Can you help?

Also during compilation there are a warnins like this:
C:\Users\Stephane\Documents\Arduino\TFT_test_3\TFT_test_3.ino: In function 'void draw_current_screen(int)':
C:\Users\Stephane\Documents\Arduino\TFT_test_3\TFT_test_3.ino:147:83: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
setup_btn.initButton(&tft, 60, 305, 100, 30, WHITE, CYAN, BLACK, "SETUP", 2);

Is this normal with this library?

/*
CURRENT SCREEN DEFINITIONS
1: Home Screen
2: Adjust Dosing Regimen
*/

#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h>
#include <Fonts/FreeSans9pt7b.h>
//#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/SansSerif_bold_14.h>
#include <Fonts/SansSerif_plain_10.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <Wire.h>
#include <RTClib.h>

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define GREY    0x8410
#define ORANGE  0xE880

#define MINPRESSURE 200
#define MAXPRESSURE 1000
#define ONE_WIRE_BUS 49
#define CLOCK_INTERRUPT_PIN 19

DeviceAddress thermometerAddress;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature tempSensor(&oneWire);
DateTime now;
RTC_DS3231 rtc;
MCUFRIEND_kbv tft;

const int XP = 6, XM = A2, YP = A1, YM = 7; //ID=0x9341
const int TS_LEFT = 926, TS_RT = 170, TS_TOP = 959, TS_BOT = 174;
int pixel_x, pixel_y;
int current_screen = 0;
int adjust_regimen_day;
float aquarium_temp;
float old_aquarium_temp;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
Adafruit_GFX_Button on_btn, off_btn, back_btn, setup_btn, maint_btn, feed_btn;

void setup() {
  Serial.begin(9600);
  tempSensor.begin();
  tempSensor.setResolution(thermometerAddress, 11);
  
  rtc.begin();
  rtc.disable32K();
  pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING);
  rtc.clearAlarm(1);
  rtc.clearAlarm(2);
  rtc.writeSqwPinMode(DS3231_OFF);
  rtc.disableAlarm(2);
//  rtc.setAlarm1(rtc.now(), DS3231_A1_PerSecond);
  rtc.setAlarm1(rtc.now() + TimeSpan(1),DS3231_A1_Second);  
  uint16_t ID = tft.readID();
  tft.begin(ID);
  tft.setRotation(3);
  draw_current_screen(current_screen);
}


void loop() {
    now = rtc.now();
    if(rtc.alarmFired(1)) {
      rtc.clearAlarm(1);
      rtc.setAlarm1(rtc.now() + TimeSpan(1),DS3231_A1_Second);
    }
    bool down = Touch_getXY();
    if (current_screen ==0) {

      // DAY PRESSED
      if (pixel_y > 35 && pixel_y < 80) { 
        if (pixel_x > 120 && pixel_x <170) {  // MONDAY
          adjust_regimen_day = 1;
          current_screen = 1;
          draw_current_screen(current_screen);
        } 
      }   
    }
    if (current_screen == 1) {
      back_btn.press(down && back_btn.contains(pixel_x, pixel_y));
      if (back_btn.justPressed()) {
          back_btn.drawButton(true); 
          current_screen = 0;
          draw_current_screen(current_screen);
      }   
    }
}

void draw_current_screen(int x)
{
  switch (x) {
    case 0:  
      tft.fillScreen(BLACK);
      tft.setFont(NULL);
/*      on_btn.initButton(&tft,  60, 200, 60, 30, WHITE, CYAN, BLACK, "ON", 1);
      off_btn.initButton(&tft, 180, 200, 60, 30, WHITE, CYAN, BLACK, "OFF", 1);
      on_btn.drawButton(false);
      off_btn.drawButton(false);
      tft.fillRect(40, 80, 160, 80, RED); */
      tft.fillRect(0, 0, 480, 20, GREEN); 
      showmsgXY(140, 16, 1, &FreeSans9pt7b, "NANO SCAPE QUEBEC", BLACK);

      // DOSING REGIMEN
      tft.fillRect(0,35,470,45,BLUE);
      showmsgXY(30, 55, 1, &SansSerif_bold_14, "Dosing", WHITE);
      showmsgXY(30, 72, 1, &SansSerif_bold_14, "Regimen", WHITE);
      tft.drawRect(120, 35, 350, 45, YELLOW);
      tft.drawFastHLine(120, 57, 350, YELLOW);
      tft.drawFastVLine(170, 35, 45, YELLOW); 
      tft.drawFastVLine(220, 35, 45, YELLOW);
      tft.drawFastVLine(270, 35, 45, YELLOW);
      tft.drawFastVLine(320, 35, 45, YELLOW);
      tft.drawFastVLine(370, 35, 45, YELLOW); 
      tft.drawFastVLine(420, 35, 45, YELLOW);
      showmsgXY(134, 50, 1, &SansSerif_plain_10, "MON", WHITE);
      showmsgXY(184, 50, 1, &SansSerif_plain_10, "TUE", WHITE);
      showmsgXY(234, 50, 1, &SansSerif_plain_10, "WED", WHITE);
      showmsgXY(284, 50, 1, &SansSerif_plain_10, "THU", WHITE);
      showmsgXY(334, 50, 1, &SansSerif_plain_10, "FRI", WHITE);
      showmsgXY(384, 50, 1, &SansSerif_plain_10, "SAT", WHITE);
      showmsgXY(434, 50, 1, &SansSerif_plain_10, "SUN", WHITE);

      // PH
      tft.fillRoundRect(0,90,80,90,9,GREEN);
      showmsgXY(30, 105, 1, &SansSerif_bold_14, "PH", BLACK);
      
      // TEMPERATURE
      tft.fillRoundRect(0,190,80,90,9,BLUE);
      showmsgXY(10, 205, 1, &SansSerif_bold_14, "TEMP F", BLACK);
      
      // BOTTOM MENU
      tft.setFont(NULL);
      setup_btn.initButton(&tft,  60, 305, 100, 30, WHITE, CYAN, BLACK, "SETUP", 2);
      setup_btn.drawButton(false);
      maint_btn.initButton(&tft,  240, 305, 150, 30, WHITE, CYAN, BLACK, "MAINTAIN", 2);
      maint_btn.drawButton(false);
      feed_btn.initButton(&tft,  420, 305, 100, 30, WHITE, CYAN, BLACK, "FEED", 2);
      feed_btn.drawButton(false);
      
      break; 

    case 1:
      tft.fillScreen(BLACK);
      showmsgXY(70, 55, 1, &SansSerif_bold_14, "Adjust Dosing Quantity for ", WHITE);
      switch (adjust_regimen_day) {
        case 1:
          showmsgXY(315, 55, 1, &SansSerif_bold_14, "MONDAY", WHITE);
          break;
      }
      tft.setFont(NULL);
      back_btn.initButton(&tft,  30, 305, 60, 30, WHITE, CYAN, BLACK, "BACK", 1);
      back_btn.drawButton(false);
      break;
  }
}

void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg, uint16_t color)
{
    int16_t x1, y1;
    uint16_t wid, ht;
    tft.setFont(f);
    tft.setCursor(x, y);
    tft.setTextColor(color);
    tft.setTextSize(sz);
    tft.print(msg);
    tft.setFont(NULL);
}

bool Touch_getXY(void)
{
    TSPoint p = ts.getPoint();
    pinMode(YP, OUTPUT);      //restore shared pins
    pinMode(XM, OUTPUT);
    digitalWrite(YP, HIGH);   //because TFT control pins
    digitalWrite(XM, HIGH);
    bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
    if (pressed) {
        pixel_x = map(p.y, TS_BOT, TS_TOP, 0, tft.width());
        pixel_y = map(p.x, TS_LEFT, TS_RT, 0, tft.height());
    }
    return pressed;
}

void displayTemp() {

  char result[4];
  tempSensor.requestTemperatures();
  aquarium_temp = tempSensor.getTempFByIndex(0);
  Serial.println("Interrupt !");
  if (aquarium_temp != old_aquarium_temp) {
    
    dtostrf(old_aquarium_temp, 4, 1, result);
    showmsgXY(10, 245, 1, &SansSerif_bold_14, result, BLUE);
    dtostrf(aquarium_temp, 4, 1, result);
    showmsgXY(10, 245, 1, &SansSerif_bold_14, result, BLACK);
    Serial.println(aquarium_temp);
    Serial.println(result);
    old_aquarium_temp = aquarium_temp;
  }
}

 void showTime()
 {
  Serial.print(now.hour());
  Serial.print(":");
  Serial.print(now.minute());
  Serial.print(":");
  Serial.print(now.second());
  Serial.println("  ");
 }

  void onAlarm() {
    if (current_screen == 0) {
      displayTemp(); 
    } 
}

You are using Serial.println("Interrupt !"); within the interrupt sub-function, this is anyway no good, but to prevent the tft from being interfered by calling it from inside an interrupt, you should just 'set a flag' inside the ISR and call displayTemp(); from loop() if the flag has been set. and then un-set it.

Thank you for your answer. You were right sir. Problem solved. I really taught I could call a function from an interrupt routine if this is the last thing in the routine.... It seems I can't.

You can call a function, but as a rule your ISR should be short and should not contain references to Serial or use delay(). The functions that send data to the tft are rather slow and should also be avoided.

Also you must not forget that any global variable that gets modified inside the ISR (or it's sub-functions) and is used outside of it, must be declared 'volatile' (that does go for you flag as well) and any variable that consists of more than 1 byte may change value halfway though the reading process. In your case the tft object has variable that are not declared volatile, that is probably the cause.

Very interesting thoughts. Thank you very much.

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