跳到主要内容

MicroPython编程

最后更新于2020-9-15
更新摘要


『喵比特存在2种模式,分别为Arcade游戏编程模式和MicroPython模式,两者不相通
接下来跟着步骤操作,完成进入Micropython模式的前置步骤吧👇』

01 进入Micropython模式

下载最新固件

📥 先下载最新固件:meowbit.uf2.zip

危险

如果你还没使用过MicroPython模式,请仔细根据以下步骤操作

操作流程

❶ 进入固件烧录界面    
将喵比特插上USB,按如下步骤操作

完成这一步后,可以看到💻中出现了 ARCADE-F4盘符 即可开始继续下面步骤

❷ 烧录固件
将下载得到的meowbit.zip解压得到meowbit.uf2,这便是固件文件。固件的烧录也很简单,只需要将.uf2文件往ARCADE-F4盘符里一拖(就像拷U盘文件那样轻松),等待完成即可
image.png

❸ 成功进入Micropython模式的现象
屏幕变成喵喵Logo,并且💻中ARCADE-F4盘符转变为 PYBFLASH 盘符
meowbit2.jpg

❹ 编写你的第一个程序
用文本编辑器打开PYBFLASH盘符中的main.py文件(这里推荐Vscode),将下列代码复制到喵比特的main.py文件内,保存并按下喵比特RESET按键复位一次

from meowbit import *
screen.text('hello world')

此时你可以看到屏幕左上角出现了hello world字样😃,开启你的编程之旅吧!

危险

当程序中完全没有涉及到屏幕相关的程序段,喵比特则会一直保持喵喵Logo图案


02 Micropython API

『进入了Micropython的世界,这一节将为你提供丰富的接口,帮助你用喵比特做更多的事情』

导入meowbit库

只有导入了meowbit库,才能使用喵比特完整的功能API噢😶

 # Micropython中的导包缩写形式,可以少些一些代码
from meowbit import *
screen.text('hello world')

按键

喵比特上有6个可编程按键,布局贴合游戏机

sensor.btnValue(btn)
返回按键状态值,数字信号。参数:

  • btn: 取值 'a'、'b'、'up'、'down'、'left'、'right',分别代表6个按键

sensor.btnTrig[btn] = fn
按键的中断事件,可以给按键按下绑定一个执行函数。参数:

  • fn:中断时要执行的函数

    危险

    这个自定义中断函数内不要做

  • 延时太长或执行内容太多的工作

  • 带有内存分配的操作,比如新建一个变量 :::

示例程序📋:以下包含2个程序示例,请自行区分

# 按键A控制LED1开关
from meowbit import *

while 1:
if(sensor.btnValue('a')):
led1.on()
else:
led1.off()



# 按键A的中断事件控制LED1亮灭
from meowbit import *
import time

def fn():
led1.toggle()
time.sleep_ms(500) # delay(ms)/消除机械抖动

sensor.btnTrig['a'] = fn
sensor.startSchedule() # 不管开了几个中断线程,这条只需一次

LED

喵比特右上角有2颗LED,分别是绿色led1和红色led2

led1.on() / led1.off()
开关控制

led1.toggle()
状态切换,根据当前该灯的状态去另一个状态

led1.intensity(brightness)
更改LED灯的亮度

  • brightness:0~255(暗~亮,默认255,建议50)

示例程序📋:以下包含3个程序示例,请自行区分

# 开关_开机绿灯闪烁5次
from meowbit import *
from time import sleep

for i in range(5):
led1.on()
sleep(1)
led1.off()
sleep(1)

# 状态切换_开机红灯闪烁5次
from meowbit import *
from time import sleep

for i in range(5): # 红色灯不太明显,可能需要拨开套子看
led2.toggle()
sleep(1)

# 状态切换_从暗到亮再到灭
from meowbit import *
import time

for i in range(256):
led1.intensity(i)
time.sleep_ms(10)
for i in range(255, 0-1):
led1.intensity(i)
time.sleep_ms(10)

蜂鸣器

无源蜂鸣器是采用定时器模拟PWM驱动发声

