Initial FilamentGauger firmware

This commit is contained in:
2026-04-13 17:02:28 +03:00
commit 93e55a7418
8 changed files with 2662 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.pio/
.vscode/

29
README.md Normal file
View File

@@ -0,0 +1,29 @@
# FilamentGauger
PlatformIO firmware for the Guition `JC8048W550(C)` display with an `HX711` load-cell amplifier.
Pins:
- `HX711 SCK -> IO17`
- `HX711 DOUT -> IO18`
Important:
- On this display family `IO18` is normally used by the capacitive touch interrupt.
- In this firmware the touch controller stays enabled, but its interrupt pin is moved to `GPIO_NUM_NC`, so touch works in polling mode and `IO18` becomes available for `HX711`.
Default calibration flow:
1. Leave the platform empty.
2. Tap `Tare`.
3. Put a `100 g` reference weight on the platform.
4. Tap `Cal 100 g`.
Serial commands:
- `tare`
- `cal 100`
- `scale 432.1`
- `reset`
- `status`
Build:
```bash
platformio run
```

View File

@@ -0,0 +1,142 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_16MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"'-D ARDUINO_ESP32S3_DEV'",
"'-D BOARD_HAS_PSRAM'",
"'-D ARDUINO_USB_MODE=1'",
"'-D ARDUINO_RUNNING_CORE=1'",
"'-D ARDUINO_EVENT_RUNNING_CORE=1'",
"'-D ARDUINO_USB_CDC_ON_BOOT=0'",
"'-D JC8048W550_HX711'",
"'-D DISPLAY_WIDTH=800'",
"'-D DISPLAY_HEIGHT=480'",
"'-D DISPLAY_SOFTWARE_ROTATION'",
"'-D LVGL_BUFFER_PIXELS=(DISPLAY_WIDTH*DISPLAY_HEIGHT)'",
"'-D LVGL_BUFFER_MALLOC_FLAGS=(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT)'",
"'-D DISPLAY_BCKL=2'",
"'-D DISPLAY_ST7262_PAR'",
"'-D SMARTDISPLAY_DMA_BUFFER_SIZE=131072'",
"'-D SMARTDISPLAY_DMA_QUEUE_SIZE=6'",
"'-D SMARTDISPLAY_DMA_CHUNK_THRESHOLD=1024'",
"'-D SMARTDISPLAY_DMA_TIMEOUT_MS=500'",
"'-D ST7262_PANEL_CONFIG_CLK_SRC=LCD_CLK_SRC_PLL160M'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_PCLK_HZ=(12.5*1000000)'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_H_RES=DISPLAY_WIDTH'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_V_RES=DISPLAY_HEIGHT'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_PULSE_WIDTH=4'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_BACK_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_FRONT_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_PULSE_WIDTH=4'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_BACK_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_FRONT_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_HSYNC_IDLE_LOW=false'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_VSYNC_IDLE_LOW=false'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_DE_IDLE_HIGH=false'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_PCLK_ACTIVE_NEG=true'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_PCLK_IDLE_HIGH=false'",
"'-D ST7262_PANEL_CONFIG_DATA_WIDTH=16'",
"'-D ST7262_PANEL_CONFIG_SRAM_TRANS_ALIGN=4'",
"'-D ST7262_PANEL_CONFIG_PSRAM_TRANS_ALIGN=64'",
"'-D ST7262_PANEL_CONFIG_HSYNC=39'",
"'-D ST7262_PANEL_CONFIG_VSYNC=41'",
"'-D ST7262_PANEL_CONFIG_DE=40'",
"'-D ST7262_PANEL_CONFIG_PCLK=42'",
"'-D ST7262_PANEL_CONFIG_DATA_R0=8'",
"'-D ST7262_PANEL_CONFIG_DATA_R1=3'",
"'-D ST7262_PANEL_CONFIG_DATA_R2=46'",
"'-D ST7262_PANEL_CONFIG_DATA_R3=9'",
"'-D ST7262_PANEL_CONFIG_DATA_R4=1'",
"'-D ST7262_PANEL_CONFIG_DATA_G0=5'",
"'-D ST7262_PANEL_CONFIG_DATA_G1=6'",
"'-D ST7262_PANEL_CONFIG_DATA_G2=7'",
"'-D ST7262_PANEL_CONFIG_DATA_G3=15'",
"'-D ST7262_PANEL_CONFIG_DATA_G4=16'",
"'-D ST7262_PANEL_CONFIG_DATA_G5=4'",
"'-D ST7262_PANEL_CONFIG_DATA_B0=45'",
"'-D ST7262_PANEL_CONFIG_DATA_B1=48'",
"'-D ST7262_PANEL_CONFIG_DATA_B2=47'",
"'-D ST7262_PANEL_CONFIG_DATA_B3=21'",
"'-D ST7262_PANEL_CONFIG_DATA_B4=14'",
"'-D ST7262_PANEL_CONFIG_DISP=GPIO_NUM_NC'",
"'-D ST7262_PANEL_CONFIG_FLAGS_DISP_ACTIVE_LOW=false'",
"'-D ST7262_PANEL_CONFIG_FLAGS_RELAX_ON_IDLE=false'",
"'-D ST7262_PANEL_CONFIG_FLAGS_FB_IN_PSRAM=true'",
"'-D DISPLAY_SWAP_XY=false'",
"'-D DISPLAY_MIRROR_X=false'",
"'-D DISPLAY_MIRROR_Y=false'",
"'-D BOARD_HAS_TOUCH'",
"'-D CONFIG_ESP_LCD_TOUCH_MAX_POINTS=1'",
"'-D CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=0'",
"'-D TOUCH_GT911_I2C'",
"'-D GT911_I2C_HOST=I2C_NUM_0'",
"'-D GT911_I2C_CONFIG_SDA=19'",
"'-D GT911_I2C_CONFIG_SCL=20'",
"'-D GT911_I2C_CONFIG_SDA_PULLUP_EN=GPIO_PULLUP_DISABLE'",
"'-D GT911_I2C_CONFIG_SCL_PULLUP_EN=GPIO_PULLUP_DISABLE'",
"'-D GT911_I2C_CONFIG_MASTER_CLK_SPEED=400000'",
"'-D GT911_I2C_CONFIG_CLK_FLAGS=I2C_SCLK_SRC_FLAG_FOR_NOMAL'",
"'-D GT911_IO_I2C_CONFIG_DEV_ADDR=GT911_IO_I2C_CONFIG_DEV_ADDRESS_5D'",
"'-D GT911_IO_I2C_CONFIG_CONTROL_PHASE_BYTES=1'",
"'-D GT911_IO_I2C_CONFIG_DC_BIT_OFFSET=0'",
"'-D GT911_IO_I2C_CONFIG_LCD_CMD_BITS=16'",
"'-D GT911_IO_I2C_CONFIG_LCD_PARAM_BITS=0'",
"'-D GT911_IO_I2C_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
"'-D GT911_IO_I2C_CONFIG_FLAGS_DISABLE_CONTROL_PHASE=true'",
"'-D GT911_TOUCH_CONFIG_X_MAX=DISPLAY_WIDTH'",
"'-D GT911_TOUCH_CONFIG_Y_MAX=DISPLAY_HEIGHT'",
"'-D GT911_TOUCH_CONFIG_RST=38'",
"'-D GT911_TOUCH_CONFIG_INT=GPIO_NUM_NC'",
"'-D GT911_TOUCH_CONFIG_LEVELS_RESET=0'",
"'-D GT911_TOUCH_CONFIG_LEVELS_INTERRUPT=0'",
"'-D TOUCH_SWAP_XY=false'",
"'-D TOUCH_MIRROR_X=false'",
"'-D TOUCH_MIRROR_Y=false'",
"'-D BOARD_HAS_TF'",
"'-D TF_CS=10'",
"'-D TF_SPI_MOSI=11'",
"'-D TF_SPI_SCLK=12'",
"'-D TF_SPI_MISO=13'",
"'-D HX711_SCK_PIN=17'",
"'-D HX711_DOUT_PIN=18'"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [
[
"0x303A",
"0x1001"
]
],
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": [
"wifi"
],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "JC8048W550_HX711",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 460800
},
"url": "https://github.com/rzeldent/esp32-smartdisplay/discussions/185",
"vendor": "Guition"
}

