2019年11月28日 星期四

遇見 LittlevGL

markdown



很久很久前,剛開始研究 ARM嵌入式系統時,就對圖形化介面吸引,希望能有一套開源、輕量、開機快速又能支援顯示中文的GUI,後來有找到一個名為ParaGUI的平台,不過基於沒太多時間研究,所以只稍稍碰了一下下,玩了幾個widge就沒再繼續了

這陣子在網上亂逛時,無意發現,原來還有一套能滿足我想要的GUI平台,LittlevGL,簡稱 LVGL

網頁寫的簡單明暸,有什麼功能,啪拉啪拉一籮筐,重點是體積小,80 kB Flash, 12 kB RAM就能執行起來了,這對一般的MCU來說,就是一大福音呀

在Github上,也已有提供 Arduino的lv\_arduino library,下載後直接使用即可,不過Arduino版的LVGL圖形顯示是建立在TFT\_eSPI library上,所以必須先讓TFT_eSPI能正確驅動 LCD螢幕,LVGL才能正常顯示

後續再慢慢介紹設定與使用方式,重點是中文字的顯示呀

(圖片來源:LittlevGL官網)

2019年8月2日 星期五

使用 MAX7219 驅動4個 8x8 矩陣式LED 顯示器



之前買了三個 6cm x 6cm 的MAX7219 白光LED點矩陣,把三個點矩陣串接起來並使用MaxMatrix Library做NTP時鐘,顯示都正常,所以就再加碼,買了比較小一點 4 in 1的,打算放在臥室



就在收到貨後,立馬更換,點亮了~,不過字體怎麼怪怪的,轉了90度,Google了一下,發現有MD_MAX72XX library 可以做轉向顯示,但是我已經用MaxMatrix 寫好code,不想大改了,所以只好捲起袖子,開始 trace MaxMatrix的code,看看能不能在最小幅度的修改下,達到文字旋轉90度的需求



下面是修改MaxMatrix.c,轉90度顯示所做的修改,有三個副程式需做修改

void MaxMatrix::setColumn(byte col, byte value)
{
    int xx = (col%8);   
    int yy = 0 ;   
   
    for (int row_i=0;row_i<8;row_i++){
        yy = (col/8)*8+row_i;
        setDot(xx, yy, bitRead(value, row_i));
    }
}

void MaxMatrix::setDot(byte col, byte row, byte value)
{
    int yy = 7-(col%8);
    int xx = (col/8)*8+row;
   
    bitWrite(buffer[xx], yy, value);
   
    int n = xx / 8;
    int c = (xx % 8);
    digitalWrite(load, LOW);
    for (int i=0; i<num; i++)
    {
        if (i == n)
        {
            shiftOut(data, clock, MSBFIRST, c + 1);
            shiftOut(data, clock, MSBFIRST, buffer[xx]);
        }
        else
        {
            shiftOut(data, clock, MSBFIRST, 0);
            shiftOut(data, clock, MSBFIRST, 0);
        }
    }
	digitalWrite(load, LOW);
	digitalWrite(load, HIGH);
}

void MaxMatrix::writeSprite(int x, int y, const byte* sprite)
{
	int w = sprite[0];
	int h = sprite[1];
	   
    for (int i=0; i<w; i++){
            for (int j=0; j<h; j++)
            {
                int c = x + i;
                int r = y + j;
                if (c>=0 && c<80 && r>=0 && r<8)
                    setDot(c, r, bitRead(sprite[i+2], j));
            }
    }
}


修改完結果如下,可正常顯示,但Scroll 移動的部分就沒有修改,所以若要捲動的話顯示會出問題的,這部份等有空再來改了






2019年4月25日 星期四

新增 PM2.5 Homekit 裝置

markdown

手上買了一個Sharp GP2Y1010AU0F PM2.5的感測器,就只在買來的當下用UNO測試了一下,嗯~~可用,就收起來了,一直到這次要整合在一個能夠顯示時間又有Homekit功能的系統板上(暫且稱它為家庭顯示中心吧),才又把它拿出來了。

