Hey, I tried, but it doesn’t work when I change something in my sensor. However, if I leave it out, it works. Strange, but I need to take a closer look. Just like I still need to figure out how to add a new page, like you did. Have you also been working with the RFID reader sensor or not yet?
I would avoid updating to the latest version of esphome for the time being if you can. It seems to make everything poorly behaved, and all of my S3 devices will only boot up I connect via a usb-c cable and connect the logger (via com ports).
Additionally, there are changes to the way the polling component of the display works, and the remote github repository hasn’t been updated.
Digging into it at the moment.
Looks like esphome 2023.12.3 fixes the issues… partially. You just need to update the external component reference to my repository where I updated the gc9a01 component
external_components:
- source: github://dgaust/esphome@gc9a01
components: [ gc9a01 ]
can not update this erro ?
Failed config
touchscreen.lilygo_t5_47: [source <unicode string>:91]
Couldn't find any component that can be used for 'display::Display'. Are you missing a hub declaration?.
platform: lilygo_t5_47
interrupt_pin:
number: 14
mode:
input: True
output: False
open_drain: False
pullup: False
pulldown: False
inverted: False
ignore_strapping_warning: False
drive_strength: 20.0
i2c_id: bus_internal
id: my_touchscreen
on_touch:
then:
- logger.log:
format: touched
args: []
tag: main
level: DEBUG
update_interval: 50ms
address: 0x5A
Remove the whole code. It’s not relevant, wrong touchscreen.
This section is for the RFID reader Jarne.
rc522_i2c:
i2c_id: bus_internal
address: 0x28
on_tag:
then:
- rtttl.play: "success:d=24,o=5,b=100:c,g,b"
- homeassistant.tag_scanned: !lambda 'return x;
When I scan a new NFC card, HA adds it to my tags list.
I think you are missing some punctuation. But besides that, I have not been able to get this to work. I am wondering why…the rc522 doesnt respond at all. Are you doing some other setup besides the i2c?
When you say doesn’t respond at all, what are you testing with?
It will only work with RFID cards and tags operating at 13.56MHz.
I2C setup -
i2c:
- id: bus_internal
sda: GPIO11
scl: GPIO12
- id: bus_porta
sda: GPIO13
scl: GPIO15
# interrupt: 14
Setup for reader - rtttl wont work unless you have all the other components setup.
It can be commented out for testing.
rc522_i2c:
i2c_id: bus_internal
address: 0x28
on_tag:
then:
- rtttl.play: "success:d=24,o=5,b=100:c,g,b"
- homeassistant.tag_scanned: !lambda 'return x;'
Output from logs on reader with device discovery on I2C and when a new card is scanned.
[10:00:24][C][logger:443]: Logger:
[10:00:24][C][logger:444]: Level: DEBUG
[10:00:24][C][logger:445]: Log Baud Rate: 115200
[10:00:24][C][logger:447]: Hardware UART: USB_CDC
[10:00:25][C][i2c.arduino:053]: I2C Bus:
[10:00:25][C][i2c.arduino:054]: SDA Pin: GPIO11
[10:00:25][C][i2c.arduino:055]: SCL Pin: GPIO12
[10:00:25][C][i2c.arduino:056]: Frequency: 50000 Hz
[10:00:25][C][i2c.arduino:059]: Recovery: bus successfully recovered
[10:00:25][I][i2c.arduino:069]: Results from i2c bus scan:
[10:00:25][I][i2c.arduino:075]: Found i2c device at address 0x28
[10:00:25][I][i2c.arduino:075]: Found i2c device at address 0x38
[10:00:25][I][i2c.arduino:075]: Found i2c device at address 0x51
[10:00:25][C][i2c.arduino:053]: I2C Bus:
[10:00:25][C][i2c.arduino:054]: SDA Pin: GPIO13
[10:00:25][C][i2c.arduino:055]: SCL Pin: GPIO15
[10:00:25][C][i2c.arduino:056]: Frequency: 50000 Hz
[10:00:25][C][i2c.arduino:059]: Recovery: bus successfully recovered
[10:00:25][I][i2c.arduino:069]: Results from i2c bus scan:
[10:00:25][I][i2c.arduino:071]: Found no i2c devices!
[10:00:36][D][rtttl:051]: Playing song success
[10:00:36][D][rc522:263]: Found new tag '04-77-42-C4-08-43-70'
It is very random when it will respond. About 1 out of every 20 taps/waves it registers. I just had to keep trying to get it to work…but I wouldn’t say that means it is working. I wonder what tuning it needs…
It looks like quite a bit of work is going into this m5Dial device.
I ordered a few to have a play with and am struggling to get it to install on the device.
It looks like things have changed with how a display registers now with the latest versions of ESPhome.
“ValueError: Component ID my_lcd was not declared to inherit from Component, or was registered twice. Please create a bug report with your configuration.”
From reading others have had a similar issue, but with existing devices that they were just wanting to update.
This was the example of what needed to be changed…
In the last release of ESPHome, some small changes were done to the display component, to make subcomponents leaner. With those changes, compilation breaks if a display is trying to register as a component itself (this is now done automatically when registering the display).
Also, DisplayBuffer now automatically inherits from PollingComponent, so there is no need to explicitly inherit from that.
This is probably a breaking change if someone uses a lower version of esphome after this is merged.
From the above example does anyone have any ideas how to actually fix the yaml that has been shared in the above posts?
Thanks heaps!
I am facing the same issue:
INFO ESPHome 2023.12.5
INFO Reading configuration /config/esphome/m5dial1.yaml...
INFO Generating C++ source...
Traceback (most recent call last):
File "/usr/local/bin/esphome", line 33, in <module>
sys.exit(load_entry_point('esphome', 'console_scripts', 'esphome')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/esphome/esphome/__main__.py", line 1041, in main
return run_esphome(sys.argv)
^^^^^^^^^^^^^^^^^^^^^
File "/esphome/esphome/__main__.py", line 1028, in run_esphome
rc = POST_CONFIG_ACTIONS[args.command](args, config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/esphome/esphome/__main__.py", line 458, in command_run
exit_code = write_cpp(config)
^^^^^^^^^^^^^^^^^
File "/esphome/esphome/__main__.py", line 192, in write_cpp
generate_cpp_contents(config)
File "/esphome/esphome/__main__.py", line 204, in generate_cpp_contents
CORE.flush_tasks()
File "/esphome/esphome/core/__init__.py", line 679, in flush_tasks
self.event_loop.flush_tasks()
File "/esphome/esphome/coroutine.py", line 246, in flush_tasks
next(task.iterator)
File "/esphome/esphome/__main__.py", line 184, in wrapped
await coro(conf)
File "/data/external_components/c9069712/esphome/components/gc9a01/display.py", line 77, in to_code
await setup_gc9a01(var, config)
File "/data/external_components/c9069712/esphome/components/gc9a01/display.py", line 56, in setup_gc9a01
await display.register_display(var, config)
File "/esphome/esphome/components/display/__init__.py", line 119, in register_display
await cg.register_component(var, config)
File "/esphome/esphome/cpp_helpers.py", line 56, in register_component
raise ValueError(
ValueError: Component ID my_lcd was not declared to inherit from Component, or was registered twice. Please create a bug report with your configuration.
using:
esphome:
name: m5dial1
friendly_name: m5dial1
on_boot:
priority: 100
then:
- logger.log: "Startup - Backlight on"
- lambda: |-
id(oledbacklight).set_level(0.7);
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "APIKEY"
ota:
password: "otapassword"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "M5Dial1 Fallback Hotspot"
password: "HL2GnCGseKUb"
captive_portal:
globals:
- id: screenwidth
type: int
restore_value: no
- id: max_rotary_value
type: int
restore_value: no
initial_value: '1'
- id: min_rotary_value
type: int
restore_value: no
initial_value: '100'
external_components:
- source: github://the-smart-home-maker/esphome-4cello@gc9a01
components: ["gc9a01"]
i2c:
- id: bus_internal
sda: GPIO11
scl: GPIO12
- id: bus_porta
sda: 13
scl: 15
# interrupt: 14
image:
- file: mdi:volume-low
id: volume_notmute_80
resize: 80x80
font:
- file: "gfonts://Roboto"
id: roboto16
size: 16
- file: "gfonts://Roboto"
id: roboto20
size: 20
- file: "gfonts://Roboto"
id: roboto24
size: 24
rc522_i2c:
i2c_id: bus_internal
address: 0x28
on_tag:
then:
- homeassistant.tag_scanned: !lambda 'return x;'
#touchscreen:
# - platform: lilygo_t5_47
# interrupt_pin: GPIO14
# i2c_id: bus_internal
# id: my_touchscreen
# on_touch:
# - logger.log: "touched"
spi:
mosi_pin: GPIO5
clk_pin: GPIO6
display:
- platform: gc9a01
reset_pin: GPIO8
id: my_lcd
cs_pin: GPIO7
dc_pin: GPIO4
rotation: 90
pages:
- id: page1
lambda: |-
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
it.image(halfscreenwidth, halfscreenheight -55, volume_notmute_80, ImageAlign::TOP_CENTER);
it.filled_circle(halfscreenwidth -12, 225, 3);
it.circle(halfscreenwidth, 225, 3);
it.circle(halfscreenwidth +12, 225, 3);
# on_page_change:
# - to: page1
# then:
# - sensor.rotary_encoder.set_value:
# id: rotaryencoder
# value: !lambda 'return id(workshop_volume).state * 100;'
# - component.update: my_lcd
binary_sensor:
- platform: gpio
pin: GPIO42
name: "BacklightButton"
sensor:
- platform: rotary_encoder
name: "Rotary Encoder"
id: rotaryencoder
max_value: 100
min_value: 0
pin_a:
number: GPIO40
mode:
input: true
pullup: true
pin_b:
number: GPIO41
mode:
input: true
pullup: true
accuracy_decimals: 1
on_value:
- lambda: |-
id(oledbacklight).set_level(0.7);
# - component.update: my_lcd
on_clockwise:
- display.page.show_next: my_lcd
- component.update: my_lcd
on_anticlockwise:
- display.page.show_previous: my_lcd
- component.update: my_lcd
light:
- platform: monochromatic
id: backlight
name: "Backlight"
output: oledbacklight
default_transition_length: 250ms
output:
- id: oledbacklight
platform: ledc
pin: GPIO9
#pin: GPIO21
max_power: 1
min_power: 0
Was fixed here
hallo what you full code ? can you pleas deel this ?
My code is not going to help much Jarne as it’s custom to my setup, very much still a work in progress and there is a lot of unnecessary code for customizing for yourself.
I am using the Smart Knob for controlling media player volume, ventilation fan sped and dust extractor speed for my workshop. I have not completed the dust extractor page as I still need to integrate to my PLC.
The pages are changed by buttons on a keypad a 4 x 3 keypad installed beside the smart knob. I have automations in Home Assistant to revert the page back to volume control after 10 seconds so the vent fan or dust extraction can be changed via the smart knob, but then it reverts back to volume control.
Not sure if other people have tried the external I2C connectors, but I could not get it to work at all. I need to look at the schematics to see if it has internal pull ups.
esphome:
name: workshop-rotary-test
friendly_name: workshop-rotary-test
on_boot:
priority: 100
then:
- logger.log: "Startup - Backlight on"
- lambda: |-
id(oledbacklight).set_level(0.7);
id(page1binary).publish_state(true);
id(page2binary).publish_state(false);
id(page3binary).publish_state(false);
# Formatted:
- logger.log:
format: "Vent fan Speed is %.1f"
args: [ 'id(vent_fan_speed).state' ]
# Enable Home Assistant API
api:
encryption:
key: API_KEY
ota:
password: OTA_PASSWORD
globals:
- id: screenwidth
type: int
restore_value: no
- id: max_rotary_value
type: int
restore_value: no
initial_value: '1'
- id: min_rotary_value
type: int
restore_value: no
initial_value: '100'
external_components:
- source: github://dgaust/esphome@gc9a01
components: [ gc9a01 ]
i2c:
- id: bus_internal
sda: GPIO11
scl: GPIO12
- id: bus_porta
sda: GPIO13
scl: GPIO15
# interrupt: 14
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Enable logging
logger:
level: DEBUG
color:
- id: my_red
red: 100%
green: 3%
blue: 5%
- id: my_green
hex: 59981A
- id: my_blue
red: 3%
green: 5%
blue: 100%
- id: my_yellow
hex: FFFF00
- id: my_light_blue
hex: 145DA0
- id: my_light_red
hex: fc6d6d
- id: my_light_orange
hex: FD7F20
- id: my_light_yellow
hex: B58B00
image:
- file: mdi:volume-variant-off
id: volume_mute
resize: 40x40
- file: mdi:volume-low
id: volume_notmute
resize: 40x40
- file: mdi:fan
id: fan_40
resize: 40x40
- file: mdi:weather-tornado
id: cyclone_icon_40
resize: 40x40
- file: mdi:weather-tornado
id: cyclone_icon_80
resize: 80x80
- file: mdi:fan
id: fan_80
resize: 80x80
- file: mdi:knob
id: volumeknob
resize: 80x80
- file: mdi:volume-low
id: volume_notmute_80
resize: 80x80
- file: mdi:volume-variant-off
id: volume_mute_80
resize: 80x80
font:
- file: "fonts/arial.ttf"
id: my_font
size: 40
- file: "gfonts://Roboto"
id: roboto16
size: 16
- file: "gfonts://Roboto"
id: roboto20
size: 20
- file: "gfonts://Roboto"
id: roboto24
size: 24
- file: "gfonts://Roboto"
id: roboto40
size: 40
wifi:
ssid: WIFI_SSID
password: WIFI_PASSWRD
captive_portal:
rc522_i2c:
i2c_id: bus_internal
address: 0x28
on_tag:
then:
- rtttl.play: "success:d=24,o=5,b=100:c,g,b"
- homeassistant.tag_scanned: !lambda 'return x;'
spi:
mosi_pin: GPIO5
clk_pin: GPIO6
display:
- platform: gc9a01
reset_pin: GPIO8
id: my_lcd
cs_pin: GPIO7
dc_pin: GPIO4
rotation: 90
pages:
- id: page1
lambda: |-
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
if (id(mediaplayermute).state == "on")
{
it.image(halfscreenwidth, halfscreenwidth -55, volume_mute_80, ImageAlign::TOP_CENTER);
}
else
{
it.start_clipping(0, ((id(beam_volume).state * -1) * 300) + 155, 250, 250);
it.filled_circle(halfscreenwidth, screenheight, 255, my_light_yellow);
it.end_clipping();
it.image(halfscreenwidth, halfscreenheight -55, volume_notmute_80, ImageAlign::TOP_CENTER);
}
it.printf(halfscreenwidth, halfscreenheight + 35, id(roboto40), TextAlign::TOP_CENTER, "%.0f%%", id(beam_volume).state * 100);
it.filled_circle(halfscreenwidth -12, 225, 3);
it.circle(halfscreenwidth, 225, 3);
it.circle(halfscreenwidth +12, 225, 3);
id(page1binary).publish_state(true);
id(page2binary).publish_state(false);
id(page3binary).publish_state(false);
- id: page2
lambda: |-
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
it.image(halfscreenwidth, halfscreenheight - 55, fan_80, ImageAlign::TOP_CENTER);
it.printf(halfscreenwidth, halfscreenheight + 35, id(roboto24), TextAlign::TOP_CENTER, "%.0f%%", id(vent_fan_speed).state);
it.circle(halfscreenwidth -12, 225, 3);
it.filled_circle(halfscreenwidth, 225, 3);
it.circle(halfscreenwidth +12, 225, 3);
id(page1binary).publish_state(false);
id(page2binary).publish_state(true);
id(page3binary).publish_state(false);
- id: page3
lambda: |-
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
it.image(halfscreenwidth, halfscreenheight - 55, cyclone_icon_80, ImageAlign::TOP_CENTER);
it.printf(halfscreenwidth, halfscreenheight + 35, id(roboto24), TextAlign::TOP_CENTER, "%.0f%%", id(vent_fan_speed).state);
it.circle(halfscreenwidth -12, 225, 3);
it.circle(halfscreenwidth, 225, 3);
it.filled_circle(halfscreenwidth +12, 225, 3);
id(page1binary).publish_state(false);
id(page2binary).publish_state(false);
id(page3binary).publish_state(true);
on_page_change:
- to: page1
then:
- sensor.rotary_encoder.set_value:
id: rotaryencoder
value: !lambda 'return id(beam_volume).state * 100;'
- component.update: my_lcd
binary_sensor:
- platform: gpio
pin: GPIO42
name: "BacklightButton"
on_press:
- if:
condition:
- display.is_displaying_page: page1
then:
if:
condition:
lambda: return id(mediaplayermute).state == "off";
then:
- logger.log:
format: "The mediaplayer sensor reports value %s"
args: [ 'id(mediaplayermute).state' ]
- homeassistant.service:
service: media_player.volume_mute
data:
entity_id: media_player.workshop
is_volume_muted: 'true'
else:
- logger.log:
format: "The mediaplayer sensor reports value %s"
args: [ 'id(mediaplayermute).state' ]
- homeassistant.service:
service: media_player.volume_mute
data:
entity_id: media_player.workshop
is_volume_muted: 'false'
- platform: homeassistant
name: "keypad6"
id: "fan_button"
entity_id: binary_sensor.keypadkey_6
on_state:
then:
- display.page.show: page2
- component.update: my_lcd
- platform: homeassistant
name: "keypad9"
id: "dusty_button"
entity_id: binary_sensor.keypadkey_9
on_state:
then:
- display.page.show: page3
- component.update: my_lcd
- platform: homeassistant
name: "testbinary"
id: "testbinary"
entity_id: binary_sensor.test_binary
on_state:
then:
- display.page.show: page2
- component.update: my_lcd
- delay: 10s
- display.page.show: page1
- platform: template
name: "Page 1 Active"
id: page1binary
- platform: template
name: "Page 2 Active"
id: page2binary
- platform: template
name: "Page 3 Active"
id: page3binary
sensor:
- platform: rotary_encoder
name: "Rotary Encoder"
id: rotaryencoder
max_value: 100
min_value: 0
pin_a:
number: GPIO40
mode:
input: true
pullup: true
pin_b:
number: GPIO41
mode:
input: true
pullup: true
accuracy_decimals: 1
on_clockwise:
- rtttl.play: quick_e:d=4,o=5,b=100:16e6
on_anticlockwise:
- rtttl.play: quick_d:d=4,o=5,b=100:16d6
- platform: homeassistant
name: "Media Volume"
id: "beam_volume"
entity_id: media_player.workshop
attribute: volume_level
light:
- platform: monochromatic
id: backlight
name: "Backlight"
output: oledbacklight
default_transition_length: 250ms
output:
- id: oledbacklight
platform: ledc
pin: GPIO9
#pin: GPIO21
max_power: 1
min_power: 0
- platform: ledc
id: buzzer_out
pin:
number: GPIO3
# Enable ringtone music support
rtttl:
id: buzzer
output: buzzer_out
text_sensor:
- platform: homeassistant
name: "Media Player Mute"
id: "mediaplayermute"
entity_id: media_player.workshop
attribute: is_volume_muted
on_value:
then:
- component.update: my_lcd
- platform: homeassistant
name: "Vent Fan Status"
id: vent_fan
entity_id: switch.vent_fan
on_value:
- component.update: my_lcd
- platform: homeassistant
name: "Vent Fan Speed"
id: vent_fan_speed
entity_id: input_number.vent_fan_speed
on_value:
- component.update: my_lcd
Great! your config helped me get going a lot. Thanks
Do you use an automation to actually change the volume? and if so why did you not map it directly to the media player volume?
Thanks heaps, i missed the new repo URL
Yeah I use an automation that selects the variable to be changed - Volume, Fan Speed, etc, depending what page is showing on the rotary encoder. But it’s still very much a work in progress. The example earlier from dgaust shows another working method.
Again, huge thanks to @dgaust for sharing his code and work on this.
I have touch semi working on this, but currently just getting gibberish from the i2c registers. I think that the touchscreen is at address 0x38 and the RTC at 0x51 based on experimentation and the ft3267 documentation and examples. Definitely need some additional work, but I’ve not had much opportunity over the holidays.
I can however change the page based on a touch, which is useful (although sometimes reads two touches).
You can try it by updating the external components reference to - the refresh just means you’ll always get the most latest version when you compile
external_components:
- source: github://dgaust/esphome@gc9a01
components: [ gc9a01, ft3267_touchscreen ]
refresh: 0s
And then define the touchscreen as below.
ft3267_touchscreen:
id: ft3267_touch
address: 0x38
interrupt_pin: GPIO14
on_release:
then:
- display.page.show_next: my_lcd
For the rotary encoder, I then have it setup to do some stuff depending on what page it’s on. Setting the light brightness works, but it’s really dumb at the moment. It needs some checks for when brightness is at its min/max, but it works well enough.
sensor:
- platform: rotary_encoder
name: "Rotary Encoder"
id: rotaryencoder
pin_a:
number: GPIO40
mode:
input: true
pullup: true
pin_b:
number: GPIO41
mode:
input: true
pullup: true
accuracy_decimals: 1
on_clockwise:
- if:
condition:
- display.is_displaying_page: page1
then:
- homeassistant.service:
service: light.turn_on
data:
entity_id: light.great_room_dimmer_4
brightness: !lambda int brightness = id(dimmersensor_brightness).state + 15; return brightness;
- component.update: my_lcd
- if:
condition:
- display.is_displaying_page: page2
then:
- homeassistant.service:
service: climate.set_temperature
data:
entity_id: climate.doris
temperature: !lambda return (id(climatedevice_setpoint).state + 1);
- component.update: my_lcd
- if:
condition:
- display.is_displaying_page: page3
then:
- homeassistant.service:
service: media_player.volume_up
data:
entity_id: media_player.living_room
- component.update: my_lcd
on_anticlockwise:
- if:
condition:
- display.is_displaying_page: page1
then:
- homeassistant.service:
service: light.turn_on
data:
entity_id: light.great_room_dimmer_4
brightness: !lambda int brightness = id(dimmersensor_brightness).state - 15; return brightness;
- component.update: my_lcd
- if:
condition:
- display.is_displaying_page: page2
then:
- homeassistant.service:
service: climate.set_temperature
data:
entity_id: climate.doris
temperature: !lambda return (id(climatedevice_setpoint).state - 1);
- component.update: my_lcd
- if:
condition:
- display.is_displaying_page: page3
then:
- homeassistant.service:
service: media_player.volume_down
data:
entity_id: media_player.living_room
- component.update: my_lcd
Great with the touchscreen - Thanks !
I get this however:
INFO ESPHome 2023.12.5
INFO Reading configuration /config/esphome/m5dial1.yaml...
INFO Updating https://github.com/dgaust/esphome.git@gc9a01
WARNING GPIO3 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
Failed config
ft3267_touchscreen: [source <unicode string>:57]
Too many candidates found for 'i2c_id' type 'i2c::I2CBus' Some are 'bus_internal', 'bus_porta'.
id: ft3267_touch
address: 0x38
interrupt_pin:
number: 14
mode:
input: True
output: False
open_drain: False
pullup: False
pulldown: False
inverted: False
ignore_strapping_warning: False
drive_strength: 20.0
on_release:
then:
- display.page.show_next:
id: my_lcd
update_interval: 50ms