關於MicroPython mpremote工具 的一些用例,閑聊

我嘗試了很多不同的第三方micropython工具,有些是Windows應用程式,有些是VScode插件。

但是當我嘗試過MicroPython的mpremote工具後,我幾乎決定它將成為我的首選工具。😄

我通常將其與VScode結合使用。它的程式碼突出顯示,自動完成和自動縮進非常有用。同時打開其他插件也很容易。另外VScode也是一個多平台的IDE,我比較習慣在幾個不同的作業系統里用同一個IDE,來回切換不會生手。

也許有些極簡主義者,我認為mpremote工具也會很合適,只需將系統的終端與任何文本編輯器一起使用即可,如果你是命令行老手,則只需要一個終端即可完成所有操作。

目錄 (Table of Contents)

鏈接

PyPI 頁面 在終端用pip install mpremote命令即可安裝。(推薦)

GitHub 頁面

MicroPython文檔頁面

本文在GitHub micropython/discussions/9096的頁面

1. cp

這可能是除 repl 之外最常見的命令,用於將文件從本地複製到設備,或從設備複製到本地。可能是因為我還不熟悉終端命令語法,起初我無法從MicroPython文檔中的幾個用例中完全掌握cp命令的用法,反覆運用和嘗試後就漸漸上手了。

1.1 在終端的當前路徑中複製文件

首先創建一個乾淨的臨時文件夾,並在其中寫入一個main.py文件。

print ("start")
for i in range(2):
    print(i)
print ("end")

最簡單的用例,在終端中輸入此文件夾路徑,將文件從本地複製到設備:

mpremote connect COM1 cp main.py : 

mpremote connect COM1 cp main.py :main.py

這兩個命令實現完全相同的功能。

:符號之後,如果輸入文件名,則文件在複製到設備時將重命名為此文件名。

將文件從設備複製到本地 :

mpremote connect COM1 cp :main.py .

mpremote connect COM1 cp :main.py main.py

這兩個命令實現完全相同的功能。

如果要重命名,可以刪除.符號並輸入所需的文件名。

1.2 複製絕對路徑中的文件

它有點複雜。

在 Windows 上,使用文件的絕對路徑從本地複製到設備:

mpremote connect COM1 cp D:\temp\main.py :main.py

將文件從設備複製到本地 :

mpremote connect COM1 cp :main.py D:\temp\main.py

目前在mpremote 0.3.0版本,應特別注意在Windows中不能省略目標文件名!
我在 GitHub 上已提交PR #9148 對 Windows 路徑名分隔符的支援,下一個版本應該就可以隨意在Windows里使用相對路徑和絕對路徑了,不影響其他功能。

在 Linux(如 Ubuntu)中,從絕對路徑複製文件可以省略目標文件名:

mpremote connect /dev/ttyACM0 cp ~/temp/main.py :

mpremote connect /dev/ttyACM0 cp /home/wind/temp/main.py :

mpremote connect /dev/ttyACM0 cp :main.py ~/temp/

mpremote connect /dev/ttyACM0 cp :main.py /home/wind/temp/

1.3 同時複製多個文件

在Linux中,例如Ubuntu,將多個文件從本地複製到具有絕對路徑的設備:

mpremote connect /dev/ttyACM0 cp ~/temp/main.py ~/temp/main2.py :

將多個文件從設備複製到本地絕對路徑:

mpremote connect /dev/ttyACM0 cp :main.py :main2.py ~/temp/

2. exec, run

這些命令用於控制遠程設備在不複製文件的情況下運行 Python 程式碼或腳本。

2.1 執行給定的 Python 程式碼

mpremote connect COM1 exec "print(1234)"

就像在REPL中輸入一行Python程式碼一樣。

2.2 從本地文件系統運行腳本

mpremote connect COM1 run test_1.py

就像在REPL中進入粘貼模式一樣,將程式碼複製並粘貼到指定的Python腳本中,然後運行它。

3. mount

我未曾想過有這種使用MicroPython設備的方法,請看以下用例並嘗試理解它,隨後你就會像我一樣對這個功能愛不釋手~~

3.1 在遠程設備上掛載本地目錄

首先創建一個乾淨的臨時目錄,並在其中寫入一些Python腳本,如下所示:

# numbers.py
num_1 = 21
num_2 = 22
num_3 = 23
num_4 = 24

# test_1.py
print("test_1 start")
import numbers
print(numbers.num_1)
print(numbers.num_2)
print(numbers.num_4)
print("test_1 end")