把UNO的code  Ctrl+C、Ctrl+V到ESP32下,理論上應該是沒問題的,所以就做啦,只把Delay的部分修改為vTaskDelay,因為我是採用ESP-IDF + RTOS + Arduino 的平台,Flash完,怎麼收到的電壓都是0V,用VR分壓測試,A/D沒問題啊,怎麼沒收到GP2Y的電壓,換回UNO,一切正常啊,甚麼問題???

好,Hardward沒問題,Firmware我只修改Delay,問題不會就在這吧

沒錯,在UNO下的Delay是
delayMicroseconds(280)
ESP32是
vTaskDelay(280/portTICK_RATE_MS)
這可是差1000倍呀!!

既然在ESP-IDF下已經有支援arduino的套件,那就在這裡也改用delayMicroseconds函數吧,應該不至於影響整個系統太多,畢竟我還有其他task在執行

compiler...  flash... run... ,Yes~ got it ,讀到值啦,那就繼續往下一步去,增加到Homekit裝置

新增Homekit裝置時,都需要滿足Apple的servicecharacteristics定義,但因為我不是ios developer,所以也不知道定義的方式為何,不過沒關係,網路上很多神人的,下面就有一個 characteristics.h 的定義檔可以參考

characteristics.h

用一個開關當範例說明 (參考characteristics.h)

在SERVICE中需要的的是ON這個Characteristics
NAME就列為選項,可有可無了

/**
 Defines that the accessory contains a switch.
 
 Required Characteristics:
 - ON
 
 Optional Characteristics:
 - NAME
 */
#define HOMEKIT_SERVICE_SWITCH HOMEKIT_APPLE_UUID2("49")


ON這個Characteristics的定義如下

(第6行).permissions中有read、write與notify三個函數
(第9行).value中描述值為BOOL

所以我們共要有三個函數加一個BOOL值

#define HOMEKIT_CHARACTERISTIC_ON HOMEKIT_APPLE_UUID2("25")
#define HOMEKIT_DECLARE_CHARACTERISTIC_ON(_value, ...) \
    .type = HOMEKIT_CHARACTERISTIC_ON, \
    .description = "On", \
    .format = homekit_format_bool, \
    .permissions = homekit_permissions_paired_read \
                 | homekit_permissions_paired_write \
                 | homekit_permissions_notify, \
    .value = HOMEKIT_BOOL_(_value), \
    ##__VA_ARGS__

回到程式碼中,(第13行)struct hap\_characteristic switch1[]中
switch\_state 就是.value的 BOOL 定義,true 就是switch on,false即為switch off
switch1\_read、switch1\_write與switch1\_notify 就分別是三個函數啦
void *accessory_object = hap_accessory_add(acc);
    struct hap_characteristic cs[] = {
        {HAP_CHARACTER_IDENTIFY, (void *)true, NULL, identify_read, NULL, NULL},
        {HAP_CHARACTER_MANUFACTURER, (void *)MANUFACTURER_NAME, NULL, NULL, NULL, NULL},
        {HAP_CHARACTER_MODEL, (void *)MODEL_NAME, NULL, NULL, NULL, NULL},
        {HAP_CHARACTER_NAME, (void *)ACCESSORY_NAME, NULL, NULL, NULL, NULL},
        {HAP_CHARACTER_SERIAL_NUMBER, (void *)"0123456789", NULL, NULL, NULL, NULL},
        {HAP_CHARACTER_FIRMWARE_REVISION, (void *)"1.0", NULL, NULL, NULL, NULL},
    };
    hap_service_and_characteristics_add(acc, accessory_object, HAP_SERVICE_ACCESSORY_INFORMATION, cs, ARRAY_SIZE(cs));


struct hap_characteristic switch1[] = {
        {HAP_CHARACTER_ON, (void *)switch_state,NULL, switch1_read, switch1_write, switch1_notify},
    };
    hap_service_and_characteristics_add(acc, accessory_object, HAP_SERVICE_SWITCHS, switch1, ARRAY_SIZE(switch1));

switch1\_read、switch1\_write與switch1\_notify 三個函數範例程式如下

void *switch1_read(void *arg)
{
    return (void *)switch_state;
}

