2023-11-18

在 RP2040晶片 試用 KalumaJS

之前在 Raspberry Pi Pico 之類使用 RP2040晶片 的 開發板上使用 Arduino AVR-C 、 MicroPython 、 CircuitPython
最近發現還有一種稱為 KalumaJS 可以在 RP2040晶片 上執行
因此在下嘗試使用,比較其他已經開發成熟的程式碼

安裝 KalumaJS

KalumaJS 是能夠編寫 JavaScript 在 RP2040晶片 執行的程式
KalumaJS 的 韌體檔案 可以在 https://kalumajs.org/ 下載
將 韌體檔案 複製到 RPI-RP2

或使用指令直接下載 及 安裝

對應 RP2040晶片 的 uf2檔案

curl "https://kalumajs.org/download/" | grep '\.uf2' | sed -r 's/.*"(http[^"]+pico-[0-9][^"]+uf2)".*/\1/g'

對應 Raspberry Pi Pico W 版本 的 uf2檔案

curl "https://kalumajs.org/download/" | grep '\.uf2' | sed -r 's/.*"(http[^"]+pico-w-[0-9][^"]+uf2)".*/\1/g'

可以直接在 RPI-RP2 執行指令,並安裝韌體

測試 KalumaJS

KalumaJS 官方提供 Kaluma CLI 來編譯及上載 JS檔案 到使用 KalumaJS韌體 的 RP2040晶片
由於 Kaluma CLI 是 Node.js 其中一種套件,因此如果要使用 Kaluma CLI 還要安裝 Node.js

不過,官方亦在其官方網頁提供 Kaluma CLI IDE ,讓使用者不需要安裝及設定 Node.js 便可以使用編譯及上載
但 Kaluma CLI IDE 需要使用 Web Serial API 才能編譯及上載,而暫時只有 Chromium base 的網頁瀏覽器 能 Web Serial API
因此仍然需要安裝 Chromium base 的網頁瀏覽器才能使用 Kaluma CLI IDE ,但比安裝及設定 Node.js 及 Kaluma CLI 簡單

https://kalumajs.org/ide 便可以使用 KalumaJS CLI IDE

Connect 後會列出所有 序列裝置(Serial Device) , 選擇 RP2040裝置並連接

> 
> .hi
         ___
   _____/ . \   Welcome to Kaluma v1.1.0-beta.4
  /        __>  https://kaluma.io
 |/\________/
  \__@  v  v    Type '.help' for more info.
-----------------------------------------------

> 

在 TERMINAL 會顯示 ASCII 的文字訊息,表示 Kamula CLI IDE 已經連接到 RP2040 並正在運作
然後可以在 Kamula CLI IDE 的 CODE 中編寫 KamulaJS程式 控制 RP2040

編寫 KalumaJS 程式

KamulaJS 官方提供支援 Raspberry Pi Pico 的閃動範本,可以在 Example > Blink 開啟

/**
 * Example: Blink
 * Blinking the on-board LED every 1 second.
 */

const led = 25;
pinMode(led, OUTPUT);
setInterval(() => {
  digitalToggle(led);
}, 1000);

開啟範本後,按 Flash 便可以上載程式到 RP2040

> 
> .flash -w
Transfer a file via YMODEM... (press 'a' to abort)
CCCCCCCCCCCCCCC
Done
> 
> .load
> 

Kaluma CLI IDE 使用 YModem協議 顯示狀態,在 TERMINAL 會以 C 表示進度或載入狀態
沒有出錯完成操作程序,不會顯示任何訊息
操作異常導致進度無法完成不會逾時,需要按 a 手動終止操作
完成後 RP2040裝置 便會顯示效果

KalumaJS 語法風格

KamulaJS 使用 JerryScript 是一種專為編寫 微控制器 程式的 JavaScript

模仿 Arduino AVR-C 語法

