Closed nigels0 closed 1 month ago
The 4 purple "blinking" lights (not really binking, but rather with random intensity) mean it's listening for wake word.
Could you please ellaborate a bit on "it's not working"? What have you tried? What are you expecting it to do?
Well it isn't blinking - just a solid four sets of purple lights.
On powering on, it goes white, then flashes green for a while then just the four purple lights. I've connected it to HA (it seems OK) -
I'm trying to set this up to use OpenWakeWord (the voice parts otherwise work fine from accessing via Assist on my phone. Pressing near the four purple lights doesn't do anything, though volume up/down is working fine.
here is the log: < INFO ESPHome 2024.3.2 INFO Reading configuration /config/esphome/onju-1.yaml... INFO Starting log output from 192.168.10.212 using esphome API INFO Successfully connected to onju-voice1 @ 192.168.10.212 in 0.006s INFO Successful handshake with onju-voice1 @ 192.168.10.212 in 0.077s [16:52:28][I][app:102]: ESPHome version 2024.3.2 compiled on Apr 8 2024, 16:44:37
[16:52:28][C][wifi:408]: Local MAC: 80:65:99:C6:44:70 [16:52:28][C][wifi:413]: SSID: 'WaysIoT'[redacted] [16:52:28][C][wifi:416]: IP Address: 192.168.10.212 [16:52:28][C][wifi:420]: BSSID: 26:5A:4C:2C:EE:D5[redacted]
[16:52:28][C][wifi:423]: Signal strength: -62 dB ▂▄▆█ [16:52:28][C][wifi:427]: Channel: 6 [16:52:28][C][wifi:428]: Subnet: 255.255.255.0 [16:52:28][C][wifi:429]: Gateway: 192.168.10.1 [16:52:28][C][wifi:430]: DNS1: 1.1.1.1 [16:52:28][C][wifi:431]: DNS2: 9.9.9.9
[16:52:28][C][logger:167]: Level: DEBUG [16:52:28][C][logger:169]: Log Baud Rate: 115200 [16:52:28][C][logger:170]: Hardware UART: USB_CDC [16:52:28][C][template.number:050]: Template Number 'Touch threshold percentage' [16:52:28][C][template.number:051]: Optimistic: YES [16:52:28][C][template.number:052]: Update Interval: never [16:52:28][C][esp32_rmt_led_strip:175]: ESP32 RMT LED Strip: [16:52:28][C][esp32_rmt_led_strip:176]: Pin: 11 [16:52:28][C][esp32_rmt_led_strip:177]: Channel: 0 [16:52:28][C][esp32_rmt_led_strip:202]: RGB Order: GRB [16:52:28][C][esp32_rmt_led_strip:203]: Max refresh rate: 0 [16:52:28][C][esp32_rmt_led_strip:204]: Number of LEDs: 6 [16:52:28][C][gpio.binary_sensor:015]: GPIO Binary Sensor 'Disable wake word' [16:52:28][C][gpio.binary_sensor:016]: Pin: GPIO38
[16:52:28][C][light:105]: Default Transition Length: 0.0s [16:52:28][C][light:106]: Gamma Correct: 2.80
[16:52:28][C][light:105]: Default Transition Length: 1.0s [16:52:28][C][light:106]: Gamma Correct: 2.80
[16:52:28][C][light:105]: Default Transition Length: 1.0s [16:52:28][C][light:106]: Gamma Correct: 2.80
[16:52:28][C][light:105]: Default Transition Length: 1.0s [16:52:28][C][light:106]: Gamma Correct: 2.80 [16:52:28][C][template.switch:068]: Template Switch 'Use Wake Word' [16:52:28][C][template.switch:091]: Restore Mode: restore defaults to ON [16:52:28][C][template.switch:057]: Optimistic: YES [16:52:28][C][esp32_touch:073]: Config for ESP32 Touch Hub: [16:52:28][C][esp32_touch:074]: Meas cycle: 0.80ms [16:52:28][C][esp32_touch:075]: Sleep cycle: 2.00ms [16:52:28][C][esp32_touch:095]: Low Voltage Reference: 0.8V [16:52:28][C][esp32_touch:115]: High Voltage Reference: 2.4V [16:52:28][C][esp32_touch:135]: Voltage Attenuation: 0V [16:52:28][C][esp32_touch:169]: Filter mode: IIR_16 [16:52:28][C][esp32_touch:170]: Debounce count: 2 [16:52:28][C][esp32_touch:171]: Noise threshold coefficient: 0 [16:52:28][C][esp32_touch:172]: Jitter filter step size: 0 [16:52:28][C][esp32_touch:191]: Smooth level: IIR_2 [16:52:28][C][esp32_touch:213]: Denoise grade: BIT8 [16:52:28][C][esp32_touch:245]: Denoise capacitance level: L0 [16:52:28][C][esp32_touch:260]: Touch Pad 'volume_down' [16:52:28][C][esp32_touch:261]: Pad: T4 [16:52:28][C][esp32_touch:262]: Threshold: 483444 [16:52:28][C][status:034]: Status Binary Sensor 'api_connection' [16:52:28][C][status:034]: Device Class: 'connectivity' [16:52:28][C][captive_portal:088]: Captive Portal:
[16:52:28][C][mdns:116]: Hostname: onju-voice1 [16:52:28][C][ota:096]: Over-The-Air Updates: [16:52:28][C][ota:097]: Address: onju-voice1.local:3232 [16:52:28][C][ota:103]: OTA version: 2. [16:52:28][C][api:139]: API Server: [16:52:28][C][api:140]: Address: onju-voice1.local:6053 [16:52:28][C][api:142]: Using noise encryption: YES
[16:52:28][C][audio:225]: External DAC channels: 1 [16:52:28][C][audio:226]: I2S DOUT Pin: 12 [16:52:28][C][audio:227]: Mute Pin: GPIO21
So even when you press the top, the volume tabs, anything at all, the logs don't register anything?
Make sure the physical switch is not set to Mute. Try toggling the "Use wake word" virtual switch in HA.
Although, the main issue that all your lights are solid purple. I don't think there's any case in which the config makes all top LEDs turn solid purple. Could you paste the entire config you used, too, please?
**definitely purple!
Sorry - I wasn't clear - yes the buttons work - volume down gives:**
[15:05:11][D][binary_sensor:036]: 'volume_down': Sending state ON
[15:05:11][D][light:036]: 'left_led' Setting:
[15:05:11][D][light:047]: State: ON
[15:05:11][D][light:085]: Transition length: 1.0s
[15:05:11][D][media_player:059]: 'Onju Voice 1' - Setting
[15:05:11][D][media_player:069]: Volume: 0.85
[15:05:11][D][light:036]: 'top_led' Setting:
[15:05:11][D][light:109]: Effect: 'show_volume'
[15:05:11][D][binary_sensor:036]: 'volume_down': Sending state OFF
[15:05:11][D][light:036]: 'left_led' Setting:
[15:05:11][D][light:047]: State: OFF
[15:05:11][D][light:085]: Transition length: 1.0s
[15:05:12][D][light:036]: 'top_led' Setting:
[15:05:12][D][light:051]: Brightness: 100%
[15:05:12][D][light:059]: Red: 100%, Green: 0%, Blue: 100%
[15:05:12][D][light:085]: Transition length: 1.0s
[15:05:12][D][light:091]: Effect: 'None'
The lights go briefly white to show the volume level - then back to four purples!
Here's my config file:
captive_portal:
substitutions:
name: "onju-voice1"
friendly_name: "Onju Voice 1"
esphome:
name: ${name}
friendly_name: ${friendly_name}
name_add_mac_suffix: false
min_version: 2023.10.1
on_boot:
then:
- light.turn_on:
id: top_led
effect: slow_pulse
red: 100%
green: 60%
blue: 0%
- wait_until:
condition:
wifi.connected:
- light.turn_on:
id: top_led
effect: pulse
red: 0%
green: 100%
blue: 0%
- wait_until:
condition:
api.connected:
- light.turn_on:
id: top_led
effect: none
red: 0%
green: 100%
blue: 0%
- delay: 1s
- script.execute: reset_led
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
logger:
api:
encryption:
key: "GBQg79HCLfP6e0JWW/rHLRkpLhctZkt2O/75quNEqO8="
services:
- service: start_va
then:
- voice_assistant.start
- service: stop_va
then:
- voice_assistant.stop
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Onju-1 Fallback Hotspot"
password: "IKEtRK2suWwy"
globals:
- id: thresh_percent
type: float
initial_value: "0.03"
restore_value: false
- id: touch_calibration_values_left
type: uint32_t[5]
restore_value: false
- id: touch_calibration_values_center
type: uint32_t[5]
restore_value: false
- id: touch_calibration_values_right
type: uint32_t[5]
restore_value: false
interval:
- interval: 1s
then:
- script.execute:
id: calibrate_touch
button: 0
- script.execute:
id: calibrate_touch
button: 1
- script.execute:
id: calibrate_touch
button: 2
i2s_audio:
- i2s_lrclk_pin: GPIO13
i2s_bclk_pin: GPIO18
media_player:
- platform: i2s_audio
name: None
id: onju_out
dac_type: external
i2s_dout_pin: GPIO12
mode: mono
mute_pin:
number: GPIO21
inverted: True
######
# speaker:
# - platform: i2s_audio
# id: onju_out
# dac_type: external
# i2s_dout_pin: GPIO12
# mode: stereo
######
microphone:
- platform: i2s_audio
id: onju_microphone
i2s_din_pin: GPIO17
adc_type: external
pdm: false
voice_assistant:
id: va
microphone: onju_microphone
media_player: onju_out
######
# speaker: onju_out
######
use_wake_word: true
on_start:
- light.turn_on:
id: top_led
blue: 100%
red: 0%
green: 0%
effect: none
on_listening:
- light.turn_on:
id: top_led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: pulse
on_tts_end:
- media_player.play_media: !lambda return x;
- light.turn_on:
id: top_led
blue: 0%
red: 20%
green: 100%
effect: pulse
on_end:
- delay: 100ms
- wait_until:
not:
media_player.is_playing: onju_out
- script.execute: reset_led
on_client_connected:
- if:
condition:
and:
- switch.is_on: use_wake_word
- binary_sensor.is_off: mute_switch
then:
- voice_assistant.start_continuous:
on_client_disconnected:
- if:
condition:
and:
- switch.is_on: use_wake_word
- binary_sensor.is_off: mute_switch
then:
- voice_assistant.stop:
on_error:
- light.turn_on:
id: top_led
blue: 0%
red: 100%
green: 0%
- delay: 1s
- script.execute: reset_led
number:
- platform: template
name: "Touch threshold percentage"
id: touch_threshold_percentage
update_interval: never
entity_category: config
initial_value: 1.25
min_value: -1
max_value: 5
step: 0.25
optimistic: true
on_value:
then:
- lambda: !lambda |-
id(thresh_percent) = 0.01 * x;
esp32_touch:
setup_mode: false
sleep_duration: 2ms
measurement_duration: 800us
low_voltage_reference: 0.8V
high_voltage_reference: 2.4V
filter_mode: IIR_16
debounce_count: 2
noise_threshold: 0
jitter_step: 0
smooth_mode: IIR_2
denoise_grade: BIT8
denoise_cap_level: L0
binary_sensor:
- platform: esp32_touch
id: volume_down
pin: GPIO4
threshold: 539000 # 533156-551132
on_press:
then:
- light.turn_on: left_led
- script.execute:
id: set_volume
volume: -0.05
- delay: 1s
- while:
condition:
binary_sensor.is_on: volume_down
then:
- script.execute:
id: set_volume
volume: -0.05
- delay: 150ms
on_release:
then:
- light.turn_off: left_led
- platform: esp32_touch
id: volume_up
pin: GPIO2
threshold: 580000 # 575735-593064
on_press:
then:
- light.turn_on: right_led
- script.execute:
id: set_volume
volume: 0.05
- delay: 1s
- while:
condition:
binary_sensor.is_on: volume_up
then:
- script.execute:
id: set_volume
volume: 0.05
- delay: 150ms
on_release:
then:
- light.turn_off: right_led
- platform: esp32_touch
id: action
pin: GPIO3
threshold: 751000 # 745618-767100
on_click:
- if:
condition:
or:
- switch.is_off: use_wake_word
- binary_sensor.is_on: mute_switch
then:
- if:
condition: voice_assistant.is_running
then:
- voice_assistant.stop:
- script.execute: reset_led
else:
- voice_assistant.start:
else:
- voice_assistant.stop
- delay: 1s
- script.execute: reset_led
- script.wait: reset_led
- voice_assistant.start_continuous:
- platform: gpio
id: mute_switch
pin:
number: GPIO38
mode: INPUT_PULLUP
name: Disable wake word
on_press:
- script.execute: turn_on_wake_word
on_release:
- script.execute: turn_off_wake_word
- platform: status
id: api_connection
filters:
- delayed_on: 1s
on_press:
- if:
condition:
and:
- switch.is_on: use_wake_word
- binary_sensor.is_off: mute_switch
then:
- voice_assistant.start_continuous:
on_release:
- if:
condition:
and:
- switch.is_on: use_wake_word
- binary_sensor.is_off: mute_switch
then:
- voice_assistant.stop:
light:
- platform: esp32_rmt_led_strip
id: leds
pin: GPIO11
chipset: SK6812
num_leds: 6
rgb_order: grb
rmt_channel: 0
default_transition_length: 0s
gamma_correct: 2.8
- platform: partition
id: left_led
segments:
- id: leds
from: 0
to: 0
- platform: partition
id: top_led
segments:
- id: leds
from: 1
to: 4
effects:
- pulse:
name: pulse
transition_length: 250ms
update_interval: 250ms
- pulse:
name: slow_pulse
transition_length: 1s
update_interval: 2s
- addressable_lambda:
name: show_volume
update_interval: 50ms
lambda: |-
int int_volume = int(id(onju_out).volume * 100.0f * it.size());
int full_leds = int_volume / 100;
int last_brightness = int_volume % 100;
int i = 0;
for(; i < full_leds; i++) {
it[i] = Color::WHITE;
}
if(i < 4) {
it[i++] = Color(0,0,0).fade_to_white(last_brightness*256/100);
}
for(; i < it.size(); i++) {
it[i] = Color::BLACK;
}
- platform: partition
id: right_led
segments:
- id: leds
from: 5
to: 5
script:
- id: reset_led
then:
- if:
condition:
and:
- switch.is_on: use_wake_word
- binary_sensor.is_off: mute_switch
then:
- light.turn_on:
id: top_led
blue: 100%
red: 100%
green: 0%
brightness: 100%
effect: none
else:
- light.turn_off: top_led
- id: set_volume
mode: restart
parameters:
volume: float
then:
- media_player.volume_set:
id: onju_out
volume: !lambda return clamp(id(onju_out).volume+volume, 0.0f, 1.0f);
- light.turn_on:
id: top_led
effect: show_volume
- delay: 1s
- script.execute: reset_led
- id: turn_on_wake_word
then:
- if:
condition:
and:
- binary_sensor.is_off: mute_switch
- switch.is_on: use_wake_word
then:
- lambda: id(va).set_use_wake_word(true);
- if:
condition:
not:
- voice_assistant.is_running
then:
- voice_assistant.start_continuous
- script.execute: reset_led
- id: turn_off_wake_word
then:
- voice_assistant.stop
- lambda: id(va).set_use_wake_word(false);
- script.execute: reset_led
- id: calibrate_touch
parameters:
button: int
then:
- lambda: |-
static byte thresh_indices[3] = {0, 0, 0};
static uint32_t sums[3] = {0, 0, 0};
static byte qsizes[3] = {0, 0, 0};
static int consecutive_anomalies_per_button[3] = {0, 0, 0};
uint32_t newval;
uint32_t* calibration_values;
switch(button) {
case 0:
newval = id(volume_down).get_value();
calibration_values = id(touch_calibration_values_left);
break;
case 1:
newval = id(action).get_value();
calibration_values = id(touch_calibration_values_center);
break;
case 2:
newval = id(volume_up).get_value();
calibration_values = id(touch_calibration_values_right);
break;
default:
ESP_LOGE("touch_calibration", "Invalid button ID (%d)", button);
return;
}
if(newval == 0) return;
//ESP_LOGD("touch_calibration", "[%d] qsize %d, sum %d, thresh_index %d, consecutive_anomalies %d", button, qsizes[button], sums[button], thresh_indices[button], consecutive_anomalies_per_button[button]);
//ESP_LOGD("touch_calibration", "[%d] New value is %d", button, newval);
if(qsizes[button] == 5) {
float avg = float(sums[button])/float(qsizes[button]);
if((fabs(float(newval)-avg)/avg) > id(thresh_percent)) {
consecutive_anomalies_per_button[button]++;
//ESP_LOGD("touch_calibration", "[%d] %d anomalies detected.", button, consecutive_anomalies_per_button[button]);
if(consecutive_anomalies_per_button[button] < 10)
return;
}
}
//ESP_LOGD("touch_calibration", "[%d] Resetting consecutive anomalies counter.", button);
consecutive_anomalies_per_button[button] = 0;
if(qsizes[button] == 5) {
//ESP_LOGD("touch_calibration", "[%d] Queue full, removing %d.", button, id(touch_calibration_values)[thresh_indices[button]]);
sums[button] -= (uint32_t) *(calibration_values+thresh_indices[button]);// id(touch_calibration_values)[thresh_indices[button]];
qsizes[button]--;
}
*(calibration_values+thresh_indices[button]) = newval;
sums[button] += newval;
qsizes[button]++;
thresh_indices[button] = (thresh_indices[button] + 1) % 5;
//ESP_LOGD("touch_calibration", "[%d] Average value is %d", button, sums[button]/qsizes[button]);
uint32_t newthresh = uint32_t((sums[button]/qsizes[button]) * (1.0 + id(thresh_percent)));
//ESP_LOGD("touch_calibration", "[%d] Setting threshold %d", button, newthresh);
switch(button) {
case 0:
id(volume_down).set_threshold(newthresh);
break;
case 1:
id(action).set_threshold(newthresh);
break;
case 2:
id(volume_up).set_threshold(newthresh);
break;
default:
ESP_LOGE("touch_calibration", "Invalid button ID (%d)", button);
return;
}
switch:
- platform: template
name: Use Wake Word
id: use_wake_word
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
on_turn_on:
- script.execute: turn_on_wake_word
on_turn_off:
- script.execute: turn_off_wake_word
Please format the code properly.
Sorry. Done.
Ah, now I get it! I suggest you either update to the latest version of my config or request support from the guy from where you got your config :)
Unlike Mark, I actually keep it up to date, because I understand what's there since I've written it myself.
yes, that fixed it thanks.
I assembled one of these glorious devices, the assembly seemed OK, it’s showing up in HA as a voice device and the logs look normal - though isn’t working. It is WiFi connected and starts up OK.
What do the four purple lights mean? Where am I going wrong!
thanks for a great project!