当前位置:   article > 正文

[星瞳科技]OpenMV是否属于单片机?

[星瞳科技]OpenMV是否属于单片机?

文件系统

MicroPyhon的文件系统是FatFS。

根目录

路径都是以根目录为起点。

当插入sd卡后,根目录就是SD卡;不插入sd卡,根目录就是内置的Flash。

如果需要,你可以在SD卡上,新建一个空文件:/flash/SKIPSD,这会避免挂载SD卡,当然,你可以使用os.mount来手动挂载SD卡。

绝对路径与相对路径

绝对路径是以根目录为起点的,相对路径是以当前目录为起点的。
比如:

image.save("/example.jpg")

中的"/example.jpg"就是绝对路径。会存放在根目录/下。
比如:

  1. image.save("./pic/example.jpg")
  2. image.save("pic/example.jpg")

这就是相对路径,表示当前路径下的pic文件夹下的example.jpg文件。

MicroPython的文件读写

Python学习(九)IO 编程 —— 文件读写 - feesland - 博客园

MicroPython的OS模块

在代码中,可以使用os库,来进行新建目录,新建文件之类的操作。

  • os.listdir([dir])
    如果没有参数,列出当前目录。如果给了参数,就列出参数所代表的目录。

  • os.chdir(path)
    改变当前目录

  • os.getcwd()
    获得当前目录

  • os.mkdir(path)
    新建一个新的目录

  • os.remove(path)
    删除文件

  • os.rmdir(path)
    删除目录

  • os.rename(old_path, new_path)
    重命名文件

  • os.stat(path)
    获得文件或者路径的状态

OpenMV的默认文件

默认情况下,OpenMV的磁盘有三个文件。

  • main.py
    上电自动运行这个文件的代码。

  • openmv.inf
    windows驱动文件。

  • README.txt
    可以简单看一下。

模块的使用

什么是模块?

随着代码的增多,在一个文件里的代码会越来越长,越来越难看懂。

为了编写可维护的代码,我们把很多函数分组,放到不同的文件里。在Python中,一个.py文件就称之为一个模块(Module)。

模块有什么好处?复用代码方便!如果我写了一个模块,你也写了一个模块,我们就有了两个模块。我们把这些模块都组织起来,大家就可以少写很多代码了!

如何使用模块?

  1. import machine
  2. red_led = machine.LED("LED_RED")
  3. red_led.on()

import machine就是引入machine这个模块。通过import语句,就可以引入模块。

还有from xxx import ooo 的语句,意思是通过xxx模块引入ooo类,或者通过xxx模块引入ooo函数。比如上面的程序可以写成:

  1. from machine import LED
  2. red_led = LED("LED_RED")
  3. red_led.on()

这就是通过machine的模块来引入LED类了。

如何添加自定义模块?

之前我们提到了,OpenMV是有文件系统的。

文件系统的根目录存在一个main.py,代码执行的当前目录就是根目录。

所以我们把模块的文件复制到OpenMV的“U盘”里就可以。如图:

这里的pid.py只是举一个举例。

我把pid.py复制到了U盘的根目录下。那么在程序中:

import pid

就可以引入pid模块了了。或者通过:

from pid import PID

这就是引入了PID类。

pyb各种外设

概览

作为一个单片机,控制IO口,IIC,SPI,CAN,PWM。定时器当然都是可以的。
而且,使用python语言,可以非常简单的调用它们,而不用考虑寄存器。

 

 

 

TablesOpenMV2 M4OpenMV3 M7OpenMV4 H7OpenMV4 H7 PlusOpenMV RT1062
Pin910101014
ADC11111
DAC11110
SPI11111
I2C12221
UART12221
Servo23324
CAN bus01111
电源按键00001
自定义按键00001
引脚耐受5V5V5V5V3.3V
引脚电平3.3V3.3V3.3V3.3V3.3V
ICSTM32F427STM32F765STM32H743STM32H743IMXRT1062
RAM256KB512KB1MB32MB + 1MB32MB + 1MB
Flash1MB2MB2MB32MB + 2MB16MB
频率180MHz216MHZ480MHZ480MHZ600MHZ
标配感光元件OV7725(30W像素)OV7725(30W像素)OV7725(30W像素)OV5640(500W像素)OV5640(500W像素)

注意:因为MicroPython可以在很多平台上运行。最开始在pyb模块,pyboard,是基于STM32的,但是后来又加入了esp8266和esp32,以及nrf系列,他们的架构和STM32不同。所以官方统一制定了machine模块,所以通用性更高一些,最终pyb会被淘汰。

OpenMV4 H7 Plus / OpenMV4 H7 / OpenMV3,主控为STM32,一般用pyb模块。

