Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tft reinit after deep sleep #19

Open
biccius opened this issue Oct 3, 2020 · 5 comments
Open

tft reinit after deep sleep #19

biccius opened this issue Oct 3, 2020 · 5 comments

Comments

@biccius
Copy link

biccius commented Oct 3, 2020

Hi

This is meant to be an attempt of improvement on the display drawing speed after the ESP32 wakes up from deep sleep. In all the sources I've seen, the display call tft.init() at every wake of the microcontroller.
This include a hardware or software reset that blank the screen for some milliseconds.

The ST7735 display has sleep and shutdown commands, preserving the contents of the on-screen buffer in memory.

My purpose is to try to:

  • fill the screen with a color A
  • send the esp32 to deep sleep
  • wake up with button press the esp32 and redraw the display with color A
  • then change in progression colors to B, C , etc..

Here's the code i'm working on:

#include <pcf8563.h>
#include <TFT_eSPI.h>            // Graphics and font library for ST7735 driver chip
#include <SPI.h>
#include <WiFi.h>
#include <Wire.h>
#include "sensor.h"
#include "esp_adc_cal.h"


#define TP_PIN_PIN          33
#define TP_PWR_PIN 			25

TFT_eSPI tft = TFT_eSPI();       // Invoke library, pins defined in User_Setup.h
RTC_DATA_ATTR int boots = 0;


void setupTFT()
{
  tft.init();
  tft.setRotation(1);
  tft.setSwapBytes(true);
}


int color = 0x5555;



void Wake()
{
    SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
    pinMode(TFT_CS, OUTPUT);
    pinMode(TFT_DC, OUTPUT);
    pinMode(TFT_BL, OUTPUT);
	tft.writecommand(ST7735_DISPON);
	tft.writecommand(ST7735_SLPOUT);
}

void Sleep()
{
  tft.writecommand(ST7735_SLPIN);
  tft.writecommand(ST7735_DISPOFF);
  delay(200);

  digitalWrite(GPIO_NUM_26, HIGH);  // keep GPIO_26 high state after deep sleep reset
  gpio_hold_en(GPIO_NUM_26);		// display is preserved
  gpio_deep_sleep_hold_en();

  esp_sleep_enable_ext1_wakeup(GPIO_SEL_33, ESP_EXT1_WAKEUP_ANY_HIGH);
  esp_deep_sleep_start();
}


void setup(void)
{
	  pinMode(TP_PIN_PIN, INPUT);
	  pinMode(TP_PWR_PIN, PULLUP);
	   //! Must be set to pull-up output mode in order to wake up in deep sleep mode
	   digitalWrite(TP_PWR_PIN, HIGH);

	  Serial.begin(115200);

	  if(boots == 0) //Run this only the first time
	  {
		  Serial.println("first boot");
		  setupTFT();
		  tft.fillScreen(color);
		  color+=0x1000;
	  	  boots ++;
	  }
	  else
	  {
		  Serial.println("wake");
		  Wake();
		  tft.setRotation(1);
		  tft.setSwapBytes(1);
		  while (1)
		  {
			  Serial.println("changing color");
			  tft.fillScreen(color);
			  color+=0x1000;
			  delay(1000);
		  }
	  }//if boots
}




void loop()
{
	delay(5000);
	Serial.println("sleep");
	Sleep();
}

Can't understand why after the wake up the display is not working as expected

@genotix
Copy link

genotix commented Oct 4, 2020 via email

@biccius
Copy link
Author

biccius commented Oct 4, 2020

