ESP32-C3 with integrated GC9A01 - cheap touch controller

That looks great, pretty cool!

Yeah - I was only thinking about that as a means of having the controller in a state ready to detect touches, but it would normally be in deep sleep based on no movement. Yep, would need the sensor to be connected to the ESP32 and thinking about it, that sensor itself would use power… dang. Personally I used to use arduino pros and NRF24L01+ radios that happily would last for a year or more on two AA batteries until I was tempted by these power hungry esp devices. :slight_smile:

Made some more progress with this device. Now it’s working as a smart touchscreen light controller. Works to:

  • Turn Lights on and off with up and down swipes
  • Control light dimming
  • Control color with a color wheel selector

It’s working with battery but the big problem I’m having is that once I switched to a battery the touchscreen does not wake it up after a minute or so. I’m not sure what the problem is, in development I had it plugged into the USB port and was putting it into deep sleep. It would wake up from touches no matter how long it was in deep sleep… If anyone has any ideas it is greatly appreciated, right now you have to touch the button on the side to wake it up from deep sleep.

Here it is in action (I’ll clean up the code and publish soon):

7 Likes

Looking good!

I will note that I have found the screen to occasionally not register touches (and that’s when plugged into USB power) and being a little hit and miss with respect to being able to differentiate between single and double taps. With the unit connected to a battery, my theory is it is isolated from ground and further reduces the sensitivity of the screen to detect touches. Maybe could try to separately connect the screen to actual ground and see if that improves things?

Even so, for me at least, I think I can work within those restrictions so am happy with it!

Here is the code for the video uploaded earlier:
smart_switch/smart_switch_deepsleep.yaml at main · GadgetFactory-Jeannie/smart_switch (github.com)

This is an automation to make a HA light group follow this smart switch.
smart_switch/smart_switch_automation.yaml at main · GadgetFactory-Jeannie/smart_switch (github.com)

This works but I’m not super happy with it. These are the things that I don’t like:

  • You have to do a gesture twice to wake up from deep sleep. I just want to swipe down to turn off/on a light, not twice.
  • It is very difficult to touch the color wheel precisely enough to get the color you want.
  • I never got a chance to get espnow working with this so there is a delay after waking from deepsleep before it connects to HA and can control a light.

I’m leaning away from moving forward with this device and am going to focus more on an esp32-c6 device as a sleepy end device.

2 Likes

Thank you for your work on this. I am intending to power it permanently, so the wake up probably won’t be a concern.

Cheers.

Yes, I think I’m going to do the same, my kids really like it so I will probably keep this plugged in so they can change the color of lights. It works pretty well in that scenario.

1 Like

Hi, I’m getting this now:
ValueError: Component ID watchface was not declared to inherit from Component, or was registered twice.

and after some googling, found this:
There was a change in the display structure that breaks all external display components; the fix needs to be done in the external component. See landonr/lilygo-tdisplays3-esphome#46 for an example of the needed changes to have this compile again

Any idea how to workaround this?
EDIT:
after doing this:

external_components:
  - source: github://zagnuts/esphome-components
#    components: [ gc9a01 ]
  - source: github://GadgetFactory/[email protected] 

it finally starts to compile, but errors with:

