nodemcujs 是一个在 ESP32 芯片上的 JavaScript 运行时。不同于 NodeMcu,这是在 ESP32 芯片上运行了一个真正的 JavaScript 虚拟机。在 ESP32 上编写 JavaScript 就和编写 NodeJS 程序一样。并且提供了一个 32MBit 的片上虚拟文件系统,你可以编写模块化的应用,然后使用 require() 导入模块。甚至直接将你的兼容 NodeJS 模块运行在 ESP32 上,而无需做任何改动。
website: https://timor.tech 正在编写文档,under the development
github: https://github.com/nodemcujs/nodemcujs-doc
这是 nodemcujs 的网站,所有文档和最新信息将会发布在这里。也可以通过 fork 项目贡献文章。文档还在不断完善中。
HTTP Client
WIFI
SPI
Sigmadelta Modulation
Remote Control
驱动
Node
var foo = require('/foo.js')
console.log('hello nodemcujs')
process.delay(1000) // sync and non-block
setTimeout(function() {
console.log('timeout')
}, 1000)
console.log('hello world')
var wifi = require('wifi')
wifi.init();
wifi.setMode(wifi.WIFI_MODE.STA);
wifi.setConfig(wifi.WIFI_MODE.STA, {
ssid: 'SSID',
password: 'PASS',
auth: wifi.WIFI_AUTH_MODE.WIFI_AUTH_WPA2_PSK
});
wifi.start();
wifi.connect(); // connect to ap
快速在本地环境构建出可执行的固件并烧写到 ESP32 芯片上。
项目使用 CMake cmake_minimum_required (VERSION 3.5)
构建。
我在 MacOS 10.13、Ubuntu 18.04.2 LTS、Windows 10 中已验证构建通过,你可以选择适合自己的开发环境。
在 Windows 中环境设置比较麻烦,请仔细参照官方文档进行环境安装,我多数在 Ubuntu 下进行开发测试。
参照官方文档进行安装。注意本项目使用的是 V4.3.1 版本,理论上 v4 全系版本都支持的。
ESP-IDF(V4.3.1): https://docs.espressif.com/projects/esp-idf/zh_CN/v4.3.1/esp32/get-started/index.html#esp-idf
你也可以在没有安装 git 的环境中下载源码包: https://dl.espressif.com/dl/esp-idf/releases/esp-idf-v4.3.1.zip
在设置工具链前,请按照对应的系统安装必须的软件包:
然后按照官方文档进行编译工具链的安装:
$ git clone --recursive git@github.com:nodemcujs/nodemcujs-firmware.git
项目已经将 JerryScript 作为子模块,存放在 /deps/jerryscript
目录下。clone
的时候会一并将所有子模块 clone 下来。
如果你忘记了在 clone
时候加 --recursive
选项,那么你可以通过下面的命令单独 clone 子模块
。
$ git submodule update --init
先进入项目根目录:
$ cd nodemcujs-firmware
创建 build 文件夹,为了编译后的临时文件不影响源码目录。
$ mkdir build
$ cd build
使用 Cmake 构建
$ cmake ../
可选步骤。配置构建参数。大多数情况下使用默认参数就可以,这里一般只需要配置好串口和波特率。
$ make menuconfig
注意: 项目使用了自定义的分区表。详情可以查看分区表文件 partitions.csv
最后进行编译固件。
$ make
如果编译成功,会生成 4 个文件:
使用下面的命令进行固件的烧录。
$ make flash
如果你看到控制台输出如下信息,并一直停留,那么你需要手动让 ESP32 芯片进入下载模式。
esptool.py --chip esp32 -b 460800 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x1000 bootloader/bootloader.bin 0x8000 partition_table/partition-table.bin 0x10000 nodemcujs.bin
esptool.py v2.6
Found 3 serial ports
Serial port /dev/ttyUSB0
Connecting........___........___
等待烧录完成,重启 ESP32 就可以了。
注意:make flash 会自动烧录文件镜像,此文件镜像就是 spiffs 目录下的文件。
系统上电会默认启动用户文件系统中的 /index.js,所以你的应用入口可以写在这里。
此外你还可以使用 ESPlorer 连接上 ESP32,输入 JavaScript 和它进行交互了。
对于没有或者不方便安装 ESP-IDF 工程的用户,可以使用烧录工具进行烧录已经构建好的固件。
我们推荐使用 esptool.py 工具进行烧录。可以从 release 页面下载已经构建好的固件。
Tips: ESP-IDF 内置了 esptool.py
工具,可以直接使用。路径在 $IDF_PATH/components/esptool_py/esptool/esptool.py
$ python esptool.py --chip esp32 -p /dev/ttyUSB0 -b 460800 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x1000 bootloader.bin 0x8000 partition-table.bin 0x10000 nodemcujs.bin 0x00110000 storage.bin
这里有几点需要说明:
-b 参数表示下载固件时使用的波特率,如果出现烧录失败等问题,请尝试降低波特率为 115200 或者 9600。这可能是劣质的串口芯片造成的。
-p 参数表示 ESP32 芯片在你电脑上的串口设备,请替换为实际的值或者端口号。在 Windows 上的可能值为 COM3。
0x1000 和 0x8000,以及 0x10000 使用的是默认值。
第一次烧录需要这 3 个文件,以后烧录只需要一个 nodemcujs.bin 文件就行了。
storage.bin 是可选的,系统启动只需要前面三个固件即可。
nodemcujs 使用 spiffs 作为默认文件系统,容量大约为 2.7MB
,所以文件的总大小不能超出此范围。关于为什么容量只有 2.7MB,请参考 partitions.csv。
我们建议将要烧录到 flash 存储的文件放到 spiffs
文件夹内,在我们的构建系统中,我们将会自动构建 flash 镜像并随固件一起烧录。文件系统是默认以 /
为根目录的。
制作文件镜像有多种方式,我们推荐使用 nodemcujs 里面集成的方式:
spiffs
文件夹内。make spiffs_storage_bin
命令即可一键制作文件镜像。spiffs
文件夹下面的所有文件打包成一个 storage.bin
镜像。手动制作文件镜像
我们使用 mkspiffs 来制作镜像。这是 C++ 工程,首先你要编译它,得到可执行文件 mkspiffs
。
$ mkspiffs -c spiffs -b 4096 -p 256 -s 0x2F0000 storage.bin
上面的命令会将 spiffs
文件夹内的全部文件打包成镜像,并且在当前目录生成 storage.bin
文件。
这里有几点需要注意:
-s 0x2F0000 是 nodemcujs 所使用的大小,至少在目前你不能大于此值。除非你自己定义分区表。
编译 mkspiffs 时需要传递参数:
CPPFLAGS="-DSPIFFS_OBJ_META_LEN=4"
否则会出现 nodemcujs 文件系统无法工作。
nodemcujs 会在启动时检查分区,如果无法挂载 storage
分区,则会自动格式化 storage
分区并挂载。
你可以将你的 JavaScript 应用或者任何文件烧录到 ESP32 上,nodemcujs 会在启动时自动加载 /spiffs/index.js
文件,所以这可能是自动启动应用的一个好主意。
烧录文件镜像有多种方式,我们推荐使用 nodemcujs 里面集成的方式:
make flash-storage
命令即可一键烧录文件镜像。手动烧录文件镜像
$ python esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 115200 write_flash -z 0x110000 storage.bin
手动烧录文件镜像请将 /dev/ttyUSB0 替换为你实际的设备,或者自动选择设备。
有几点需要注意:
一旦你烧录文件镜像,则原来的分区会被覆盖掉,请知道你自己在做什么。
-z 0x10000 是目前 nodemcujs 默认分区表参数,至少在目前你不能小于此值,否则 app 程序可能会被覆盖。
jerryscript 作为一个子模块放置在 /deps/jerryscript
目录下,所以更新 jerryscript 很方便,进入 /deps/jerryscript
目录,使用 git
拉取最新 commit
就行了。
或者手动下载最新 jerryscript 文件替换掉。
硬件驱动部分或者性能要求高的部分,我们必须使用 C\C++ 编写,这个时候就需要用到 native
模块了。比如 GPIO
模块。
在这之前,有几个关于模块的概念必须要搞清楚:
注意:通常内置模块包含一个对应的 native模块,我们把 内置js 和 native模块 统称为 内置模块。比如 console。 如果一个内置模块有对应的 native模块,则 nodemcujs 会自动将对应的 native模块 注入到 内置js模块中,通过 native 全局变量引用。
native
模块是由 C\C++ 编写的模块,它和 JS 文件模块的使用方法是一样的。native模块以 nodemcujs_module_xxx.c
命名,存放在 /main/src/modules
文件夹下,我们规定 native
模块都必须有一个 nodemcujs_module_init_xxx
方法用于导出,该函数的返回值是 jerry_value_t
类型。
下面我们以编写 GPIO
模块为例。
首先我们编写该模块的 init 函数:
// main/src/modules/nodemcujs_module_gpio.c
jerry_value_t nodemcujs_module_init_gpio()
{
jerry_value_t gpio = jerry_create_object();
// ......
return gpio;
}
新增native模块后,需要重新执行 cmake ..
构建。然后我们就可以通过 var gpio = require('gpio')
使用了。
此外,我们还可以再编写一个对应的内置js模块,把native模块通过js包装成更友好的API:
// main/src/js/gpio.js
var gpio = native; // 这个全局变量 native 就是 C函数 nodemcujs_module_init_gpio 返回的对象
function GPIO(pin) {
this.pin = pin;
}
GPIO.prototype.mode = function(mode) {
gpio.mode(this.pin, mode);
}
GPIO.prototype.write = function(level) {
gpio.write(this.pin, level);
}
module.exports = GPIO;
最后在 JS 中使用它:
var GPIO = require('gpio') // 此时 gpio 就是 gpio.js 到处的对象了
native
模块是有 缓存
的,init 方法被调用后,会将模块的值缓存起来,以后再次 require
将会直接返回缓存的值。
请前往官方网站查看。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型