基於Chappie-II的二次開發日誌-1

K0maru發表於2024-11-03

出於個人興趣決定在原Forairaaaaa/Chappie-II的基礎上進行個性化修改和部分特殊功能的實現,本文主要包括:

  • 開發環境配置
  • 系統邏輯簡讀
  • 設定頁面menu實現

注:僅為隨筆,不建議做任何技術參考

1. 環境配置

1.1 WSL+VScode+PIO

因為習慣了將開發環境整合在wsl中,然後用vscode連線後使用,所以本次依然是WSL+VScode這一套。由於原工程就是PIO工程,曾經也用過vscode上的PIO外掛,所以不多做贅述。
PIO安裝與使用可參考在vscode 中用PlatformIO開發-CSDN部落格
其中需要注意的是程式的燒錄等操作依賴USB連線,而wsl並不會像宿主機一樣輕鬆識別使用USB裝置,所以需要使用USB/IP 開源專案 usbipd-win來實現開發板與開發環境的連線,方法可以參考連線 USB 裝置 | Microsoft Learn
但因為程式燒錄時有上電操作,所以連線會斷開,需要手動使用usbipd attach --wsl --busid <busid>來連線一下。如果嫌麻煩可以寫個指令碼。

1.2 檔案樹和依賴庫

1.2.1 檔案樹

Chappie-II/Firmware
├── default_16MB.csv
├── lib
│   ├── arduinoFFT
│   ├── ESP32-BLE-Gamepad
│   ├── FastLED
│   ├── LovyanGFX
│   ├── lv_conf.h
│   ├── lvgl
│   ├── NimBLE-Arduino
│   └── README
├── platformio.ini
├── src
    ├── ChappieBsp
    ├── ChappieUI
    └── main.cpp

1.2.2 下載依賴

git submodule init
git submodule update
cd lib
git clone https://github.com/lovyan03/LovyanGFX.git
git clone -b v8.3.5 https://github.com/lvgl/lvgl.git
git clone https://github.com/FastLED/FastLED.git
git clone https://github.com/lemmingDev/ESP32-BLE-Gamepad.git
git clone https://github.com/h2zero/NimBLE-Arduino.git
git clone --branch 1.6.2 https://github.com/kosme/arduinoFFT.git 

注意,使用高於1.6.2版本的arduinoFFT會出現報錯。

2. 系統邏輯簡讀

2.1 系統啟動

#include "Arduino.h"
#include "ChappieUI/ChappieUI.h"

CHAPPIEUI ChappieUI;
/**
 * @brief 系統初始化並啟動App_Launcher
 */
void setup()
{
    ChappieUI.begin();
}

/**
 * @brief 重新整理App_Launcher以獲得實時資訊
 */
void loop()
{
    ChappieUI.update();
    delay(5);
}

系統功能以APP為單位體現,包括此處的App_Launcher本身也是App。輪詢App和系統狀態實現App的啟動和退出。
此處App_Launcher的功能包括:

  • void App_Launcher::onCreate():App_Launcher的建立
  • void App_Launcher::onDestroy():App_Launcher的退出,以載入lvgl主螢幕並銷燬Launcher screen實現
  • void App_Launcher::updateDeviceStatus():響應按鍵A、B一個電源鍵一個home鍵
  • void App_Launcher::updateAppManage():App狀態管理,包括onCreateisRunningonDestroy三種狀態。可以看到App被退出也就是onDestroy狀態,會預設建立App_Launcher,實現退出返回主頁的效果。且在App預設框架中要求返回Appname,與AppRegister中已註冊的App對應,實現查詢和訪問。

2.2 App_Settings簡讀

App_Settings是系統中的”設定“app,可以看到其透過WIFI實現時間的同步

