Ported the code to M5Stack Core2 (different display) and removed reboot on disconnect
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
substitutions:
|
||||
name: "owon-b35t"
|
||||
friendly_name: "OWON B35T Multimeter"
|
||||
device_description: "M5Stack Core 1 BLE client for OWON B35T/B35T+ multimeter with local graphical display"
|
||||
name: "owon-b35t-m5stack-core2"
|
||||
friendly_name: "OWON B35T Multimeter Core2"
|
||||
device_description: "M5Stack Core2 BLE client for OWON B35T/B35T+ multimeter with local graphical display"
|
||||
owon_mac_address: !secret owon_b35t_mac_address
|
||||
|
||||
esphome:
|
||||
@@ -10,17 +10,27 @@ esphome:
|
||||
comment: ${device_description}
|
||||
min_version: 2024.6.0
|
||||
includes:
|
||||
- owon_b35t.h
|
||||
- owon_b35t-m5stack-core2.h
|
||||
on_boot:
|
||||
priority: 850
|
||||
then:
|
||||
- lambda: |-
|
||||
owon_b35t::core2_axp192_init(id(core2_i2c));
|
||||
project:
|
||||
name: "custom.owon-b35t-m5stack"
|
||||
name: "custom.owon-b35t-m5stack-core2"
|
||||
version: "1.0"
|
||||
|
||||
esp32:
|
||||
board: m5stack-core-esp32
|
||||
board: m5stack-core2
|
||||
flash_size: 16MB
|
||||
framework:
|
||||
type: esp-idf
|
||||
advanced:
|
||||
minimum_chip_revision: "3.1"
|
||||
sram1_as_iram: true
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
speed: 80MHz
|
||||
|
||||
logger:
|
||||
level: INFO
|
||||
@@ -44,20 +54,21 @@ wifi:
|
||||
ssid: "OWON B35T Fallback Hotspot"
|
||||
password: !secret fallback_psk
|
||||
|
||||
# Disabled to save RAM on the M5Stack Core 1. Re-enable temporarily if Wi-Fi recovery is needed.
|
||||
# captive_portal:
|
||||
captive_portal:
|
||||
|
||||
interval:
|
||||
- interval: 10s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGI("mem", "heap free=%u min_free=%u internal_free=%u internal_largest=%u dma_free=%u dma_largest=%u",
|
||||
ESP_LOGI("mem", "heap free=%u min_free=%u internal_free=%u internal_largest=%u dma_free=%u dma_largest=%u psram_free=%u psram_largest=%u",
|
||||
static_cast<unsigned>(esp_get_free_heap_size()),
|
||||
static_cast<unsigned>(esp_get_minimum_free_heap_size()),
|
||||
static_cast<unsigned>(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)),
|
||||
static_cast<unsigned>(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL)),
|
||||
static_cast<unsigned>(heap_caps_get_free_size(MALLOC_CAP_DMA)),
|
||||
static_cast<unsigned>(heap_caps_get_largest_free_block(MALLOC_CAP_DMA)));
|
||||
static_cast<unsigned>(heap_caps_get_largest_free_block(MALLOC_CAP_DMA)),
|
||||
static_cast<unsigned>(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)),
|
||||
static_cast<unsigned>(heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM)));
|
||||
|
||||
esp32_ble_tracker:
|
||||
scan_parameters:
|
||||
@@ -75,22 +86,24 @@ ble_client:
|
||||
then:
|
||||
- lambda: |-
|
||||
owon_meter.on_disconnect();
|
||||
- logger.log:
|
||||
level: WARN
|
||||
format: "OWON BLE meter disconnected; restarting M5Stack to reclaim heap"
|
||||
- delay: 1s
|
||||
- lambda: |-
|
||||
esp_restart();
|
||||
|
||||
spi:
|
||||
clk_pin: GPIO18
|
||||
mosi_pin: GPIO23
|
||||
miso_pin: GPIO19
|
||||
|
||||
i2c:
|
||||
id: core2_i2c
|
||||
sda: GPIO21
|
||||
scl: GPIO22
|
||||
scan: true
|
||||
|
||||
output:
|
||||
- platform: ledc
|
||||
pin: GPIO32
|
||||
- platform: template
|
||||
type: float
|
||||
id: lcd_backlight
|
||||
write_action:
|
||||
- lambda: |-
|
||||
owon_b35t::core2_axp192_set_backlight(state);
|
||||
|
||||
light:
|
||||
- platform: monochromatic
|
||||
@@ -173,35 +186,38 @@ font:
|
||||
]
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
- platform: mipi_spi
|
||||
id: lcd
|
||||
model: M5STACK
|
||||
cs_pin: GPIO14
|
||||
dc_pin: GPIO27
|
||||
reset_pin: GPIO33
|
||||
invert_colors: true
|
||||
color_palette: 8BIT
|
||||
rotation: 0
|
||||
model: M5CORE2
|
||||
update_interval: 500ms
|
||||
lambda: |-
|
||||
owon_meter.render(it, id(meter_font));
|
||||
|
||||
touchscreen:
|
||||
- platform: ft63x6
|
||||
id: touch
|
||||
display: lcd
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
- platform: touchscreen
|
||||
id: button_a
|
||||
pin:
|
||||
number: GPIO39
|
||||
inverted: true
|
||||
touchscreen_id: touch
|
||||
x_min: 34
|
||||
x_max: 74
|
||||
y_min: 212
|
||||
y_max: 240
|
||||
internal: true
|
||||
on_press:
|
||||
then:
|
||||
- lambda: |-
|
||||
owon_meter.previous_button();
|
||||
- platform: gpio
|
||||
- platform: touchscreen
|
||||
id: button_b
|
||||
pin:
|
||||
number: GPIO38
|
||||
inverted: true
|
||||
touchscreen_id: touch
|
||||
x_min: 108
|
||||
x_max: 208
|
||||
y_min: 212
|
||||
y_max: 240
|
||||
internal: true
|
||||
on_click:
|
||||
- min_length: 50ms
|
||||
@@ -233,11 +249,13 @@ binary_sensor:
|
||||
uint8_t press_type = (owon_meter.selected_button == 1 || owon_meter.selected_button == 5) ? 0x01 : 0x00;
|
||||
std::vector<uint8_t> data = {owon_meter.selected_button, press_type};
|
||||
return data;
|
||||
- platform: gpio
|
||||
- platform: touchscreen
|
||||
id: button_c
|
||||
pin:
|
||||
number: GPIO37
|
||||
inverted: true
|
||||
touchscreen_id: touch
|
||||
x_min: 242
|
||||
x_max: 282
|
||||
y_min: 212
|
||||
y_max: 240
|
||||
internal: true
|
||||
on_press:
|
||||
then:
|
||||
@@ -278,16 +296,16 @@ sensor:
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: "${friendly_name} Reading"
|
||||
update_interval: 2s
|
||||
update_interval: 1s
|
||||
lambda: |-
|
||||
return owon_meter.reading_text();
|
||||
- platform: template
|
||||
name: "${friendly_name} Unit"
|
||||
update_interval: 2s
|
||||
update_interval: 1s
|
||||
lambda: |-
|
||||
return std::string(owon_meter.scale()) + owon_meter.unit();
|
||||
- platform: template
|
||||
name: "${friendly_name} Mode"
|
||||
update_interval: 2s
|
||||
update_interval: 1s
|
||||
lambda: |-
|
||||
return owon_meter.mode_text();
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_system.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/display/display.h"
|
||||
|
||||
@@ -22,6 +23,92 @@ using esphome::Color;
|
||||
using esphome::display::Display;
|
||||
|
||||
static const char *const TAG = "owon_b35t";
|
||||
static const char *const POWER_TAG = "core2_power";
|
||||
static constexpr uint8_t AXP192_ADDR = 0x34;
|
||||
static esphome::i2c::I2CDevice axp192;
|
||||
static bool axp192_ready = false;
|
||||
|
||||
static bool axp_write(uint8_t reg, uint8_t value) {
|
||||
if (!axp192_ready) return false;
|
||||
bool ok = axp192.write_byte(reg, value);
|
||||
if (!ok) ESP_LOGW(POWER_TAG, "AXP192 write reg 0x%02X failed", reg);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool axp_read(uint8_t reg, uint8_t *value) {
|
||||
if (!axp192_ready) return false;
|
||||
bool ok = axp192.read_byte(reg, value);
|
||||
if (!ok) ESP_LOGW(POWER_TAG, "AXP192 read reg 0x%02X failed", reg);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void axp_update(uint8_t reg, uint8_t clear_mask, uint8_t set_mask) {
|
||||
uint8_t value = 0;
|
||||
if (!axp_read(reg, &value)) return;
|
||||
value = (value & ~clear_mask) | set_mask;
|
||||
axp_write(reg, value);
|
||||
}
|
||||
|
||||
static uint8_t axp_dc_voltage_data(uint16_t millivolts) {
|
||||
if (millivolts < 700) millivolts = 700;
|
||||
if (millivolts > 3500) millivolts = 3500;
|
||||
return static_cast<uint8_t>((millivolts - 700) / 25) & 0x7F;
|
||||
}
|
||||
|
||||
static uint8_t axp_ldo_voltage_data(uint16_t millivolts) {
|
||||
if (millivolts < 1800) millivolts = 1800;
|
||||
if (millivolts > 3300) millivolts = 3300;
|
||||
return static_cast<uint8_t>((millivolts - 1800) / 100) & 0x0F;
|
||||
}
|
||||
|
||||
static void core2_axp192_set_lcd_voltage(uint16_t millivolts) {
|
||||
uint8_t value = 0;
|
||||
axp_read(0x27, &value);
|
||||
axp_write(0x27, (value & 0x80) | axp_dc_voltage_data(millivolts)); // DCDC3, LCD backlight
|
||||
}
|
||||
|
||||
static void core2_axp192_set_backlight(float brightness) {
|
||||
if (brightness <= 0.0f) {
|
||||
axp_update(0x12, 0x02, 0x00); // DCDC3 off
|
||||
return;
|
||||
}
|
||||
if (brightness > 1.0f) brightness = 1.0f;
|
||||
uint16_t millivolts = static_cast<uint16_t>(2400 + brightness * 900);
|
||||
core2_axp192_set_lcd_voltage(millivolts);
|
||||
axp_update(0x12, 0x00, 0x02); // DCDC3 on
|
||||
}
|
||||
|
||||
static void core2_axp192_init(esphome::i2c::I2CBus *bus) {
|
||||
axp192.set_i2c_bus(bus);
|
||||
axp192.set_i2c_address(AXP192_ADDR);
|
||||
axp192_ready = true;
|
||||
ESP_LOGI(POWER_TAG, "Initializing M5Stack Core2 AXP192 LCD power");
|
||||
axp_update(0x30, 0xF9, 0x02); // Disable VBUS current limit, preserve bit 2.
|
||||
axp_update(0x92, 0x07, 0x00); // GPIO1 open-drain output.
|
||||
axp_update(0x93, 0x07, 0x00); // GPIO2 open-drain output.
|
||||
axp_write(0x35, 0xA2); // RTC battery charging.
|
||||
|
||||
uint8_t value = 0;
|
||||
axp_read(0x26, &value);
|
||||
axp_write(0x26, (value & 0x80) | axp_dc_voltage_data(3350)); // DCDC1 ESP32 VDD.
|
||||
core2_axp192_set_lcd_voltage(2800);
|
||||
|
||||
uint8_t ldo2 = axp_ldo_voltage_data(3300);
|
||||
uint8_t ldo3 = axp_ldo_voltage_data(2000);
|
||||
axp_write(0x28, (ldo2 << 4) | ldo3); // LDO2 LCD logic/SD, LDO3 vibrator.
|
||||
axp_update(0x12, 0x00, 0x07); // Enable DCDC1, DCDC3, LDO2.
|
||||
axp_write(0x82, 0xFF); // ADCs on.
|
||||
axp_update(0x95, 0x8D, 0x84); // GPIO4 setup, as M5Core2 library does.
|
||||
axp_write(0x36, 0x4C); // Power key timing.
|
||||
|
||||
// LCD reset through AXP192 GPIO4.
|
||||
axp_update(0x96, 0x02, 0x00);
|
||||
delay(100);
|
||||
axp_update(0x96, 0x00, 0x02);
|
||||
delay(100);
|
||||
|
||||
core2_axp192_set_backlight(1.0f);
|
||||
}
|
||||
|
||||
static const uint8_t ACCU_BMP[32] = {
|
||||
0b00000000, 0b00000000,
|
||||
Reference in New Issue
Block a user