語法上使用 Arduino AVR-C 常見的 pinMode 、 digitalWrite 、 delay 等 功能名稱及參數
並以 JavaScript 的 setInterval 替代 loop 等關鍵功能,容易由 Arduino 的概念理解及學習

const LED = 25;
pinMode(LED, OUTPUT);
setInterval(() => {
	digitalWrite(LED, HIGH);
	delay(1000);
	digitalWrite(LED, LOW);
	delay(1000);
}, 0);

以 Arduino AVR-C 風格編寫 KalumaJS 程式,執行結果與 KalumaJS 例如相同

模仿 *Python 語法

除了模仿 Arduino AVR-C 語法,還提供類似 MicroPython 及 CircuitPython 的 物件導向 語法存取 GPIO

const { GPIO } = require("gpio");
const GPIO25 = new GPIO(25, OUTPUT);
setInterval(() => {
	GPIO25.write(HIGH);
	delay(1000);
	GPIO25.write(LOW);
	delay(1000);
}, 0);
const { LED } = require("led");
const LED = new LED(25);
setInterval(() => {
	LED.on();
	delay(1000);
	LED.off();
	delay(1000);
}, 0);

兩個例子都是相同的結果

雖然有些重覆,但當程式巨大時,以類別方式編寫程式比較容易區分用途
GPIO類別 可以控制 輸入及輸出, LED類別 只可以控制 輸出

KalumaJS 語法限制

由於 KalumaJS 繼承 JavaScript ,因此具備一些 Arduino AVR-C 沒有的類型,例如:
boolean 、 null 、 undefined

const LED = 25;
pinMode(LED, OUTPUT);
setInterval(() => {
	digitalWrite(LED, !digitalRead(LED));
}, 1000);

由於 Arduino AVR-C 實際沒有 boolean 類型,因此 !digitalRead 傳回 0 或 1
因此在 Arduino 中容許 digitalWrite(LED, !digitalRead(LED)) 這種語法
但 JavaScript 具有 boolean 類型,因此 !digitalRead 傳回 true 或 false
不符合 digitalWrite 參數的要求而發生錯誤, TERMINAL 會顯示

> TypeError: "value" argument must be a number
at <anonymous>:4

RP2040 Matrix

在下除了使用 Raspberry Pi Pico ,亦使用其他 RP2040晶片 開發板測試效果

外觀

RP2040 Matrix 的正面
體積基本上與 RP2040 Zero 相同,主要是正面焊接了 25粒 RGB LED

使用 USB Type-C 插孔

RP2040 Matrix 的背面
所有核心零件都焊接在背面

Raspberry Pi 的 RP2040晶片

BOOT按鈕
當 BOOT按鈕 按下時起動 RP2040 Matrix ,會進入 起動模式,能夠更新 RP2040 的韌體
與 Raspberry Pi Pico 相同

EN按鈕
其實即是 重設 (RST) ,按下放開後會重新啟動 RP2040 Matrix

但 BOOT按鈕 及 EN按鈕

引腳

RP2040 Matrix 的引腳與 RP2040 Zero 及 RP2040 One 相同,因此不重覆在此介紹
可以到 RP2040-Zero 引腳 @ 使用 RP2040微控制器 控制 NeoPixel 翻查資料
GPIO16 仍然是用作控制 RGB LED 的引腳,但沒有 GPIO17 至 GPIO25 的 SMD引腳

LED佈局

RP2040 Matrix 總共有 25粒 RGB LED 焊接在 正面, 使用 WS2812B 驅動器
佈局及操作方式與一般 RGB LED Matrix 相同

KalumaJS 匯入函式庫

KalumaJS 除了原生的函式庫,亦有提供第三方的函式庫
可以到 https://kalumajs.org/packages/ 安裝