2024年最新款的OpenMV RT1062,主控为IMXRT1062,只支持machine模块,不支持pyb模块。请使用对应的machine代码哦~

常用的函数

  1. pyb.delay(50) # 延时 50 毫秒
  2. pyb.millis() # 获取从启动开始计时的毫秒数

LED

  1. from pyb import LED
  2. led = LED(1) # 红led
  3. led.toggle()
  4. led.on()#亮
  5. led.off()#灭

LED(1) -> 红LED
LED(2) -> 绿LED
LED(3) -> 蓝LED
LED(4) -> 红外LED,两个

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import LED
  2. import time
  3. red_led = LED("LED_RED")
  4. green_led = LED("LED_GREEN")
  5. blue_led = LED("LED_BLUE")
  6. blue_led.off()
  7. green_led.off()
  8. red_led.off()
  9. while(1):
  10. green_led.toggle()
  11. red_led.on()
  12. time.sleep_ms(250)
  13. red_led.off()
  14. time.sleep_ms(250)

IO

  1. from pyb import Pin
  2. p_out = Pin('P7', Pin.OUT_PP)#设置p_out为输出引脚
  3. p_out.high()#设置p_out引脚为高
  4. p_out.low()#设置p_out引脚为低
  5. p_in = Pin('P7', Pin.IN, Pin.PULL_UP)#设置p_in为输入引脚,并开启上拉电阻
  6. value = p_in.value() # get value, 0 or 1#读入p_in引脚的值

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import Pin
  2. p_out = Pin("P7", Pin.OUT)#设置p_out为输出引脚
  3. p_out.high()#设置p_out引脚为高
  4. p_out.low()#设置p_out引脚为低
  5. p_in = Pin("P8", Pin.IN, Pin.PULL_UP)#设置p_in为输入引脚,并开启上拉电阻
  6. value = p_in.value() # get value, 0 or 1#读入p_in引脚的值
Copy

Servo

视频教程34 - OpenMV控制三个舵机:OpenMV控制3个舵机 | 星瞳科技
  1. from pyb import Servo
  2. s1 = Servo(1) # servo on position 1 (P7)
  3. s1.angle(45) # move to 45 degrees
  4. s1.angle(-60, 1500) # move to -60 degrees in 1500ms
  5. s1.speed(50) # for continuous rotation servos
  • Servo(1) -> P7 (PD12)
  • Servo(2) -> P8 (PD13)

OpenMV3 M7 / OpenMV4 H7上增加:

  • Servo(3) -> P9 (PD14)

注意:OpenMV4 H7 Plus P9不能使用PWM

OpenMV RT1062 有P7 P8 P9 P10 四个PWM引脚。 在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. # 舵机控制例子
  2. #
  3. # 这个例子展示了如何使用OpenMV来控制舵机
  4. #
  5. # 伺服系统需要 50 Hz PWM,脉冲宽度为 1000us 至 2000us。
  6. import time
  7. from machine import PWM
  8. # P7 和 P8 可以共享相同的 PWM module,它们需要具有相同的频率。
  9. p7 = PWM("P7", freq=50, duty_ns=(2000 * 1000))
  10. p8 = PWM("P8", freq=50, duty_ns=(2000 * 1000))
  11. # P9 和 P10 可以共享相同的 PWM module,它们需要具有相同的频率。
  12. p9 = PWM("P9", freq=50, duty_ns=(2000 * 1000))
  13. p10 = PWM("P10", freq=50, duty_ns=(2000 * 1000))
  14. while True:
  15. for i in range(1000, 2000, 100):
  16. p7.duty_ns(i * 1000)
  17. p8.duty_ns(i * 1000)
  18. p9.duty_ns(i * 1000)
  19. p10.duty_ns(i * 1000)
  20. time.sleep_ms(1000)
  21. for i in range(2000, 1000, -100):
  22. p7.duty_ns(i * 1000)
  23. p8.duty_ns(i * 1000)
  24. p9.duty_ns(i * 1000)
  25. p10.duty_ns(i * 1000)
  26. time.sleep_ms(1000)

IO中断

  1. from pyb import Pin, ExtInt
  2. callback = lambda e: print("intr")
  3. ext = ExtInt(Pin('P7'), ExtInt.IRQ_RISING, Pin.PULL_NONE, callback)

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import Pin
  2. import time
  3. pin0 = Pin("P0", Pin.IN, Pin.PULL_UP)
  4. callback = lambda e: print("intr")
  5. pin0.irq(callback, Pin.IRQ_FALLING)
  6. while True:
  7. time.sleep(1)

定时器

  1. from pyb import Timer
  2. tim = Timer(4, freq=1000)
  3. tim.counter() # get counter value
  4. tim.freq(0.5) # 0.5 Hz
  5. tim.callback(lambda t: pyb.LED(1).toggle())