buzzer.tone(freq, d = 0.5)
频率对应音调表

  • freq:频率,对应音调
  • d:持续时间(单位秒),默认为0.5s,当d=-1时,设置为持续发声

buzzer.note(note, rest = 0.5)

  • note:0~130共12个八度,12的整处倍数为C调
  • rest:持续时间(单位秒),默认为0.5s

buzzer.rest(rest)
静音一定时间

  • rest:持续时间(单位秒)

buzzer.melody(m, bpm = 120)
播放一段旋律

  • bpm:拍速,默认为120,即120拍/分钟
  • m:m=octave:duration=音符+八度音阶[默认为4]:滴答音的次数[默认4],规定duration = 4为1个四分音符,并且滴答音单位时长是由bpm决定的,可为任意时长
    • 当c4:4在bpm为默认情况下,效果为响1拍(即0.5s)
    • 当c4:8在bpm为默认情况下,效果为c4:4时长的2倍
    • 改变bpm为60,c4:4的时长变为1s
  • 固件内保留了以下3个简单音效 | 名字 | 内容 | | --- | --- | | CORRECT | "c6:1 f6:2" | | NOTICE | "d5:1 b4:1" | | ERROR | "a3:2 r a3:2" |

buzzer.stop()
蜂鸣器停止播放,可以放置于按键中断里强行中断播放旋律,也可以和持续播放旋律配合使用制作按下发声抬起收声的效果

示例程序📋:以下包含2个程序示例,请自行区分

# 展示所有蜂鸣器函数效果,按键A能中断播放
from meowbit import *

def stopBuzzer():
buzzer.stop()

sensor.btnTrig['a'] = stopBuzzer # 绑定中断函数
sensor.startSchedule() # 打开中断线程

buzzer.tone(262, 1)
buzzer.rest(1)
buzzer.note(60, 1)
buzzer.rest(1)
buzzer.melody("d r d4:4")
buzzer.rest(1)
buzzer.melody(CORRECT) # 当播放这段旋律的时候,按下案件A,执行停止蜂鸣器操作,声音停止


# 按键A按下蜂鸣器响起,松开蜂鸣器收声
from meowbit import *

while 1:
if sensor.btnValue('a'):
buzzer.tone(240, -1)
else:
buzzer.stop()

温度传感器

sensor.getTemp()
获取温度数值,单位是摄氏度

示例程序📋:

from meowbit import *

screen.sync = 0 # 0为关闭同步刷新,默认为1(打开)则每次screen单条函数都会调用一次tft.show(fb),会造成闪屏
while 1:
screen.fill(1)
tempValue = sensor.getTemp()
screen.text('Temperature:' + str(tempValue), 20, 50)
screen.refresh()

光线传感器

sensor.getLight()
亮度传感器检测环境明暗程度,返回值为模拟量0~4096,随着光线越强数值越大

示例程序📋:

from meowbit import *

screen.sync = 0 # 0为关闭同步刷新,默认为1(打开)则每次screen单条函数都会调用一次tft.show(fb),会造成闪屏

while 1:
screen.fill(0)
lightValue = sensor.getLight()
screen.text('brightness' + str(lightValue), 20, 50)
screen.refresh()

陀螺仪

sensor.acc轴()
返回x,y,z三轴各自当加速度值,单位为g(m/s2)。参数:

  • 轴:X、Y、Z 需要大写

sensor.gyro轴()
返回x,y,z三轴各自的轴转向加速度,单位为g(角度/s)。参数:

  • 轴:X、Y、Z 需要大写
危险