不過 KalumaJS CLI IDE 沒有提供安裝操作,因此不能匯入函式庫,但仍然可以將第三方函式庫的原始碼直接複製到 CODE 來執行
匯入函式庫其實只是將已有的程式碼載入到主程式,例如 RP2040 Matrix 的 WS2812B 使用 NeoPixel 函式庫
操作方法與 NeoPixel燈板 @ 使用 RP2040微控制器 控制 NeoPixel 的相同
由於無法安裝函式庫,因此在下到 https://raw.githubusercontent.com/niklauslee/neopixel/main/index.js
將整個函式庫的原始碼複製到 CODE 中

// NeoPixel class copied from "https://raw.githubusercontent.com/niklauslee/neopixel/main/index.js"
// NeoPixel class start
const { PIO, ASM, StateMachine } = require("rp2");
class NeoPixel {
	constructor(pin, len, options = {}) {
		this.pin = pin;
		this.length = len;
		this.smId = options.sm ?? StateMachine.getAvailableId();
		this.hz = options.hz || 800000;
		this.buf = new Uint32Array(this.length);
		this.buf.fill(0);
		const asm = new ASM({
			"sideset": 1
		});
		asm
			.label("bitloop")
			.out("x", 1)
			.side(0)
			.delay(2)
			.jmp("!x", "do_zero")
			.side(1)
			.delay(1)
			.label("do_one")
			.jmp("bitloop")
			.side(1)
			.delay(4)
			.label("do_zero")
			.nop()
			.side(0)
			.delay(4);
		this.sm = new StateMachine(this.smId, asm, {
			"freq": this.hz * 10,
			"autopull": true,
			"pullThreshold": 24,
			"fifoJoin": PIO.FIFO_JOIN_TX,
			"sidesetBase": this.pin,
			"outShiftDir": PIO.SHIFT_LEFT
		});
		this.sm.active(true);
	}
	color(r, g, b) {
		return (g << 24) | (r << 16) | (b << 8);
	}
	setPixel(index, color) {
		this.buf[index] = color;
	}
	getPixel(index) {
		return this.buf[index];
	}
	clear() {
		this.buf.fill(0);
	}
	show() {
		this.sm.put(this.buf);
	}
}
// comment or delete the line "exports.NeoPixel = NeoPixel;"
//exports.NeoPixel = NeoPixel;
// NeoPixel class end
const PIN = 16;
const LENGTH = 25;
const neopixel = new NeoPixel(PIN, LENGTH);
setInterval(() => {
	for (let i = 0; i < LENGTH; i++) {
		neopixel.clear();
		neopixel.setPixel(i, neopixel.color(8, 8, 8));
		neopixel.show();
		delay(100);
	}
}, 0);

結果能夠正確運作

總結

在下早於 2年前 已經發現 KalumaJS 這個專案,當時 KalumaJS 亦沒有提供 KalumaJS CLI IDE ,需要自行安裝 Node.js 及 KalumaJS CLI
KalumaJS 隨後提供 KalumaJS CLI IDE , 類似 Arduino Web Editor
只需要網頁瀏覽器支援 Web Serial API 便能夠編譯及上載,不需要安裝特定軟件及設定便可以使用

由於語法與 Arduino AVR-C 、 MicroPython 及 CircuitPython 非常相似,在下亦有編寫 JavaScript ,因此學習相對容易
但亦由於太相似,在下曾經使用類似 MicroPython 及 CircuitPython 的迴圈語法作為 loop 的操作
結果導致 Raspberry Pi Pico 不能上載程式,即使重新安裝 KalumaJS韌體 亦無法再次使用
最後還是要用 flash_nuke.uf2 將還原 Raspberry Pi Pico

操作其實與之前的 使用 RP2040微控制器 控制 NeoPixel 相同
只是 RP2040 Matrix 具備 5x5 WS2812B 能即時製作類似 RGB燈板 的效果

另外還試用 Micro REPL 能夠在 Android 在修改 MicroPython裝置
雖然不及 CircuitPython 能夠將裝置當作儲存裝置列出及編輯檔案
但都能夠方便地使用 Android 即時修改裝置的程式

參考資料

沒有留言 :

張貼留言