Timer 1 Channel 3 Negative -> P0
Timer 1 Channel 2 Negative -> P1
Timer 1 Channel 1 Negative -> P2
Timer 2 Channel 3 Positive -> P4
Timer 2 Channel 4 Positive -> P5
Timer 2 Channel 1 Positive -> P6
Timer 4 Channel 1 Negative -> P7
Timer 4 Channel 2 Negative -> P8

OpenMV M7上增加:
Timer 4 Channel 3 Positive -> P9

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import LED
  2. from machine import Timer
  3. blue_led = LED("LED_BLUE")
  4. # 当被调用时,我们将返回timer对象
  5. # 注意:在回调中不允许分配内存的函数
  6. def tick(timer):
  7. blue_led.toggle()
  8. # machine模块目前仅支持-1虚拟定时器。
  9. tim = Timer(-1, freq=1, callback=tick) # 创建一个定时器对象—以1Hz触发

PWM

  1. from pyb import Pin, Timer
  2. p = Pin('P7') # P7 has TIM4, CH1
  3. tim = Timer(4, freq=1000)
  4. ch = tim.channel(1, Timer.PWM, pin=p)
  5. ch.pulse_width_percent(50)

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import PWM
  2. import time
  3. p7 = PWM("P7", freq=100, duty_u16=32768)
  4. while True:
  5. for i in range(0, 65536, 256):
  6. p7.duty_u16(65535 - i)
  7. time.sleep_ms(10)
  8. p7.duty_u16(32768)

ADC

  1. from pyb import Pin, ADC
  2. adc = ADC('P6')
  3. adc.read() # read value, 0-4095

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import ADC
  2. adc = ADC('P6')
  3. adc.read_u16()

DAC

  1. from pyb import Pin, DAC
  2. dac = DAC('P6')
  3. dac.write(120) # output between 0 and 255

UART

  1. from pyb import UART
  2. uart = UART(3, 9600)
  3. uart.write('hello')
  4. uart.read(5) # read up to 5 bytes

UART 3 RX -> P5 (PB11)
UART 3 TX -> P4 (PB10)

OpenMV3 M7 / OpenMV4 H7/ OpenMV4 H7 Plus上增加:
UART 1 RX -> P0 (PB15)
UART 1 TX -> P1 (PB14)

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import UART
  2. uart = UART(1, 9600)
  3. uart.write('hello')
  4. uart.read(5) # read up to 5 bytes

OpenMV RT1062只有串口1,对应 P4 P5 引脚。 UART 1 RX -> P5 (PB11)
UART 1 TX -> P4 (PB10)

SPI

  1. from pyb import SPI
  2. spi = SPI(2, SPI.MASTER, baudrate=200000, polarity=1, phase=0)
  3. spi.send(b'hello')
  4. spi.recv(5) # receive 5 bytes on the bus
  5. spi.send_recv(b'hello') # send a receive 5 bytes

在 OpenMV RT 上不能用pyb模块,只能使用以下machine模块:

  1. from machine import SPI
  2. spi = SPI(1, baudrate=int(1000000000 / 66), polarity=0, phase=0)
  3. spi.write(b'hello')
  4. spi.read(5) # receive 5 bytes on the bus
  5. txdata = b"12345678"
  6. rxdata = bytearray(len(txdata))
  7. spi.write_readinto(txdata, rxdata) # Simultaneously write and read bytes.

I2C

  1. from machine import I2C, Pin
  2. i2c = I2C(sda=Pin('P5'),scl=Pin('P4'))
  3. i2c.scan()
  4. i2c.writeto(0x42, b'123') # write 3 bytes to slave with 7-bit address 42
  5. i2c.readfrom(0x42, 4) # read 4 bytes from slave with 7-bit address 42
  6. i2c.readfrom_mem(0x42, 8, 3) # read 3 bytes from memory of slave 42,
  7. # starting at memory-address 8 in the slave
  8. i2c.writeto_mem(0x42, 2, b'\x10') # write 1 byte to memory of slave 42
  9. # starting at address 2 in the slave

I2C 2 SCL (Serial Clock) -> P4 (PB10)
I2C 2 SDA (Serial Data) -> P5 (PB11)

OpenMV3 M7 / OpenMV4 H7 / OpenMV4 H7 Plus上增加:
I2C 4 SCL (Serial Clock) -> P7 (PD13)
I2C 4 SDA (Serial Data) -> P8 (PD12)

machine库是软件模拟的I2C协议,所以使用任何引脚都可以,但是还是推荐使用上面所说的引脚。