31
include/lv_conf.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef LV_CONF_H
#define LV_CONF_H
#define LV_COLOR_DEPTH 16
#define LV_MEM_SIZE (128U * 1024U)
#define LV_DEF_REFR_PERIOD 16
#define LV_USE_LOG 0
#define LV_FONT_MONTSERRAT_14 1
#define LV_FONT_MONTSERRAT_18 1
#define LV_FONT_MONTSERRAT_20 1
#define LV_FONT_MONTSERRAT_24 1
#define LV_FONT_MONTSERRAT_32 1
#define LV_FONT_MONTSERRAT_48 1
#define LV_FONT_DEFAULT &lv_font_montserrat_20
#define LV_USE_LABEL 1
#define LV_LABEL_LONG_TXT_HINT 1
#define LV_USE_BUTTON 1
#define LV_USE_BUTTONMATRIX 1
#define LV_USE_FLEX 1
#define LV_USE_KEYBOARD 1
#define LV_USE_OBSERVER 1
#define LV_USE_TEXTAREA 1
#define LV_USE_THEME_DEFAULT 1
#define LV_THEME_DEFAULT_DARK 1
#define LV_THEME_DEFAULT_GROW 0
#endif

34
platformio.ini Normal file
View File

@@ -0,0 +1,34 @@
; FilamentGauger firmware for Guition JC8048W550(C)
; HX711 wiring:
; SCK -> IO17
; DOUT -> IO18
[platformio]
default_envs = jc8048w550_hx711
[env]
platform = espressif32 @ 6.9.0
framework = arduino
monitor_speed = 115200
monitor_rts = 0
monitor_dtr = 0
monitor_filters = esp32_exception_decoder
build_flags =
-Ofast
-Wall
'-D BOARD_NAME="${this.board}"'
'-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO'
'-D LV_CONF_PATH=${platformio.include_dir}/lv_conf.h'
'-D HX711_REFERENCE_WEIGHT_GRAMS=100.0f'
lib_deps =
https://github.com/rzeldent/esp32-smartdisplay
lvgl/lvgl @ 9.2.2
bblanchon/ArduinoJson @ 7.4.3
lib_ldf_mode = chain+
[env:jc8048w550_hx711]
board = JC8048W550_HX711

110
src/hx711_sensor.cpp Normal file
View File

@@ -0,0 +1,110 @@
#include "hx711_sensor.h"
void Hx711Sensor::begin(uint8_t dout_pin, uint8_t sck_pin, uint8_t gain)
{
dout_pin_ = dout_pin;
sck_pin_ = sck_pin;
pinMode(dout_pin_, INPUT);
pinMode(sck_pin_, OUTPUT);
digitalWrite(sck_pin_, LOW);
setGain(gain);
}
bool Hx711Sensor::isReady() const
{
return digitalRead(dout_pin_) == LOW;
}
bool Hx711Sensor::waitReady(uint32_t timeout_ms) const
{
const uint32_t started = millis();
while (!isReady())
{
if (millis() - started >= timeout_ms)
{
return false;
}
delay(1);
}
return true;
}
int32_t Hx711Sensor::readRaw()
{
uint32_t value = 0;
noInterrupts();
for (uint8_t bit = 0; bit < 24; ++bit)
{
digitalWrite(sck_pin_, HIGH);
delayMicroseconds(1);
value = (value << 1) | (digitalRead(dout_pin_) ? 1UL : 0UL);
digitalWrite(sck_pin_, LOW);
delayMicroseconds(1);
}
for (uint8_t pulse = 0; pulse < gain_pulses_; ++pulse)
{
digitalWrite(sck_pin_, HIGH);
delayMicroseconds(1);
digitalWrite(sck_pin_, LOW);
delayMicroseconds(1);
}
interrupts();
if (value & 0x800000UL)
{
value |= 0xFF000000UL;
}
return static_cast<int32_t>(value);
}
int32_t Hx711Sensor::readAverage(uint8_t samples, uint32_t timeout_ms_per_sample)
{
int64_t total = 0;
uint8_t collected = 0;
while (collected < samples)
{
if (!waitReady(timeout_ms_per_sample))
{
break;
}
total += readRaw();
++collected;
delay(1);
}
if (collected == 0)
{
return 0;
}
return static_cast<int32_t>(total / collected);
}
void Hx711Sensor::setGain(uint8_t gain)
{
switch (gain)
{
case 128:
gain_pulses_ = 1;
break;
case 32:
gain_pulses_ = 2;
break;
case 64:
gain_pulses_ = 3;
break;
default:
gain_pulses_ = 1;
break;
}
}

24
src/hx711_sensor.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef HX711_SENSOR_H
#define HX711_SENSOR_H
#include <Arduino.h>
class Hx711Sensor
{
public:
void begin(uint8_t dout_pin, uint8_t sck_pin, uint8_t gain = 128);
bool isReady() const;
bool waitReady(uint32_t timeout_ms) const;
int32_t readRaw();
int32_t readAverage(uint8_t samples, uint32_t timeout_ms_per_sample = 1500);
private:
void setGain(uint8_t gain);
uint8_t dout_pin_ = 0;
uint8_t sck_pin_ = 0;
uint8_t gain_pulses_ = 1;
};
#endif

2289
src/main.cpp Normal file

File diff suppressed because it is too large Load Diff