參考 https://gist.github.com/neoyagami/5f431928997dbf255e84e4c937983e8e
4.2.2 board,如下圖。
BL_T 接頭,IN (PB0) 當輸出,控制伺服馬達。OUT (PB1) 當輸入,接 probe 信號。
參考 https://gist.github.com/neoyagami/5f431928997dbf255e84e4c937983e8e
4.2.2 board,如下圖。
BL_T 接頭,IN (PB0) 當輸出,控制伺服馬達。OUT (PB1) 當輸入,接 probe 信號。
目的,加上 ILI9488 LCD 的驅動程式。
因為建立的 external module,載入時會失敗,只好把驅動程式加入建立 image 時的 kernel source 中,這樣建立的 module 就可以使用。只是很難debug,就找現成的來用 吧。
先 git clone https://github.com/armbian/build
再執行一次 build,不用到最後,只要建立 kernel source 就好
然後把 cache 下的對應的 kernel source,整個複製到新的目錄,如 [6.6_sunxi_armhf_wk]。然後,到新的目錄下,執行 make clean,把編譯的檔案刪掉。刪掉 .git 檔,再執行下列指令,建立啟始的 git 專案。
再把驅動程式,如 fb_ili9488.c,複製到對應的目錄下,如 drivers/staging/fbtft,並修改相關的檔案,如 drivers/staging/fbtft 目錄下的 Kconfig 和 Makefile。
然後執行下列指令,提交程式修改。
再將這個 patch 檔,複製到 patch/kernel/archive/sunxi-6.6/patches.armbian/ 下,並修改 series.armbian 和 series.conf,加入這個 patch 檔。
修改 config/kernel/linux-sunxi-legacy.config,加入 CONFIG_FB_TFT_ILI9488=m。
然後,build image,測試結果。
先展示一下成果,放張照片,當作紀念。要走到這邊,實在不容易。
因為貪便宜,也為了改 3D印表機不要花太高的成本,在網路上買了好幾片 Orange Pi One 的單板電腦。
可能因為用的晶片太舊,新的 Kernel 在支援上會有問題。例如目前的 kernel 是 6.12.30,同樣的程式,在 Orange Pi Zero 3 上,可以正常執行,但在 Orange Pi One 就是怪怪的,使用 tinydrm 的 module,完全無法啟動 X window。經反覆測試,確認在較舊的 kernel 6.6.75 上,才能正常執行。另外,armbian/build 的 32位元的 sunxi 的 kernel,沒有把 gpio-backlight 編成 module,dts 中,無法控制背光。
使用 panel-mipi-dbi-spi,在 Orange Pi Zero3 下,可以正常運作,也可以執行 KlipperScreen。但在 Orange Pi One,相同的設定檔,會出現下面的錯誤訊息。後來確認,背光控制要有 gpio_backlight 的 kernel module。
$ dmesg | less
[ 18.163593] panel-mipi-dbi-spi spi0.0: supply power not found, using dummy regulator
[ 18.163853] panel-mipi-dbi-spi spi0.0: supply io not found, using dummy regulator
[ 18.164817] spi spi0.0: deferred probe pending: panel-mipi-dbi-spi: Failed to get backlight
$ sudo modprobe gpio_backlight
[sudo] password for klipper:
modprobe: FATAL: Module gpio_backlight not found in directory /lib/modules/6.12.23-current-sunxi
另外,Orange Pi Zero3 的 image 裡,有 fb_st7796s 的模組,在 Orange Pi One 則沒有。
使用 6.12.30-current-sunxi,雖然 console 是正常的,但啟動 X window,就會出現 Bus error。
$ X
X.Org X Server 1.21.1.7
X Protocol Version 11, Revision 0
Current Operating System: Linux orangepione 6.12.30-current-sunxi #2 SMP Thu May 22 20:29:54 CST 2025 armv7l
Kernel command line: root=UUID=4c8b2287-edb5-431a-904c-a21f8f213ef8 rootwait rootfstype=ext4 splash=verbose console=ttyS0,115200 console=tty1 hdmi.audio=EDID:0 disp.screen0_output_mode=1920x1080p60 consoleblank=0 loglevel=1 ubootpart=d0be82e5-01 ubootsource=mmc usb-storage.quirks=0x2537:0x1066:u,0x2537:0x1068:u sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_fb_mem_reserve=16 cgroup_enable=memory
xorg-server 2:21.1.7-3+deb12u9 (https://www.debian.org/support)
Current version of pixman: 0.42.2
Before reporting problems, check http://wiki.x.org
to make sure that you have the latest version.
Markers: (--) probed, (**) from config file, (==) default setting,
(++) from command line, (!!) notice, (II) informational,
(WW) warning, (EE) error, (NI) not implemented, (??) unknown.
(==) Log file: "/var/log/Xorg.0.log", Time: Mon Jun 23 14:36:07 2025
(==) Using config directory: "/etc/X11/xorg.conf.d"
(==) Using system config directory "/usr/share/X11/xorg.conf.d"
(EE)
(EE) Backtrace:
(EE)
(EE) Bus error at address 0xb6185000
(EE)
Fatal server error:
(EE) Caught signal 7 (Bus error). Server aborting
(EE)
(EE)
Please consult the The X.Org Foundation support
at http://wiki.x.org
for help.
(EE) Please also check the log file at "/var/log/Xorg.0.log" for additional information.
(EE)
(EE) Server terminated with error (1). Closing log file.
Aborted
另外,使用 6.12.30-current-sunxi,自行編譯的 fb_st7796s 或 fb_ili9488 模組,也不能正常運作,會變得一片白屏。
經過反覆的測試,確認 Orange Pi One 的 32位元的系統,要使用 6.6.75 的 kernel 才能正常運作。
再持續地做各種嘗試,發現使用 edge 的 image,6.15 的 kernel 可以正常運作。比對 6.12 和 6.15 的 driver 原始碼,發現程式有不少的變動,6.12 的可能有一些 bug 吧。那就用最新的吧。
至於 ILI9488界面的 LCD,因為必須使用 666 的格式,6.12 之後可以支援,但是使用 X 仍會當,最好暫時不要用。
後來自行照著 armbian 的 build 說明,自行 build image,終於可以正常安裝執行 KlipperScreen。
複製 armbian/build 的程式。
$ git clone https://github.com/armbian/build
然後修改 build/config/kernel/linux-sunxi-legacy.config,增加 build gpio_backlight 和 fb_st7796s 的 kernel module。
.......
CONFIG_BACKLIGHT_QCOM_WLED=m
CONFIG_BACKLIGHT_RT4831=m
CONFIG_BACKLIGHT_GPIO=m
CONFIG_BACKLIGHT_LED=m
........
CONFIG_FB_TFT_ST7735R=m
CONFIG_FB_TFT_ST7789V=m
CONFIG_FB_TFT_ST7796S=m
CONFIG_FB_TFT_TINYLCD=m
........
執行 compile.sh。
$ ./compile.sh \
BOARD=orangepione \
BRANCH=legacy RELEASE=bookworm \
BUILD_MINIMAL=yes BUILD_DESKTOP=no \
NETWORKING_STACK="network-manager" \
KERNEL_CONFIGURE=no \
INSTALL_HEADERS=yes \
KERNEL_BTF=yes
編譯完成,產生的 image。
$ ls build/output/images/
Armbian-unofficial_25.08.0-trunk_Orangepione_bookworm_legacy_6.6.75_minimal.img
Armbian-unofficial_25.08.0-trunk_Orangepione_bookworm_legacy_6.6.75_minimal.img.sha
Armbian-unofficial_25.08.0-trunk_Orangepione_bookworm_legacy_6.6.75_minimal.img.txt
在網路上購買的便宜裸裝 TF 卡,容量 32GB,一片只要 50元,大約是便宜的威剛同容量的 TF 卡的一半價格。
nexby,沒聽過的品牌,made in Taiwan,好像還不錯。
但是先前曾在淘寶買便宜的 TF卡,結果根本不能用。這次只敢買 3片,湊成免運。等確定可用再多買。
測試軟體,F3 (Fight Flash Fraud or Fight Fake Flash) ,可參考 f3read 及 f3write 指令說明。
安裝
看來便宜的無名 SD 卡表現不錯,至於工程卡,終究是早期的產品,有點慢。
Linux 的 fb-tft 對 ILI9341 有完整的支援,但是解析度只有 320x240。KlipperScreen 要求的最低解析度是 480x320,若解析度低於這要求,雖然還是可以執行,但字跡會變模糊不清。
在淘寶可以找到較多人使用,480x320 的 SPI 界面 LCD,其控制晶片為 ILI9488/9486,另外則是 ST7796。因為搜尋 SPI LCD 的方案,大多會找到 ILI9488 相關的,因此先買 ILI9488 / ILI9486 來測試。很辛苦的改驅動,編譯 kernel module,最後是成功了。但是系統一更新,又變得改的程式都不能用了。
經過交叉測試,發現 Fly PI 的 LCD,使用 ST7796 控制器,用 fb_ili9341 的 driver,竟然能夠點亮,雖然顯示不正常,但可以看到在 320x240 的範圍內,正常顯示。
這表示 ST7796 可以使用 RGB565 的格式,經測試,只要把 fb_ili9341 的驅動程式的解析度改成 480x320 即可使用,幾乎完全不用改到程式的其他部分。
淘寶買 ili9488 的 LCD,用 fb_ili9341 的驅動程式來改,只會一片白屏。使用 fb_ili9486.c 來改,若 PIXEL_FORMAT 是 0x55,顯示一片白屏。將 PIXEL_FORMAT 是 0x66,會輸出雜亂的顯示。再加上轉換的 function,則可以成功驅動。
這類控制晶片透過 SPI 界面串列的傳送視訊資料,為了減少資料量,一個畫素 (pixel) 通常用 RGB565 或 RGB666 的格式。RGB565 為 R: 5bits, G: 6bits, B:5bits,共 16bits,傳送時,一個畫素佔 2bytes。RGB666 為 R: 6bits, G: 6bits, B:6bits,共 18bits ,傳送時,一個畫素佔 3bytes。相同的頻寬,後者可傳送的資料量只剩 2/3。
ILI9488 / ILI 9486,確定只能使用 RGB666 的格式。因此,較佳的選擇是買 ST7796 控制的 LCD。但 ILI9488 的 LCD,有較小的 3.5" 螢幕的選擇,價格更低。
能夠找到的資訊,有的有點過時,或者,更新後,OS 版本太新,舊的方式不能用。因此雜亂地收集了一堆可能用得到的參考,等確定作法,再將沒用的刪除。
升級至最近的 kernel 6.12.30 之後,可以使用 tiny drm 的 panel-mipi-dbi-spi 模組,不用自行編譯 kernel module 了,方便很多。
LCD 的 SDO 和觸控的 T_DO 都是接到 host 的 MISO。這兩支腳都是輸出,若將這兩支腳短路,可能會使得觸控不能運作。
將這兩支腳短路,在 ILI9341 的板子上沒問題,在 ILI9486 或 ILI9488 上,卻使得觸控不能運作。經過不斷的測試,花了好久的時間,才確認問題。
要同時驅動 LCD 和觸控,照著 ILI9341 測試成功的作法,將 SCK, SDO, SDI 三支腳都短路,然後 ILI9486 和 ILI9488 的觸控一直都沒反應。
先前因為 ads7846 驅動的設定改變,花了不少時間才解決。因而一開始也懷疑是 DTS 設定問題,或是某些 MCU 的接腳不能用。把手邊各種不同的 LCD 都拿來測試,包括 Fly Pi 的螢幕。改變各種設定,還是不能動作。
只能懷疑是 IC 壞掉,或是電阻膜被我弄壞。拿一塊新的 ILI9488,還沒把接腳短路,單獨測觸控功能,正常。但將接腳一短路,就掛了。
準備去買幾顆 IC 來換,發現 ILI9341 板子上的觸控 IC 是 XPT2046,ILI9488 板子上的觸控 IC 是 HR2046,是相容的 IC,才懷疑可能是 IC 的輸出短路造成問題。將 SDO 的短路線剪掉,測試觸控功能,OK。
LCD 沒用到 SDO,那就不要將這支腳短路吧,這樣 LCD 和觸控都正常了。
在 Orange PI Zero3,6.6.75-current-sunxi64,PC9 接腳不能用。
開始測試時,kernel 版本是 6.6.75,測試成功後。升級後,kernel 版本變 6.12.30,又變成不能驅動 LCD 了,會出現 "cannot register SPI host" 的錯誤。
經過好久,終於撈到解答。
/dts-v1/;
/plugin/;
/ {
compatible = "xunlong,orangepi-zero3", "allwinner,sun50i-h616";
fragment@0 {
target = <&spi1>;
__overlay__ {
status = "okay";
pinctrl-names = "default"; // new for linux 6.12
pinctrl-0 = <&spi1_pins>; // new for linux 6.12
cs-gpios = <&pio 2 7 0>; /* PC7 */
st7796s: st7796s@0 {
compatible = "sitronix,st7796s";
reg = <0>; /* Chip Select 0 */
#spi-cs-high;
spi-max-frequency = <40000000>;
rotate = <180>;
bgr = <0>;
fps = <30>;
width = <480>;
height = <320>;
buswidth = <8>;
reset-gpios = <&pio 2 6 1>; /*RESET=PC6*/
dc-gpios = <&pio 2 5 0>; /*DC_RS=PC5*/
led-gpios = <&pio 2 8 0>; /*LED=PC8*/
debug = <4>;
};
};
};
};
要加上 pinctrl-names = "default"; 和 pinctrl-0 = <&spi1_pins>; 。
在網路上收的二手機。
$ cd klipper
$ make menuconfig
[*] Enable extra low-level configuration options
Micro-controller Architecture (Atmega AVR)
Processor model (atmega2560)
$ make
Creating symbolic link out/board
Building out/autoconf.h
Compiling out/src/sched.o
.................
Compiling out/src/generic/serial_irq.o
Building out/compile_time_request.o
Version: v0.12.0-458-gd886c1761
Linking out/klipper.elf
Creating hex file out/klipper.elf.hex
$ make
$ make flash FLASH_DEVICE=/dev/serial/by-id/usb-RRD__www.ru_RUMBA_-_ATmega_2560_co_55437333437351B0A120-if00
重新啟動系統。
參考 requireJs中使用Vue3及Vue3框架(viewUIPlus、elementPlus)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
<script src="js/lib/require.js" data-main="js/script/main"></script>
</head>
<body>
require.config({
// 加載 js 的目錄,paths 中以此目錄為標準讀取
baseUrl: 'js',
// 類庫别名和路徑配置
paths: {
jquery: 'lib/jquery-3.7.1',
// vue 别名必须為 vue,由於其他框架或模块寻找 vue 时查询的是 vue 的别名
vue: 'lib/vue3/vue.global.prod',
// viewUIPlus框架
viewUIPlus: 'lib/viewUiPlus/viewuiplus.min',
// elementPlus 框架
elementPlus: 'lib/elementPlus/index.full.min',
// elementPlus 字体库
elementPlusIconsVue: 'lib/elementPlus/icons-vue/dist/index.iife.min',
},
// 依赖以及导出设置,key值需对应paths中的别名,用于非AMD标准的类库进行导出
shim: {
// 由于vue3不是标准的AMD模块,需要手动抛出Vue变量,供其他框架使用
'vue': {
exports: 'Vue'
},
// viewUIPlus css
'viewUIPlus': ['vue', 'css!lib/viewUiPlus/styles/viewuiplus.css'],
// elementPlus 字体库依赖vue 没有这个配置,加载字体库时可能因为vue还未加载而报错
'elementPlusIconsVue': {
// 依赖
deps: ['vue'],
// 导出变量
exports: 'ElementPlusIconsVue',
},
// elementPlus css 字體庫
'elementPlus': ['vue', 'css!lib/elementPlus/index.css', 'elementPlusIconsVue',],
},
// 插件以及其他模塊配置
map: {
'*': {
// 加載 css 插件
'css': 'lib/require-css'
},
},
});
// 單獨使用 vue
require(['vue'], function (Vue) {
const {createApp} = Vue
const app = createApp({
data() {
return {
message: 'Hello Vue!',
}
},
methods: {}
})
app.mount("#app");
})
// viewUIPlus vue依赖已在shim中配置,无需再次引入
require(['viewUIPlus'], function (ViewUIPlus) {
const {createApp} = Vue
const app = createApp({
data() {
return {
message: 'Hello viewUiPlus!',
}
},
methods: {}
})
app.use(ViewUIPlus);
app.mount("#viewUi");
})
// elementPlus 字体库和vue依赖已在shim中配置,无需再次引入
require(['elementPlus'], function (ElementPlus) {
const {createApp} = Vue
const app = createApp({
data() {
return {
message: 'Hello elementPlus'
}
},
methods: {}
})
// 字体库组件
for ([name, comp] of Object.entries(ElementPlusIconsVue)) {
app.component(name, comp);
}
app.use(ElementPlus);
app.mount("#ele");
})
require.config({
baseUrl: ntuweb.baseUrl+'/assets',
paths: {
"jquery": "jquery-1.12.4.min",
"jqueryform": "jquery.form.4.2.2.min",
"jqueryui": "jquery-ui/jquery-ui-1.10.4.custom.min",
"vue": "vue_2.6.14",
'vue3': "vue.global-3.5.12.min",
"showModalDialog": "showModalDialog",
'corejs': 'corejs-2.6.12_shim.min'
, 'swal': 'sweetalert2-10.min'
},
// 以下為非 AMD 程式,有固定的載入順序
shim : {
// 由於 vue3 不是準的 AMD 模塊,需要手動拋出 Vue 變量,用於非AMD標準類庫進行導出
'vue3': {
exports: 'Vue'
},
"jqueryui": ["jquery"],
"jqueryform": ["jquery"]
, 'swal': ['corejs']
, "showModalDialog": ["jqueryui"]
, 'wbSingle': ['swal']
}
});
使用 Vue2
require(['jquery', 'vue', 'showModalDialog', 'jqueryform'], function($, Vue)
{
vm = new Vue({
el: '#main-div',
data: {
dat: <?= json_encode($gdat) ?>,
frm_label: '',
LbState: 0,
},
computed: {
.....
},
methods: {
.....
}
});
});
使用 Vue3
rrequire(['jquery', 'vue3', 'showModalDialog', 'jqueryform'], function($, Vue)
{
const { createApp, ref ,reactive, computed} = Vue;
vm = createApp({
setup() {
const dat = reactive({
cou_code: ref(''),
cou_cname: ref(''),
credit: ref(0),
..........
});
const frm_label = ref('');
const LbState = ref(0);
return {
dat, frm_label, LbState,
}
},
computed: {
..........
},
methods: {
...........
}
}).mount('#main-div');
});
更新物件 dat 的屬性的值
Object.keys(vm.dat).forEach(function (kk) {
vm.dat[kk] = ret[kk];
});