INFO ESPHome 2023.12.5
INFO Reading configuration /config/esphome/smart-button.yaml...
WARNING GPIO2 is a strapping PIN and should only be used for I/O with care.
Attaching external pullup/down resistors to strapping pins can cause unexpected failures.
See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins
INFO Generating C++ source...
INFO Compiling app...
Processing smart-button (board: esp32-c3-devkitm-1; framework: arduino; platform: platformio/[email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
Dependency Graph
|-- AsyncTCP-esphome @ 2.0.1
|-- WiFi @ 2.0.0
|-- FS @ 2.0.0
|-- Update @ 2.0.0
|-- ESPAsyncWebServer-esphome @ 3.1.0
|-- DNSServer @ 2.0.0
|-- ESPmDNS @ 2.0.0
|-- noise-c @ 0.1.4
|-- SPI @ 2.0.0
|-- Wire @ 2.0.0
|-- CST816S @ 1.1.1+sha.dd4f520
Compiling .pioenvs/smart-button/src/esphome/components/animation/animation.cpp.o
Compiling .pioenvs/smart-button/src/esphome/components/api/list_entities.cpp.o
Compiling .pioenvs/smart-button/src/esphome/components/api/proto.cpp.o
Compiling .pioenvs/smart-button/src/esphome/components/api/subscribe_state.cpp.o
In file included from src/esphome/components/animation/animation.h:2,
                 from src/esphome/components/animation/animation.cpp:1:
src/esphome/components/image/image.h:34:41: error: expected class-name before '{' token
 class Image : public display::BaseImage {
                                         ^
src/esphome/components/image/image.h:42:36: error: 'esphome::display::Display' has not been declared
   void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override;
                                    ^~~~~~~
src/esphome/components/image/image.h:38:7: error: 'int esphome::image::Image::get_width() const' marked 'override', but does not override
   int get_width() const override;
       ^~~~~~~~~
src/esphome/components/image/image.h:39:7: error: 'int esphome::image::Image::get_height() const' marked 'override', but does not override
   int get_height() const override;
       ^~~~~~~~~~
src/esphome/components/image/image.h:42:8: error: 'void esphome::image::Image::draw(int, int, int*, esphome::Color, esphome::Color)' marked 'override', but does not override
   void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override;
        ^~~~
*** [.pioenvs/smart-button/src/esphome/components/animation/animation.cpp.o] Error 1
========================= [FAILED] Took 10.77 seconds =========================

Fix:

external_components:
#  - source: github://zagnuts/esphome-components
  - source: github://bearpawmaxim/esphome@pr3625fix
    components: [ gc9a01 ]
  - source: github://GadgetFactory/[email protected] 
display:
#  - platform: ili9xxx
#    model: gc9a01
# Above is for when or if this is merged into the ili9xxx platform
# Until then though, need to use an external component
  - platform: gc9a01
    id: watchface
    reset_pin: $repin
    cs_pin: $cspin
    dc_pin: $dcpin
3 Likes

For those people, who are using my fork of the display driver (github://bearpawmaxim/esphome@pr3625fix). I advise you to try to set 16bit color with the line eight_bit_color: false. You will get x2 increase of drawing speed and more essential colors. On the opposite side, it will consume x2 ram (115200 vs 57600) but that is not a problem because we have lots of it.

For anyone else, it is also a good idea to use the touchscreen driver from this pull request https://github.com/esphome/esphome/pull/5941

Config example for using the display and new touchscreen drivers:

external_components:
  - source: github://bearpawmaxim/esphome@pr3625fix
    components: [gc9a01]
  - source: github://pr#5941
    components: [cst816]

spi:
  mosi_pin: GPIO7
  clk_pin: GPIO6

i2c:
  sda: GPIO4
  scl: GPIO5

output:
  - platform: ledc
    pin: GPIO3
    id: gpio_3_backlight_pwm

light:
  - platform: monochromatic
    output: gpio_3_backlight_pwm
    name: "Display Backlight"
    id: backlight
    restore_mode: ALWAYS_ON

display:
#  - platform: ili9xxx
#    model: gc9a01
# Above is for when or if this is merged into the ili9xxx platform
  - platform: gc9a01
    id: watchface
    cs_pin: GPIO10
    dc_pin: GPIO2
    width: 240
    height: 240
    eight_bit_color: false
    rotation: 270
    update_interval: 1s
    lambda: |-
      ...

touchscreen:
  id: cst816d
  platform: cst816
  interrupt_pin: GPIO0
  reset_pin: GPIO1
  transform:
    swap_xy: true
    mirror_y: true
  on_touch:
    - ...

Full config can be found here

4 Likes

Nice, I’ve been using the display component on the M5Dial (which has the same display), and 2x draw speed would be a big improvement. Seems to work well, although might impact a little bit on the touch response for the ft3267 touchscreen.

1 Like

Could you add the color_wheel.jpg from your config to your github repo? Or at least specify the resolution and bit depth I should use to create my own?

Actually, I guess I’m missing even more, as the yaml fails to compile with this error:

display.gc9a01: [source <unicode string>:167]
  
  Pin 1 is used in multiple places.

Set backlight to lower brightness if needed, using 50% or less greatly lowers power usage. I used the below in Lambda to set it to 50%:
id(back_light).turn_on().set_brightness(0.5).perform()

Try:

#reset_pin: GPIO1

under

display:

Any idea how to detect swipe up, down, left and right with this library?
I can’t use single touch as it it often accidentally touched when picked up.

I suggest you read the changelog for esphome 2023.12. there are several relevant threads for that change.

I think you have to (very simplified):

  1. In on_touch, save the start coordinates to a variable.
  2. In on_update check how coordinates changed and, if changed for some amount of pixels in any direction, theat this as swipe. Update the variable also.
  3. In on_release validate whether it was a correct swipe and, if yes, do your logic.
1 Like

Hey Guys, thanks for your awesome work! I ordered this device a few month ago y couldn’t get it to work. A few days agoi stumbled by accident over this post and it worked like a charm!
Yesterday i tried expanding my code a bit by adding another sensor for home assistant, nothing related to GPIO, and now my ESP won’t boot properly, giving my this thru the usb-c log on web.esphome.io. :

ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x4038bece
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   281][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
[   280][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000

Then i tried GPIO8 as MISO pin. Since any output pin is used, that was my best guess. then i tried GPIO0 and both gave me this error log:

ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x4206f848
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40382602
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x438
load:0x403ce000,len:0x918
load:0x403d0000,len:0x24e4
entry 0x403ce000

I tried different libraries from this thread and strange enough, everytime i got the same error message.

[ 281][E][esp32-hal-spi.c:227] spiAttachMISO(): SPI Does not have default pins on ESP32C3!

Did anyone else enocounter this problem or maybe knows how to fix it?

No yaml, no issue.

I went back to the other library, because it is working fine for me and I only need to detect swipes and simple touch anywhere on the screen. Haven’t looked into this any more, as my use case was to use swipe instead of touch to prevent accidental touches when handling or picking up the device.
Overall this little device works great.
I tried BLE as a scanner or Proxy, but seems like it’s a bit too much for it to handle. It did detect a device, so it’s technically working.
One thing I never got to work was GIF animations, they were extremely slow, but maybe my display refresh was not defined and defaulted to 1s, I might come back to this, as I would like to show a little animated flame when heating is on.