Hi Eric

  1. SPI.end() detach all SPI pins (MISO,MOSI,CLOCK,CS) previously attached by SPI.begin() to signals events. I think is useless add it before the sleep because at restart the peripheral is uninitialized because the chip is reset by the deep sleep.
  2. According to schematics of the display (
    https://github.com/Xinyuan-LilyGO/LilyGo-T-Wristband/blob/master/schematic/T_Wristband_lsm9ds1_20200306.pdf) we can just send a RESET signal on RES pin. I want to avoid this because the display is already initialized.

In the sleep phase we use

tft.writecommand(ST7735_SLPIN);
 delay(150);
 tft.writecommand(ST7735_DISPOFF);
 delay(200);

In wake up we have to do the same with SLPOUT and DISPON but before do that we have to re-initialize the SPI perpipheral
3. This pin is used by touchpad to wakeup the device. Actually I find this pointless because the sleep is working correctly for me.
4. If we do a tft.init() everything restart to work correctly. This method called at every wake is very slow so avoid the re-init of the display with all SPI commands is what i'm trying to do. I already do DISPON and DISPOFF commands on the display and the display turn on correctly after the sleep for me.

Here's my last source revision

#include <pcf8563.h>
#include <TFT_eSPI.h>            // Graphics and font library for ST7735 driver chip
#include <SPI.h>
#include <WiFi.h>
#include <Wire.h>
#include "sensor.h"
#include "esp_adc_cal.h"


#define TP_PIN_PIN          33
#define TP_PWR_PIN 			25

TFT_eSPI tft = TFT_eSPI();       // Invoke library, pins defined in User_Setup.h
RTC_DATA_ATTR int boots = 0;


void setupTFT()
{
  tft.init();
  tft.setRotation(1);
  tft.setSwapBytes(true);
}


int color = 0x5555;


void Wake()
{

    pinMode(TFT_CS, OUTPUT);
    pinMode(TFT_DC, OUTPUT);
    pinMode(TFT_BL, OUTPUT);

    digitalWrite( TFT_BL , HIGH);

    SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);

    tft.writecommand(ST7735_DISPON);
    delay(150);
	tft.writecommand(ST7735_SLPOUT);
	delay(150);
}

void Sleep()
{
  tft.writecommand(ST7735_SLPIN);
  delay(150);
  tft.writecommand(ST7735_DISPOFF);
  delay(200);

  digitalWrite(GPIO_NUM_26, HIGH);  // keep GPIO_26 high state after deep sleep reset
  gpio_hold_en(GPIO_NUM_26);		// display is preserved
  gpio_deep_sleep_hold_en();

  digitalWrite( TFT_BL , LOW);

  SPI.end();

  esp_sleep_enable_ext1_wakeup(GPIO_SEL_33, ESP_EXT1_WAKEUP_ANY_HIGH);
  esp_deep_sleep_start();
}


void setup(void)
{
	  pinMode(TP_PIN_PIN, INPUT);
	  pinMode(TP_PWR_PIN, PULLUP);
	  //! Must be set to pull-up output mode in order to wake up in deep sleep mode
	  digitalWrite(TP_PWR_PIN, HIGH);

	  Serial.begin(115200);

	  if(boots == 0) //Run this only the first time
	  {
		  Serial.println("first boot");
		  setupTFT();
		  tft.fillScreen(color);
		  color+=0x1000;
	  	  boots ++;
	  }
	  else
	  {
		  Serial.println("wake");
		  Wake();
		  tft.setRotation(1);
		  tft.setSwapBytes(1);
		  delay(3000);
		  while (1)
		  {
			  Serial.println("changing color");
			  tft.fillScreen(color);
			  color+=10;
			  delay(10);
		  }
	  }//if boots
}


void loop()
{
	delay(5000);
	Serial.println("sleep");
	Sleep();
}

What the code do is :

  1. display start with cyan screen
  2. deepsleep after 5 seconds
  3. wakeup at button press with immediate display cyan screen shown
  4. after the wakeup the display start cycling redrawing the display with differents colors

Everything works, but at point 4 i have the display like in figure

IMAGE

So i think the tft library restart in a wrong state or the display need to be re-initialized in some way

@genotix
Copy link

genotix commented Oct 4, 2020 via email

@biccius
Copy link
Author

biccius commented Oct 6, 2020

I think you may be right about asynchronously blocking communication between ESP32 and the display.
Just adding SPI.end doesn't seem to give improvements

Not even changing the order of the write commands seems to change anything either

It could be that restarting the ESP32 at reset sends something strange to the already configured display and causes that horizontal bar not to be redrawn.

I can't understand what you're referring to in the last part of the post.

@genotix
Copy link

genotix commented Oct 13, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants