翻车鱼日历 发表于 2024-10-31 16:36

【2024 DigiKey创意大赛】esp32s3 klipper面板提交

<p>ccb04455e9616deb4aa0e2f3662cd4f6<br />
<br />
一、作品简介</p>

<p>&nbsp;&nbsp;&nbsp; 米娜大家好啊,这一次eeworld的活动咱也是白嫖上了(雾),这次咱申请的是esp32s3 lcd ev board和一个stm32f401rct6的开发板,stm32f401rct6各位都很熟悉了就不再多说了,esp32s3 lcd这块板子倒是挺好的,这屏幕是真的大啊(舔嘴),这块屏幕尺寸正好可以当86盒子,太适合做点面板了,但是因为作者家里只能家居设备实在是太少了玩homeassitant感觉也没什么太大的意思,正好有台旧的kp3s打印机刚被作者刷了个klipper加个了klicky(押),那么干脆几挫个klipper面板得了(没钱klipper screen&hellip;&hellip;?这块板子似乎比配一个klipper screen还贵????)</p>

<p>二、系统框图<br />
&nbsp;&nbsp;&nbsp; stm32f401被作者拿着测试板子啦(),所有干脆直说esp32这边<br />
&nbsp;&nbsp;&nbsp; 一如既往我还是用的espidf开发,实在是用不惯platfromio+arduino这样感觉还是有点怪<br />
&nbsp;&nbsp;&nbsp; 框架的话我是直接从局域网接入的打印机moonraker的接口,默认是7125应该是,然后因为作者之前写ws挺多的moonraker也支持ws接口直接写json收发数据,就干脆想写一下ws下json生成和处理的面向对象。页面的话还是一如既往的我做不好设计的lvgl(能用就行,挺难看的(嘘)</p>

<div style="text-align: center;"></div>

<p>三、各部分功能说明</p>

<p>Moonraker API &amp; WebSocket 接口</p>

<p>大家都知道,Moonraker 是 Klipper 提供的远程 API 接口,适合通过局域网控制 3D 打印机。这次项目中我是直接通过 ESP32 连接 Moonraker 的 API 接口,默认端口是 7125,通过它可以使用 HTTP 和 WebSocket 来和打印机交流。 特别是 WebSocket,在 Moonraker 上能保持长连接,能通过 JSON 格式的消息实时收发打印机的状态。同样数据也有广播和请求接受两种大类。案例:</p>

<pre>
<code class="language-xml">
Run a gcode:¶

HTTP request:

POST /printer/gcode/script?script=G28

JSON-RPC request:

{

    "jsonrpc": "2.0",

    "method": "printer.gcode.script",

    "params": {

        "script": "G28"

    },

    "id": 7466}

Returns:

ok when the gcode has completed execution.</code></pre>

<p>ESP-IDF 与 WebSocket 客户端</p>

<p>作为老搭档,ESP-IDF 是开发 ESP32 的标配工具。虽然配置稍显繁琐,但也比前两年的好多了lol。这次项目常规使用esp32 WebSocket 客户端,连接到 Moonraker 获取打印机的实时数据。注意现在ws client的案例需要在The&nbsp;ESP&nbsp;Component Registry去添加Component</p>

<p>WebSocket 在 ESP-IDF 里是基于事件触发的,当连接建立、数据接收或出错时都会触发不同的事件,让开发起来简洁明了。比如,当有数据到来时,会进入 WEBSOCKET_EVENT_DATA 事件。每次收到 JSON 格式的数据,就利用 cJSON 进行解析,轻松提取出温度或位置信息,避免乱码问题,同时在日志里把数据打印出来方便调试。</p>

<p>案例伪程序如下</p>

<pre>
<code class="language-cpp">#include "esp_websocket_client.h"

#include "cJSON.h"



#define TAG "websocket"

#define URI "ws://example.com/socket" // WebSocket URI (replace with actual URI)



// WebSocket事件处理程序,处理连接、数据接收、错误等

static void websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {

    esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;



    if (event_id == WEBSOCKET_EVENT_CONNECTED) {

        ESP_LOGI(TAG, "WebSocket connected");

    } else if (event_id == WEBSOCKET_EVENT_DATA) {

        ESP_LOGI(TAG, "Received data: %.*s", data-&gt;data_len, (char *)data-&gt;data_ptr);



        // 尝试解析为 JSON

        cJSON *json = cJSON_Parse(data-&gt;data_ptr);

        if (json) {

            // 打印 JSON 内容 (根据实际结构进一步解析)

            ESP_LOGI(TAG, "Parsed JSON message");

            cJSON_Delete(json); // 清理 JSON 对象

        }

    }

}



// 初始化 WebSocket 客户端并发送消息

static void websocket_app_start(void) {

    esp_websocket_client_config_t ws_cfg = {

        .uri = URI,

    };



    esp_websocket_client_handle_t client = esp_websocket_client_init(&amp;ws_cfg);

    esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, websocket_event_handler, NULL);



    esp_websocket_client_start(client); // 启动 WebSocket 客户端

    vTaskDelay(pdMS_TO_TICKS(1000));    // 1秒延迟



    if (esp_websocket_client_is_connected(client)) {

        esp_websocket_client_send_text(client, "hello", 5, portMAX_DELAY); // 发送文本消息

    }



    esp_websocket_client_close(client, portMAX_DELAY); // 关闭连接

    esp_websocket_client_destroy(client);              // 清理客户端

}



void app_main(void) {

    websocket_app_start(); // 启动WebSocket应用

}</code></pre>

<p>讲到图形界面设计,LVGL 作为轻量化 UI 库,这次项目的界面部分我依然选择了它。咱是真的不擅长设计,所以直接用 GUI Guider 工具拖拖拽拽实现基础布局,配合 LVGL 的实时刷新功能将数据展示出来。UI 里主要是显示当前温度、位置信息、打印进度等。</p>

<p>每次解析完 JSON 数据后,只需调用 LVGL 的 lv_chart_set_value 这些方法就能更新显示,比如实时温度曲线、状态文字展示等,效果很不错!这块板子的屏幕不小,图表显示起来效果也很好,不用担心看不清。而且 GUI Guider 工具生成的代码可以直接加进 ESP-IDF 作为组件使用,非常方便,不用手动一行一行写界面代码(真的省心)。</p>

<p>虽然设计水平有限,但 LVGL 整体性能还是非常给力的。界面更新流畅,数据实时同步,体验效果棒棒的!</p>

<div style="text-align: center;"></div>

<div style="text-align: center;">&nbsp;</div>

<p><br />
(中间过程截图,我真的不会做设计呜呜呜)<br />
代码的话需要添加cmakellist才可以当作espidf的Component类似这样</p>

<pre>
<code class="language-cpp">idf_component_register(SRC_DIRS "custom"

                        SRC_DIRS "generated"

                        SRC_DIRS "generated/guider_fonts"

                        SRC_DIRS "generated/guider_customer_fonts"

                        SRC_DIRS "generated/images"

                        INCLUDE_DIRS "custom"

                        INCLUDE_DIRS "generated"

                        INCLUDE_DIRS "generated/guider_fonts"

                        INCLUDE_DIRS "generated/guider_customer_fonts"

                        INCLUDE_DIRS "generated/images"

                        REQUIRES lvgl__lvgl)</code></pre>

<p>&nbsp;</p>

<div style="text-align: center;"></div>

<p>四、测试代码见附件<br />
<br />
五、演示视频</p>

<p>0e0da88cb42e431a7afa4ac152c94121<br />
&nbsp;</p>

wangerxian 发表于 2024-10-31 19:22

<p>有演示视频没有呀~</p>
页: [1]
查看完整版本: 【2024 DigiKey创意大赛】esp32s3 klipper面板提交