在 OpenMV RT 上可以这样调用:

  1. from machine import I2C, Pin
  2. i2c = I2C(1)
  3. i2c.scan()
  4. i2c.writeto(0x42, b'123') # write 3 bytes to slave with 7-bit address 42
  5. i2c.readfrom(0x42, 4) # read 4 bytes from slave with 7-bit address 42
  6. i2c.readfrom_mem(0x42, 8, 3) # read 3 bytes from memory of slave 42,
  7. # starting at memory-address 8 in the slave
  8. i2c.writeto_mem(0x42, 2, b'\x10') # write 1 byte to memory of slave 42
  9. # starting at address 2 in the slave

Switch Pin 自定义按键SW

  1. # OpenMV Cam 上的用户开关可通过“SW”引脚读取。
  2. # 该引脚通过 RC 电路在硬件中进行去抖。
  3. # 因此,您只需读取引脚状态即可了解开关是否被按下。
  4. import machine
  5. sw = machine.Pin("SW", machine.Pin.IN)
  6. r = machine.LED("LED_RED")
  7. while True:
  8. r.value(not sw.value())
  9. print(sw.value())

仅OpenMV RT具有SW自定义按键,OpenMV4 H7 / OpenMV4 H7 Plus / OpenMV3 M7 没有自定义按键。

字符串简介json/正则

介绍

在传统的单片机应用中,两个单片机串口通信,都是自己定义一些帧,包括帧头,数据帧,校验帧,帧尾。 图中 是飞控MavLink的协议。 

这种方式,稳定,高效。缺点也很明显:开发难度稍大,需要自己制定协议,编码解码需要手动编写。如果想快速尝试两个单片机通信的。我推荐使用串口传输json字符串!

优点:不需要了解底层的事情,比如:

  • 不考虑大端小端
  • 不考虑数据的byte转换
  • 支持任意长的int,float
  • 简单易懂,容易开发。

缺点:效率稍低。json的编码和解码会占用cpu。

其实传输json在网络编程中已经成为标准,比如在restful api中,前端和后端使用json来获取信息。只是在传统单片机的领域中不常见,一方面是效率稍低,嵌入式通常对成本的控制要求比较高。但是随着芯片成本的降低,很多应用对物料成本要求不是很高了,对开发效率越来越重视。

字符串

string = "hello string!"

OpenMV 是可以直接通过串口发送字符串的。

  1. from machine import UART
  2. uart = UART(1, 9600)
  3. string = "hello string!"
  4. uart.write(string)

字符串操作

Python3 字符串 | 菜鸟教程

举个例子:

  1. blobs=[12,23,11,22,33,44]
  2. print("%d", blobs[3])

JSON

JSON是一种简洁高效的交换数据的格式。 它可以是这种简单的:

"[[12,0],[10,12],[22,10],[99,11]]"

注:我通过这种简单的字符串,把OpenMV中的色块的x,y坐标发送出去。

也可以是这种复杂的:('''在python中表示多行字符串)

  1. '''
  2. {
  3. "number":10,
  4. "color" :[255,0,0],
  5. "rate" :0.65
  6. }
  7. '''

我使用这种结构把OpenMV采集到的颜色信息发送到wifi中的服务器中。

甚至于,可以像这样:

  1. '''
  2. {
  3. "firstName": "John",
  4. "lastName": "Smith",
  5. "sex": "male",
  6. "age": 25,
  7. "address":
  8. {
  9. "streetAddress": "21 2nd Street",
  10. "city": "New York",
  11. "state": "NY",
  12. "postalCode": "10021"
  13. },
  14. "phoneNumber":
  15. [
  16. {
  17. "type": "home",
  18. "number": "212 555-1234"
  19. },
  20. {
  21. "type": "fax",
  22. "number": "646 555-4567"
  23. }
  24. ]
  25. }
  26. '''

注意:json的形式和Python很像,但是json是javascript的对象表达形式,和python的表达形式稍有不同。

python生成json

OpenMV有json的模块,json.dumps(obj)和ujson.loads(str)可以很容的生成json字符串和解析json字符串。

  1. import json
  2. obj = [[12,0],[10,12],[22,10],[99,11]]
  3. print(json.dumps(obj))
  4. obj = {
  5. "number":10,
  6. "color" :[255,0,0],
  7. "rate" :0.65
  8. }
  9. print(json.dumps(obj))

会输出:

  1. '[[12, 0], [10, 12], [22, 10], [99, 11]]'
  2. '{"color": [255, 0, 0], "number": 10, "rate": 0.65}'

然后把字符串通过串口发送出去,然后在另一端,把json字符串解析成对象/数组。然后进行接下来的逻辑操作。

其他单片机的json模块

json很简单也很通用。

推荐阅读
相关标签
  

闽ICP备14008679号