void switch1_write(void *arg, void *value, int len)
{
    switch_state= ((int)value) ? true : false;

    if (switch_state)
        LED_ON();
    else
        LED_OFF();

    if (_switch1_ev_handle)
        hap_event_response(acc, _switch1_ev_handle, (void *)switch_state);
    return;
}

void switch1_notify(void *arg, void *ev_handle, bool enable)
{
    if (enable)
        _switch1_ev_handle = ev_handle;
    else
        _switch1_ev_handle = NULL;
}



好了,進入主題了,新增PM2.5的Homekit裝置

當我們要使用 air quality 時,需要AIR\_QUALITY的Characteristics,PM2\.5(PM25_DENSITY) 則是列為選項

/**
 Defines that the accessory contains a air quality sensor.
 Required Characteristics:
 - AIR_QUALITY
 
 Optional Characteristics:
 - NAME
 - STATUS_ACTIVE
 - STATUS_FAULT
 - STATUS_TAMPERED
 - STATUS_LOW_BATTERY
 - OZONE_DENSITY
 - NITROGEN_DIOXIDE_DENSITY
 - SULPHUR_DIOXIDE_DENSITY
 - PM25_DENSITY
 - PM10_DENSITY
 - VOC_DENSITY
 - CARBON_MONOXIDE_LEVEL
 - CARBON_DIOXIDE_LEVEL
 */
#define HOMEKIT_SERVICE_AIR_QUALITY_SENSOR HOMEKIT_APPLE_UUID2("8D")

來看看 AIR\_QUALITY 的Characteristics
.permissions 列出 read與notitfy
.value 是 0, 1, 2, 3, 4, 5,共六個有效值

#define HOMEKIT_CHARACTERISTIC_AIR_QUALITY HOMEKIT_APPLE_UUID2("95")
#define HOMEKIT_DECLARE_CHARACTERISTIC_AIR_QUALITY(_value, ...) \
    .type = HOMEKIT_CHARACTERISTIC_AIR_QUALITY, \
    .description = "Air Quality", \
    .format = homekit_format_uint8, \
    .permissions = homekit_permissions_paired_read \
                 | homekit_permissions_notify, \
    .min_value = (float[]) {0}, \
    .max_value = (float[]) {5}, \
    .min_step = (float[]) {1}, \
    .valid_values = { \
        .count = 6, \
        .values = (uint8_t[]) { 0, 1, 2, 3, 4, 5 }, \
    }, \
    .value = HOMEKIT_UINT8_(_value), \
    ##__VA_ARGS__

PM25\_DENSITY 的Characteristics
.permissions 列出 read與notitfy
.value 是 0~1000 的範圍

#define HOMEKIT_CHARACTERISTIC_PM25_DENSITY HOMEKIT_APPLE_UUID2("C6")
#define HOMEKIT_DECLARE_CHARACTERISTIC_PM25_DENSITY(_value, ...) \
    .type = HOMEKIT_CHARACTERISTIC_PM25_DENSITY, \
    .description = "PM25 Density", \
    .format = homekit_format_float, \
    .permissions = homekit_permissions_paired_read \
                 | homekit_permissions_notify, \
    .min_value = (float[]) {0}, \
    .max_value = (float[]) {1000}, \
    .value = HOMEKIT_FLOAT_(_value), \
    ##__VA_ARGS__

有上面這些資料,就可以變成我們的code了,範例如下

struct hap_characteristic air_quality[] = {
    {HAP_CHARACTER_AIR_QUALITY , (void *)air_quality_value,NULL, air_quality_read, NULL, air_quality_notify},
    {HAP_CHARACTER_PM2_5_DENSITY , (void *)pm25_ugm3_value,NULL, pm25_ugm3_read, NULL, pm25_ugm3_notify},
}  
hap_service_and_characteristics_add(acc, accessory_object, HAP_SERVICE_AIR_QUALITY_SENSOR , air_quality,ARRAY_SIZE(air_quality));


寫完,收工~~~~~~






2019年4月22日 星期一

單顆按鍵程式庫 OneButton

markdown
最近在開發的板子,因為當初僅設計一個按鍵,現在又需要進行更多的設定操作,結果外接的IO腳位不夠使用了,便上網搜尋了一下,找到了OneButton Library可以用,連結如下

https://github.com/mathertel/OneButton