# test_2.py
print("test_2 start")
import numbers
temp1 = numbers.num_3 - numbers.num_2
print(temp1)
temp1 = numbers.num_3 - numbers.num_1
print(temp1)
print("test_2 end")

在終端中輸入此目錄的路徑。

我們先確認一些資訊,列出設備上的文件:

mpremote connect COM1 ls

ls :
         139 boot.py

進入 REPL 並再次確認:

mpremote connect COM1 repl
>>> uos.listdir()
['boot.py']
>>>

退出 REPL,掛載本地目錄,再次進入 repl:

mpremote connect COM1 mount . repl

再次確認文件:

>>> uos.listdir()
['numbers.py','test_1.py', 'test_2.py']

這裡沒有boot.py,但我們在本地目錄創建的Python腳本出現在列表中。

導入並運行兩個測試腳本:

>>> import test_1,test_2
test_1 start
21
22
24
test_1 end
test_2 start
1
2
test_2 end
>>>

查看一個文件:

>>> f=open("numbers.py")
>>> print(f.read())
# numbers.py
num_1 = 21
num_2 = 22
num_3 = 23
num_4 = 24

>>>

驚訝之餘,你可能想知道,這些python腳本文件是不是全部都上傳到設備上並存儲起來了?我最初也是這麼猜測的。

現在,我們將終端保留在REPL中,在本地修改此文件:

# numbers.py
num_1 = 1
num_2 = 12
num_3 = 23
num_4 = 35

返回 REPL 並再次檢查:

>>> f=open("numbers.py")
>>> print(f.read())
# numbers.py
num_1 = 1
num_2 = 12
num_3 = 23
num_4 = 35

>>>

這樣就解除疑惑了,文件只保存在本地目錄中,並且這個目錄被掛載在設備上。

軟體重置後,並將重新掛載目錄。

這就像是一個移動硬碟,或者是說像是NAS,雲盤,連在MicroPython設備上,顯然這個功能能極大節約設備的flash壽命,通常只需要在必須離線運行的時候再把python腳本文件拷貝到flash里即可。

推薦使用以下組合命令執行python腳本:

mpremote connect COM1 mount . exec "import test_1"

3.2 在掛載了本地目錄後繼續使用原flash中的腳本

在REPL中使用uos.listdir("/")命令你將看到原來存儲在flash中的文件:

>>> uos.listdir("/")
['remote', 'boot.py', 'main.py']

如果你想保持掛載本地目錄的狀態下使用flash中的腳本(例如main.py),你可以使用如下命令將原flash根目錄路徑添加進sys.path列表中:

>>> import sys
>>> sys.path
['', '.frozen', '/lib']
>>> sys.path.append("/")
>>> sys.path
['', '.frozen', '/lib', '/']
>>> import main

如果掛載的本地目錄中已有main.py,則僅會運行本地目錄的main.py,可通過reverse()調換列表順序:

>>> sys.path
['', '.frozen', '/lib', '/']
>>> sys.path.reverse()
>>> sys.path
['/', '/lib', '.frozen', '']
>>> import main

現在就會優先運行flash中的腳本。

3.3 加快測試速度的一種方法

如果我們需要對一個腳本一遍測試一遍修改,而腳本中已經導入了很多存儲在本地的腳本模組,這樣的情況下,每一次掛載測試都將花費數秒甚至數十秒的時間。

我總結了一種方法,在REPL中設法不重複的import模組即可有效減少運行時間。

以測試SSD1306 OLED顯示器為例,main.py是主程式,ssd1306.py是驅動模組,此處就不再完整列舉程式程式碼了。

通過time.tick_ms()來驗證測試本地目錄的main.py腳本所需的時間,可見大概需要6秒:

>>> import time;t1 = time.ticks_ms();import main;time.ticks_diff(time.ticks_ms(),t1)
6032

使用sys.modules可以查看當前已經導入的腳本模組,可見ssd1306.py已經導入:

>>> import sys;sys.modules
{'main': <module 'main' from 'main.py'>, 'ssd1306': <module 'ssd1306' from 'ssd1306.py'>, 'flashbdev': <module 'flashbdev' from 'flashbdev.py'>}

我們僅需移除main而保留其他的模組:

>>> del main;sys.modules.pop('main')
<module 'main' from 'main.py'>
>>> import sys;sys.modules
{'ssd1306': <module 'ssd1306' from 'ssd1306.py'>, 'flashbdev': <module 'flashbdev' from 'flashbdev.py'>}

再次測試:

>>> import time;t1 = time.ticks_ms();import main;time.ticks_diff(time.ticks_ms(),t1)
1612

得到明顯改善。