static void xTaskOne(void *xTask1)
{
    while (1)
    {
        uint8_t i = 0;
        WiFi.mode(WIFI_AP_STA);
        WiFi.begin();
        while (WiFi.status() != WL_CONNECTED)
	    { //這裡是阻塞程式,直到連線成功
            vTaskDelay(100);
            i++;  
            if(i == 100)
            {
                //vTaskDelete(NULL);
                break;//等待10秒,若未連線,則退出聯網
            }
        }
        i = 0;
        if(WiFi.status() != WL_CONNECTED)
        {       
            WiFi.beginSmartConfig();
        }
        if(WiFi.status() != WL_CONNECTED)
        {
            while (!WiFi.smartConfigDone()) 
            { 
                delay(500);
                i++;  
                if(i == 200)
                {
                    WiFi.disconnect();
                    vTaskDelete(NULL);//等待25秒,若仍未配網,則登出執行緒
                }
            }
            i = 0;
            vTaskDelay(100);
            while (WiFi.status() != WL_CONNECTED) 
            { 
                vTaskDelay(100);
                i++;  
                if(i == 100)
                {
                    WiFi.disconnect();
                    vTaskDelete(NULL);
                } 
            }
        }
    	http.begin("http://quan.suning.com/getSysTime.do"); //HTTP begin
    	int httpCode = http.GET();
        if (httpCode > 0)
        {
            // httpCode will be negative on error
            if (httpCode == HTTP_CODE_OK) // 收到正確的內容
            {
            String resBuff = http.getString();
            char *pEnd;
            char charArray[100];
            char str [30];
            resBuff.toCharArray(charArray, 61);
            for(i=0;i<=15;i++){str[i]=charArray[i+46];}

            int nums[6];
            extract_ints(str, nums, 6);

            rtc_date.year = nums[0];
            rtc_date.month = nums[1];
            rtc_date.date = nums[2];
            rtc_time.hours = nums[3];
            rtc_time.minutes = nums[4];
            rtc_time.seconds = nums[5]+1;//補償資料處理的時間            
            uint16_t y = nums[0];
            uint8_t m = nums[1];
            uint8_t d = nums[2];
            if(m<3)
            {
                m+=12;
                y-=1;
            }
            rtc_date.weekDay=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
            device->Rtc.setDate(&rtc_date);
            device->Rtc.setTime(&rtc_time);
            }
        }
        http.end();
        WiFi.disconnect();
        vTaskDelete(NULL);
    }
}

WIFI的連線使用了官方的smartconfig方法,還沒進行測試。剩下的功能則是畫了一個圓弧ui,不知道作何用處的。

3. menu實現

基礎例程和呼叫lvgl庫的版本進行初始修改(函式功能和名稱發生了改變)
具體的顯示效果等下次有時間和回撥函式一起完成,嘗試把原有的Wifi同步時間的功能顯示在menu中。

   /**
     * @brief 設定介面的多級選單
     * @author K0maru3
     */
    void App_Settings_menu(void)
    {
        /*Create a menu object*/
        lv_obj_t * menu = lv_menu_create(lv_scr_act());
        lv_obj_set_size(menu, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
        lv_obj_center(menu);

        lv_obj_t * cont;
        lv_obj_t * label;

        /*Create a sub page*/
        lv_obj_t * sub_page = lv_menu_page_create(menu, NULL);

        cont = lv_menu_cont_create(sub_page);
        label = lv_label_create(cont);
        lv_label_set_text(label, "Hello, I am hiding here");

        /*Create a main page*/
        lv_obj_t * main_page = lv_menu_page_create(menu, NULL);

        cont = lv_menu_cont_create(main_page);
        label = lv_label_create(cont);
        lv_label_set_text(label, "Item 1");

        cont = lv_menu_cont_create(main_page);
        label = lv_label_create(cont);
        lv_label_set_text(label, "Item 2");

        cont = lv_menu_cont_create(main_page);
        label = lv_label_create(cont);
        lv_label_set_text(label, "Item 3 (Click me!)");
        lv_menu_set_load_page_event(menu, cont, sub_page);

        lv_menu_set_page(menu, main_page);
    }

相關文章