它可以透過一個按鍵判斷Click、Double Click、Long Press的狀態,剛好可以滿足現在的應用了

下面是把所有OneButton的Function都列出,可以把需要的Function保留下來就好

#include "OneButton.h"
OneButton button1(GPIO_NUM_0, true);

void click1(){
......
}

void doubleclick1(){
......
}

void longPressStart1(){
......
}

void longPressStop1(){
......
}

void longPress1(){
......
}

void setup(){
    button1.attachClick(click1);
    button1.attachDoubleClick(doubleclick1);
    button1.attachLongPressStart(longPressStart1);
    button1.attachLongPressStop(longPressStop1);
    button1.attachDuringLongPress(longPress1);
}

2019年4月17日 星期三

讓MAC下的終端機bash有顏色




用編輯器打開 ~/.profile
加入
export CLICOLOR="true"
export LSCOLORS="gxfxcxdxcxegedabagacad"
export PS1="\[\e[0;31m\]\u@\[\e[m\e[0;34m\]\h\[\e[m \e[0;32m\]\W >\[\e[m\]"

LSCOLORS 的字串設定順序:

directory
symbolic link
socket
pipe
executable
block special
character special
executable with setuid bit set
executable with setgid bit set
directory writable to others, with sticky bit
directory writable to others, without sticky bit

顏色的對應值:
a -> black
b -> red
c -> green
d -> brown
e -> blue
f -> magenta
g -> cyan
h -> light grey

A -> bold black, usually shows up as dark grey
B -> bold red
C -> bold green
D -> bold brown, usually shows up as yellow
E -> bold blue
F -> bold magenta
G -> bold cyan
H -> bold light grey; looks like bright white
x -> default foreground or background

每個檔案型態有兩個值,前景色和背景色。

以LSCOLORS="gxfxcxdxcxegedabagacad" 做說明,前面的 gx 是設定資料夾顯示的顏色為青色(cyan),底色是預設的前景和背景色;fx
是 symbolic link 的設定,顯示的字是洋紅(magenta),底色是預設的前景和背景色,依此類推。

若希望自已修改,又不想一個字一個字輸入,網路上有小工具,直接用 GUI 設定和預覽,設定好想要的顏色之後,就產生設定字串出來啦。

website: http://geoff.greer.fm/lscolors/

2019年3月29日 星期五

ESP32 讀取 SHT20 溫濕度感測器

markdown


之前在使用ESP8266讀取SHT20時就遇到過,使用網路上的 Library時無法正確讀取溫溼度的問題,但是那時沒時間debug,就一個個的download下來,使用try and error的精神,總算用SHT21的可以使用,就一直沒再去看問題啦

這次使用ESP32讀取時,因沒有紀錄之前哪些程式庫可以使用,就只好重來一次啦,但這次就不打算亂槍打鳥,好好來看一下問題出在哪兒吧