加速度轴和转向加速的方向如下图所示,箭头所指的方向为对应轴速度的正方向(屏幕朝向的方式
1589787844164-9ad40ac8-aab0-4c0e-9f15-bc070e22ee84.png

sensor.roll()
横滚,返回单位为角度,如图所示

sensor.pitch()
旋转,返回单位为角度,如图所示

sensor.gesture(ges)
姿态,返回值为布尔类型。参数:

  • ges:'shake' 摇晃、'freefall' 自由落体、'tilt_up' 后倾、'tilt_down' 前倾、'tilt_left' 左倾、'tilt_right' 右倾、'face_up' 朝上、'face_down' 朝下
    危险

    倾斜和朝向的参考物为手持正对喵比特时的屏幕

sensor.gesTrig[ges] = fn
姿态中断事件,档设定的姿态达到时会出发自定义的中断函数。参数:

  • ges:'shake' 摇晃、'freefall' 自由落体、'tilt_up' 后倾、'tilt_down' 前倾、'tilt_left' 左倾、'tilt_right' 右倾、'face_up' 朝上、'face_down' 朝下

    危险

    需要注意的是这里参数是使用 [ ]包裹

  • fn:自定义函数

    危险

    自定义函数的定义需要注意:

    • 这个函数内容执行应尽量短并且耗时短
    • 函数不允许有任何的内存申请,如:a = i+1
    • 如需要使用全局变量,除了提前定义一个全局变量外,函数内还需要用global修饰

示例程序📋:

# 测试所有相关返回值,打印到屏幕上
from meowbit import *

screen.sync = 0

while 1:
screen.fill(0) #清屏操作

screen.textCh('轴加速度:x/y/z', 20, 10, 1, (168, 233, 74))
screen.text(round(sensor.accX(), 2), 10, 30)
screen.text(round(sensor.accY(), 2), 60, 30)
screen.text(round(sensor.accZ(), 2), 110, 30)

screen.textCh('转向加速度:x/y/z', 10, 50, 1, (74, 233, 168))
screen.text(round(sensor.gyroX(), 2), 10, 70)
screen.text(round(sensor.gyroY(), 2), 60, 70)
screen.text(round(sensor.gyroZ(), 2), 110, 70)

screen.textCh('横滚:' + str(round(sensor.roll())), 20, 90, 1,(233, 74, 168))
screen.textCh('旋转:' + str(round(sensor.pitch())), 20, 110, 1, (233, 168, 74))

screen.textCh('屏幕朝上', 100, 95, 1, (74, 168, 233))
screen.text(sensor.gesture('face_up'), 105, 110)

screen.refresh()

屏幕显示

screen.refresh()
屏幕刷新显示,档屏幕屏幕的同步刷新关闭时需要用到

screen.sync = val
设置同步刷新 。参数:

  • val: 1 开启、 0 关闭,默认为开启状态

screen.fill(color)
屏幕填充,填充方式可以时RGB数值或者明度,参数:

  • color:
    • (R,G,B):数值区间为0~255
    • 明度:数值区间为0~255,常用screen.fill(0)来清屏
危险

坐标点(x, y)对应屏幕尺寸160x128如图所示 👀
资源 1.png

危险

🔎 以下使用color参数的地方均可使用

  • RGB色值 :(R, G, B)
  • 明度值:0~255

screen.pixel(x, y, color=255)
绘制像素点。参数:
color:R红色,G绿色,B蓝色,数值范围0~255,为标准RGB色彩数值。默认不填即为白色,明度=255

screen.line(x1, y1, x2, y2, color=255)
以坐标(x1, y1)和(x2, y2)为顶点绘制线段绘制线条

screen.rect(x, y, weight, height, color=255, fill=0)
🟥 以坐标(x, y)为矩形左上角顶点,绘制weight宽度和height高度的矩形。参数:

  • fill:填充功能
    • 0:不填充
    • 1:填充
    • 默认不填为0

screen.triangle(x1, y1, x2, y2, x3, y3, color=255, fill=0)
🔺 以坐标(x1, y1)、(x2, y2)和(x3, y3)为顶点绘制三角形

screen.circle(x, y, r, color=(R, G, B), fill=0)
🔴 以坐标(x, y)为圆形绘制半径为r的圆形

screen.polygon(x, y, sides=3, r=10, th=3, rot=0, color=255, fill=0)
🔷 以坐标(x, y)为中心点,绘制变数为多边形。参数:

  • sides,n:多边形边数,默认为3
  • r:中心点到顶点到距离,默认10
  • th:边框到厚度,默认3
  • rot:旋转角度(正数为逆时针转),默认0

screen.text(text, x=0, y=0, ext=1, color=255)
在屏幕上显示非中文字符(比如数字和字母)。参数:

  • 坐标为第一个字符左上角,不填默认为(0, 0)
  • ext:英文字符字号,默认为1号——8x8像素。字号增大的规律为8*ext

screen.textCh(text, x=0, y=0, ext=1, color=255)
在屏幕上显示中文的字符(也包含英文及数字,但显示非中文字符的视觉上不如用screen.text( ))。参数:

  • 坐标为第一个字符左上角,不填默认为(0, 0)
  • ext:中文字符字号,默认为1号——12x12像素。字号增大的规律为12*ext

screen.loadBmp(path, x=0, y=0)
在屏幕上显示一张bmp格式的图片,仅支持24/32位的bmp。参数:
path:bmp的相对位置,一般直接将图片放在PYBFLASH盘符和main.py同目录,此时path='name.bmp'
坐标:不填默认图片左上角(0, 0)

screen.loadgif(path, x = 0, y = 0)
显示.gif格式动图,建议用 SD卡 时使用,毕竟动图比较大,喵比特的Flash只有2M

危险
  • 注意图片的尺寸为160x128噢,如果大于或小于则会在屏幕中显示达不到预期效果
  • 初次将图片扔到meowbit的PYBFLASH盘符内需要软复位或者按一次复位按键才能识别得到

📥 测试图片资源bmp_test.zip

# 显示bmp
from meowbit import *
screen.loadBmp('haimian.bmp')

# 显示gif
from meowbit import *
screen.loadgif('haimian.gif')

引脚控制

p1 = MeowPin(pin, mode)
实例化引脚,设置某个引脚位特定模式。参数:

  • pin:字符串类型,如'P1'
  • mode:
    • IN:数字输入,默认已上拉
    • OUT:数字输出
    • ANALOG:模拟输入
    • PWM:模拟输出

getDigital()
设置为数字输入模式(mode = IN)时可用,返回值为高低电平0 / 1

getAnalog()
设置为模拟输入模式(mode = ANALOG)时可用,由于时12位ADC,所以返回值为0~4095

setDigital(val)
设置为数字输出模式(mode = OUT)时可用,输出引脚高低电平0V / 3.3V。参数:

  • val
    • 0:电压0V
    • 1:电压3.3V

setAnalog(val)
设置为模拟输出模式(mode =PWM)时可用,输出0~1023,将0~3.3V分解成1024份的区间电压。参数:

  • val
    • 0:电压0v
    • 1023:电压3.3V(对地)

set_pulse_width(duty)
设置为模拟输出模式(mode =PWM)时可用,输出PWM占空比,一般作用于舵机控制,通过计算得到一个周期内的占空比,精确控制角度。参数:

  • duty:比如500~2500us脉宽的9g普通舵机的0°~180°范围,在喵比特默认的20ms周期中,占空比为2.5%~12.5%

irq(trigger=ExtInt.IRQ_FALLING, handler=None, pull=Pin.PULL_UP)
引脚的外部中断,可设置中断函数,档中断条件触发后执行。参数:

  • trigger:触发条件
    • ExtInt.IRQ_FALLING    下降沿触发(默认)
    • ExtInt.IRQ_RISING    上升沿触发
    • ExtInt.IRQ_RISING_FALLING    上升沿和下降沿都触发
  • handler:中断触发后跳入执行的函数,需要自定义
  • pull:
    • Pin.PULL_UP    开启该引脚上拉(默认,且常用)
    • PULL_DOWN    开启该引脚下拉
    • PULL_NONE    不开启该引脚的上拉和下拉(少用)

应用SD卡

Meowbit使用SD必须在MicroPython模式下
该模式下接通USB后喵比特会自检,看是否有SD卡,若没有则将文件系统设置为内部Flash,为检测到匹配到SD卡则将文件系统设置为该SD卡,并且可见原本应该出现的PYBFLASH盘符变为SD卡的盘符

  1. SD卡的选型要求

    • 由于SPI总线速率比较高,所以一般的普通SD卡没法适配,需要高速卡。
      (比如一些4G以上的C10高速卡才能适配,但也并不是所有高速卡都适合,同一个品牌的不同的规格卡可能有不同的结果,测试通过的是OV 16G的C10 MicroSD卡
    • 大卡和小卡均可用,但小Micro SD卡需要一个大卡套转接使用
  2. 将卡插在喵比特上,然后 再给喵比特上电(请勿热拔插)

这是我的SD卡名字
image.png

  1. 开始编程

首先要明确,喵比特如果没有什么特殊的设置,上电即跑main.py。由此可知,我们只需要在SD盘符内存放一个main.py程序即可。(当为检测到SD卡,喵比特的PYBFLASH盘符实际用的是内部Flash仅2M,插了外部Flash后则扩展了空间,能放更多东西

◆按照如下步骤进行测试吧:

a. 首先在盘符内新建一个main.py文件(注意.py是文件后缀)
image.png

b. 用文本编辑器(建议Vscode)打开main.py,写一段让喵比特显示一排欢迎字符的程序,并保存

from meowbit import *

screen.textCh('欢迎使用喵比特', ((160/2)-(12*7/2)), (128/2-12/2), 1, (168,33,168))
# 第2和3个参数是做了一个字符居中的处理,由屏幕尺寸160x128px,一个汉字字号1尺寸为12px得出

c. 程序保存后,按一下喵比特右侧的RESET(复位按键),让喵比特重新重置,并重新检测一轮文件系统,这样做才能让你新修改的程序运行
meowSD3.jpg

d. 一起来验收一下程序结果吧
meowSD34jpg.jpg

文件系统操作

MicroPython支持标准的Python的文件模块,即可使用如open()这类原生函数

  1. 基本的对文件操作

a. 创建1个文件
将下面的代码覆盖到main.py文件内并保存,注意此时我们需要2次复位操作,第一次复位为了让main.py运行,而main.py运行完的结果是创建了一个名为'myFile'的txt文本并且填入hello world!的内容,但是由于喵比特只有在复位(无论是软复位还是硬件复位)的一开始才会检测一次文件系统更改,而后如果有任何改变只有在下一次复位才能刷新,所以第二次复位操作就是为了查看文件是否创建成功

"""
在当前路径下创建名为myFile的txt文件
'w'为只写模式,既如果不存在该名称文件便创建,若存在则覆盖。想要不覆盖的只写,可选模式为'a'
模式不填的话默认为r,即只读
"""
f = open('myFile.txt', 'w')
f.write('hello world!')
f.close() # close()相当于关闭文件并保存文件,如果没有close(),写入的内容可能会存在缓冲区中,相当于你的操作就是失败的

不出意外,我们可以看到盘符内结果如下
image.png

b. 查看文件内容
将下面的代码复制替换掉main.py的内容,保存文件并复位喵比特

from meowbit import *

f = open('myFile.txt') # 默认不填模式为'r' (只读
readStr = f.read()
f.close()

screen.text(readStr, 20, 20)

可以看到屏幕上显示的字符正是我们myFile.txt里的内容
meowSD5jpg.jpg

c. 更高级的文件/目录处理模块——os
基本的目录操作API

import os
os.getcwd() # 查看当前所在目录
os.listdir() # 查看当前目录内的所有文件
os.mkdir('dir') # dir为你想创建的目录名
os.chdir('dir') # dir为当前目录的相对目录,必须要存在的。若os.chdir('..')则表示退回上级目录
os.remove('xx') # xx为当前目录内存在的文件,需要带后缀格式如.txt
os.rmdir('dir') # 可删除一个空目录,若非空则会抛出异常

进阶用法——删除非空目录

import os

def delDir(name):
os.chdir(name)
for i in os.listdir():
os.remove(i)
os.chdir('..')
os.rmdir(name)
os.sync()

更新摘要

2020-9-15

  • 更新bmp和gif图的使用方法及提供素材图片

2020-8-7

  • 新增喵比特进入Micropython模式的指南
  • 新增Micropython API
  • 新增Micropython使用SD卡的教程
  • 新增文件系统操作的Python方法