Ported the code to M5Stack Core2 (different display) and removed reboot on disconnect
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
name: "owon-b35t"
|
name: "owon-b35t-m5stack-core2"
|
||||||
friendly_name: "OWON B35T Multimeter"
|
friendly_name: "OWON B35T Multimeter Core2"
|
||||||
device_description: "M5Stack Core 1 BLE client for OWON B35T/B35T+ multimeter with local graphical display"
|
device_description: "M5Stack Core2 BLE client for OWON B35T/B35T+ multimeter with local graphical display"
|
||||||
owon_mac_address: !secret owon_b35t_mac_address
|
owon_mac_address: !secret owon_b35t_mac_address
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
@@ -10,17 +10,27 @@ esphome:
|
|||||||
comment: ${device_description}
|
comment: ${device_description}
|
||||||
min_version: 2024.6.0
|
min_version: 2024.6.0
|
||||||
includes:
|
includes:
|
||||||
- owon_b35t.h
|
- owon_b35t-m5stack-core2.h
|
||||||
|
on_boot:
|
||||||
|
priority: 850
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
owon_b35t::core2_axp192_init(id(core2_i2c));
|
||||||
project:
|
project:
|
||||||
name: "custom.owon-b35t-m5stack"
|
name: "custom.owon-b35t-m5stack-core2"
|
||||||
version: "1.0"
|
version: "1.0"
|
||||||
|
|
||||||
esp32:
|
esp32:
|
||||||
board: m5stack-core-esp32
|
board: m5stack-core2
|
||||||
|
flash_size: 16MB
|
||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
advanced:
|
advanced:
|
||||||
minimum_chip_revision: "3.1"
|
sram1_as_iram: true
|
||||||
|
|
||||||
|
psram:
|
||||||
|
mode: quad
|
||||||
|
speed: 80MHz
|
||||||
|
|
||||||
logger:
|
logger:
|
||||||
level: INFO
|
level: INFO
|
||||||
@@ -44,20 +54,21 @@ wifi:
|
|||||||
ssid: "OWON B35T Fallback Hotspot"
|
ssid: "OWON B35T Fallback Hotspot"
|
||||||
password: !secret fallback_psk
|
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:
|
||||||
- interval: 10s
|
- interval: 10s
|
||||||
then:
|
then:
|
||||||
- lambda: |-
|
- 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_free_heap_size()),
|
||||||
static_cast<unsigned>(esp_get_minimum_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_free_size(MALLOC_CAP_INTERNAL)),
|
||||||
static_cast<unsigned>(heap_caps_get_largest_free_block(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_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:
|
esp32_ble_tracker:
|
||||||
scan_parameters:
|
scan_parameters:
|
||||||
@@ -75,22 +86,24 @@ ble_client:
|
|||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
owon_meter.on_disconnect();
|
owon_meter.on_disconnect();
|
||||||
- logger.log:
|
|
||||||
level: WARN
|
|
||||||
format: "OWON BLE meter disconnected; restarting M5Stack to reclaim heap"
|
|
||||||
- delay: 1s
|
|
||||||
- lambda: |-
|
|
||||||
esp_restart();
|
|
||||||
|
|
||||||
spi:
|
spi:
|
||||||
clk_pin: GPIO18
|
clk_pin: GPIO18
|
||||||
mosi_pin: GPIO23
|
mosi_pin: GPIO23
|
||||||
miso_pin: GPIO19
|
|
||||||
|
i2c:
|
||||||
|
id: core2_i2c
|
||||||
|
sda: GPIO21
|
||||||
|
scl: GPIO22
|
||||||
|
scan: true
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: ledc
|
- platform: template
|
||||||
pin: GPIO32
|
type: float
|
||||||
id: lcd_backlight
|
id: lcd_backlight
|
||||||
|
write_action:
|
||||||
|
- lambda: |-
|
||||||
|
owon_b35t::core2_axp192_set_backlight(state);
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: monochromatic
|
- platform: monochromatic
|
||||||
@@ -173,35 +186,38 @@ font:
|
|||||||
]
|
]
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: ili9xxx
|
- platform: mipi_spi
|
||||||
id: lcd
|
id: lcd
|
||||||
model: M5STACK
|
model: M5CORE2
|
||||||
cs_pin: GPIO14
|
|
||||||
dc_pin: GPIO27
|
|
||||||
reset_pin: GPIO33
|
|
||||||
invert_colors: true
|
|
||||||
color_palette: 8BIT
|
|
||||||
rotation: 0
|
|
||||||
update_interval: 500ms
|
update_interval: 500ms
|
||||||
lambda: |-
|
lambda: |-
|
||||||
owon_meter.render(it, id(meter_font));
|
owon_meter.render(it, id(meter_font));
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: ft63x6
|
||||||
|
id: touch
|
||||||
|
display: lcd
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: touchscreen
|
||||||
id: button_a
|
id: button_a
|
||||||
pin:
|
touchscreen_id: touch
|
||||||
number: GPIO39
|
x_min: 34
|
||||||
inverted: true
|
x_max: 74
|
||||||
|
y_min: 212
|
||||||
|
y_max: 240
|
||||||
internal: true
|
internal: true
|
||||||
on_press:
|
on_press:
|
||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
owon_meter.previous_button();
|
owon_meter.previous_button();
|
||||||
- platform: gpio
|
- platform: touchscreen
|
||||||
id: button_b
|
id: button_b
|
||||||
pin:
|
touchscreen_id: touch
|
||||||
number: GPIO38
|
x_min: 108
|
||||||
inverted: true
|
x_max: 208
|
||||||
|
y_min: 212
|
||||||
|
y_max: 240
|
||||||
internal: true
|
internal: true
|
||||||
on_click:
|
on_click:
|
||||||
- min_length: 50ms
|
- 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;
|
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};
|
std::vector<uint8_t> data = {owon_meter.selected_button, press_type};
|
||||||
return data;
|
return data;
|
||||||
- platform: gpio
|
- platform: touchscreen
|
||||||
id: button_c
|
id: button_c
|
||||||
pin:
|
touchscreen_id: touch
|
||||||
number: GPIO37
|
x_min: 242
|
||||||
inverted: true
|
x_max: 282
|
||||||
|
y_min: 212
|
||||||
|
y_max: 240
|
||||||
internal: true
|
internal: true
|
||||||
on_press:
|
on_press:
|
||||||
then:
|
then:
|
||||||
@@ -278,16 +296,16 @@ sensor:
|
|||||||
text_sensor:
|
text_sensor:
|
||||||
- platform: template
|
- platform: template
|
||||||
name: "${friendly_name} Reading"
|
name: "${friendly_name} Reading"
|
||||||
update_interval: 2s
|
update_interval: 1s
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return owon_meter.reading_text();
|
return owon_meter.reading_text();
|
||||||
- platform: template
|
- platform: template
|
||||||
name: "${friendly_name} Unit"
|
name: "${friendly_name} Unit"
|
||||||
update_interval: 2s
|
update_interval: 1s
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return std::string(owon_meter.scale()) + owon_meter.unit();
|
return std::string(owon_meter.scale()) + owon_meter.unit();
|
||||||
- platform: template
|
- platform: template
|
||||||
name: "${friendly_name} Mode"
|
name: "${friendly_name} Mode"
|
||||||
update_interval: 2s
|
update_interval: 1s
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return owon_meter.mode_text();
|
return owon_meter.mode_text();
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
#include "esphome/components/i2c/i2c.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/components/display/display.h"
|
#include "esphome/components/display/display.h"
|
||||||
|
|
||||||
@@ -22,6 +23,92 @@ using esphome::Color;
|
|||||||
using esphome::display::Display;
|
using esphome::display::Display;
|
||||||
|
|
||||||
static const char *const TAG = "owon_b35t";
|
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] = {
|
static const uint8_t ACCU_BMP[32] = {
|
||||||
0b00000000, 0b00000000,
|
0b00000000, 0b00000000,
|
||||||
Reference in New Issue
Block a user