這次使用[DFRobot SHT20](https://github.com/DFRobot/DFRobot_SHT20)的程式庫,照著example code做,得到的結果都是998的數值

Errors 998 if not sensor is detected. Error 999 if CRC is bad.

確認了好幾次,線路明明就有接好呀,怎麼會沒偵測到呢? 最後拿出了LA鈎訊號,一直覺得讀取間隔時間太快了,把間隔拉長後就竟然讀取到溫溼度的數值了

在DFRobot\_SHT20.c的 DFRobot\_SHT20::readValue(byte cmd)程式中,調整 DELAY\_INTERVAL的大小,即為調整間隔時間,我是直接將它延長兩倍時間就可以正確讀取到了
for(counter = 0, toRead = 0 ; counter < MAX_COUNTER && toRead != 3; counter++){
    delay(DELAY_INTERVAL);
    toRead = i2cPort->
    requestFrom(SLAVE_ADDRESS, 3);
}

DELAY\_INTERVAL的定義是在 DFRobot\_SHT20.h 中,所以就修改這個數值,就解決讀不到溫溼度的問題啦

2019年3月21日 星期四

RF 2.4G 無線鍵盤

為了給樹莓派一個好攜帶的鍵盤,在網路上尋找好久,一直沒找到滿意的產品,看到喜歡的價格就不便宜,便宜的外觀又不喜歡,最後終於被我找到一個價格可以接受,外觀也喜歡的產品

打開來看看本尊吧,比樹莓派再大一些些而已,一個USB接收器,一條Micro USB充電線



開關與USB充電都位在頂部,USB接收器先插在我的NB上,打開鍵盤電源開關看看

鍵盤右上方出現白色電源符號,指示鍵盤在開機狀態

鍵盤按鈕還有白色背光會透出,讓在比較昏暗處也可以清楚的看到按鍵功能
關掉電燈,讓背光可以看得更清楚些

輸入的功能,還少了一樣,滑鼠呢

來,我們翻面看看,『Touch Panel』,是觸控板啦
上面有三個圖示,拉近點看看,

一個手指點擊,代表滑鼠左鍵
二個手指點擊,代表滑鼠右鍵
二個手指滑動,可以捲動

滑鼠基本該有的功能都有啦
那操作Touch Panel時,鍵盤不會誤觸嗎?

這產品有內建G-Sensor,會判斷是在哪一面進行操作,會自動把朝下那面的功能取消,所以不用擔心會誤觸

更厲害的是,在操作Touch Panel它會知道上下左右的方向,自動修正方向,而不用去搞清楚說現在的上方在哪裡,下方在哪裡,看圖比較清楚

 不管方向怎麼轉,紅燈都會維持在右上方的位置


還沒完呀,Touch Panel面還有另一項功能,更換LED顏色

四個手指上去,透過RGB三個LED做顏色的混色組合,它就會慢慢變色給你看呢





買到一個顏值高的小鍵盤,除了給樹莓派使用外,偶爾還拿來給客廳的機上盒使用,瀏覽網頁,打字都可以比一般遙控器好操作呢,最後再來看看在手上操作的大小吧









2019年3月20日 星期三

ESP32 Homekit 開關 (SWITCH)

之前使用ESP8266製作Homekit裝置時,都須藉由RPi3當中繼,才能透過手機與Homekit裝置做控制
現在在ESP32上,裝置已經可以獨立運作,不再需要RPi3了

感謝網路上的許多神人們 younghyunjo , maximkulkin

開發ESP32的程式可以使用Arduio IDE的環境,官方網站有提供教學,或是到MAKERPRO也可以喔,不過本篇重點不在Arduino IDE的環境下做開發,就不再多做說明了

開發Homekit的程式,目前似乎都是在ESP-IDF或是ESP-OPEN-RTOS之下所開發的,所以就需要安裝相關的環境做開發,但是還是可以安裝Arduino的元件(Component),就可以混合使用Arduino的語法做開發囉

開始動手

Step 1 照著官方的步驟,安裝ESP-IDF的開發環境吧

Step 2 從Y大的GitHub下載 esp32-Homekit
$ git clone --recursive https://github.com/younghyunjo/esp32-homekit.git

Step 3 修改 examples/switch/main/main.c 裡面WiFi的SSID與WiFi密碼
#define EXAMPLE_ESP_WIFI_SSID "myssid"
#define EXAMPLE_ESP_WIFI_PASS "12345678"  

Step 4 編譯跟燒錄

以開關的範例示範
$ cd examples/switch
$ make
$ make flash

Step 5 配對
可以開啟支援Homekit的iPhone或iPad進行配對了,配對過程中會需要密碼,程式中預設的密碼為053-58-197,可以尋找程式中 hap_accessory_register 函數,自行修改配對密碼

選擇「沒有代碼或無法掃描」選項

可以看到「SWITCH」配件出現,點選它



我們是秉持DIY精神的,所以並沒有通過認證,直接強制加入就可以啦

輸入程式中的預設密碼,053-58-197


開始搜尋配件


找到後,在我們的「家庭」中就可已看到「SWICTH」了,我們可以將它重新命名,如「電燈開關」






直接在「SWITCH」上點擊,燈就會亮起啦 (ESP32 板子上的LED也會跟著亮起)


Free ERP on the Raspberry Pi (odoo)

  #更新系統軟體 sudo apt update && sudo apt upgrade -y #安裝資料庫 sudo apt install postgresql -y #安裝py程序 sudo apt install python3-pip -y #安裝od...