- 2025-01-20
-
回复了主题帖:
proteus 仿真 ws2812 效果
赞赞赞。另外问一下,gif图咋做的?
- 2024-12-26
-
回复了主题帖:
【Follow me第二季第4期】任务一:极简环境+快速烧录+花样点灯+结果输出+小知识
HonestQiao 发表于 2024-12-25 14:40
我就是用最新的arduino ide升级了下固件
谢谢大佬回复,我已经自己解决了,解决的过程我会写到自己的帖子里,太难了
- 2024-12-23
-
发表了主题帖:
【Follow me第二季第4期】任务提交+遇到的问题及经验分享+心得体会 | Micropython
本帖最后由 怀66 于 2025-1-10 21:17 编辑
前言:
真的真的很荣幸能参加这次活动,首先感谢eeworld平台及平台里无私分享的大伙们。由于之前参加过一次followme,https://bbs.eeworld.com.cn/thread-1260076-1-1.html,用的circuitpython开发adafruit家的esp32,很方便,所以本次开发也选择了micropython作为开发,两者的区别不是很大,感兴趣可自行百度。
非常遗憾的是,由于本人拿到板子后的这段时间一直很忙,另外我身边也没有其余的电子器件(焊枪,面包板,杜邦线,usb2ttl啥的),所以本次所有必做任务就只完成了基础要求,感觉愧对于平台给我的机会。当然虽然只是完成了最基本的内容,但是本人在开发过程中,依旧遇到了很多小问题,我就在此帖也写上遇到的问题及解决办法,希望能帮助遇上同样问题的小伙伴吧!
环境搭建:
首先要使用micropython开发必须将板子刷上mpy固件,固件可以在很多地方找到,如arduino nano rp2040官网的指引手册,micropython的官网,还有就是使用openmv idle操作,当然我也会在帖子下附上固件。刷固件步骤,①板子上电连上电脑usb,可以看到闪灯程序自动运行;②快速连续按两下reset按键,等待电脑弹出一个u盘,如果电脑没有反应,两次按下按键的间隔可以长一点或者短一点,多试两次就可以了;③将固件.uf2文件复制到u盘里就可以了,然后按reset重启板子。(另外如果有跳线帽,也可以尝试先短接RFU和地后,一直按reset按键不松手,再上电,然后刷上uf2固件,官网也有流程,一般用前面的方法就行,我写在这里就是来凑字数的)。
关于micropython的介绍我就不多赘述了,可以自己百度看看,也可以看01studio家的介绍,我一开始就是跟他家学的。micropython最方便的地方莫过于有一个repl实时交互解释器用作调试程序,很方便,但是注意这个repl是占用了一个串口的(我后面遇到的一个问题就和他有关),python语法也很友好,所以开发起来是不那么费脑子的,当然这也离不开前辈们写好的各种库,在这里再次感谢各位大佬提供的轮子,让我这条细狗也能跑起来哈哈哈。以下为任务提交。
使用物料:本贴只使用了开发板和一根microusb数据线
汇总视频:
[localvideo]c8552d7400b515cb4f6649e55a1e6d68[/localvideo]
①任务一:搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!
说实话这个点灯任务我就遇到了大难题,因为我一开始看原理图没找到rgb灯连在单片机那个引脚,他这个原理图很搞笑的地方是,明明rgb是先通过nina模块再连到rp2040上的,但是他却把彩灯画在rp2040旁边,误导了我。
在别的帖子的提醒下,我最终完成了任务。由于repl就是占用了串口,所以micropython的print函数就是将信息传输在串口上,我是用thonny作开发软件,底下那栏就是串口输出,当然你也可以用putty等软件查看哈或者官方推荐的openmv idle。
软件流程示意图:
from machine import Pin
import time
print(dir(Pin.board)) #打印引脚
led = Pin("LED", Pin.OUT)
blue = Pin("LED_BLUE", Pin.OUT)
green = Pin("LED_GREEN", Pin.OUT)
red = Pin("LED_RED", Pin.OUT)
led_list = [blue, green, red]
led.value(0)
while True:
#三个彩灯轮流亮,小灯亮灭是交替的
for i in led_list:
status = False
i.value(status)
status = not status
time.sleep(0.5) #亮0.5s
led.value(status)
i.value(status)
time.sleep(0.5) #灭0.5s
led.value(not status)
print('Hello DigiKey & EEWorld!')
其中print(dir(Pin.board)) #打印引脚 是可以查看固件定义好的引脚参数信息,输出信息如下:
['__class__', '__name__', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'D10', 'D11', 'D12', 'D13', 'D14', 'D15', 'D16', 'D17', 'D18', 'D19', 'D2', 'D20', 'D21', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'LED', 'LEDB', 'LEDG', 'LEDR', 'LED_BLUE', 'LED_BUILTIN', 'LED_GREEN', 'LED_RED', 'RX', 'SCL', 'SDA', 'TX', '__bases__', '__dict__']
可以看到,我们需要的LED,LEDB,LEDR,LEDG等等,十分友好方便我们使用。视频如下:
[localvideo]c7ec384943d304e0d340dbc19f855994[/localvideo]
任务二:学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据;
任务2是使用一个imu传感器,我上次followme也使用过类似的传感器,感兴趣可以去看https://bbs.eeworld.com.cn/thread-1255882-1-1.html。
然后读取六轴原始数据代码如下:(官方示例就有)
import time
from lsm6dsox import LSM6DSOX
from machine import Pin, I2C
# Initialize the LSM6DSOX sensor with I2C interface
lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
while True:
# Read accelerometer values
accel_values = lsm.accel()
print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*accel_values))
# Read gyroscope values
gyro_values = lsm.gyro()
print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*gyro_values))
print("")
time.sleep_ms(100)
由于上一次的followme,我就学习了实现姿态解算,所以这次我依旧也移植了代码。
rp2040负责读取6轴原始数据,然后根据姿态解算函数,解算出姿态角度,通过网络将角度信息发送到电脑服务端,电脑服务端收到信息后,通过虚拟串口软件,将信息通过虚拟串口送到上位机。
这么麻烦是因为,我用的上位机软件是别人编写好的,可以去我上次followme的帖子看,它只能接受串口数据,但是,由于我身边没有焊枪,没焊接排针,更没有usbtottl,就不能使用单片机的物理串口直接与上位机软件通信了。所以我就曲线救国,先通过网络,将信息传给电脑服务端,在用电脑的虚拟串口实现与上位机软件通信。电脑的服务端程序也是我自己编写的。
rp2040代码如下:
import time
from lsm6dsox import LSM6DSOX
from machine import Pin, I2C
from zitai_slove import Update_IMU
from q4 import IMUupdate
from One_filter import one_filter
import network,time
import socket
#WIFI连接函数
def WIFI_Connect():
wlan = network.WLAN(network.STA_IF) #STA模式
wlan.active(True) #激活接口
start_time=time.time() #记录时间做超时判断
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('HuaiYe', 'huaiyeshuai') #输入WIFI账号密码
while not wlan.isconnected():
#超时判断,30秒没连接成功判定为超时
if time.time()-start_time > 30 :
print('WIFI Connected Timeout!')
break
#串口打印信息
print('连接好了wifi')
print('network information:', wlan.ifconfig())
WIFI_Connect()
s = socket.socket()
addr=('192.168.137.1',9999)
s.connect(addr)
# Initialize the LSM6DSOX sensor with I2C interface
lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
# def getdata():
# accel_values = lsm.accel()
# gyro_values = lsm.gyro()
# return accel_values+gyro_values
#
# acc_gyro = getdata()
while True:
acc_x, acc_y, acc_z = [value for value in lsm.accel()]
gyro_x, gyro_y, gyro_z = [value for value in lsm.gyro()]
zitai = Update_IMU(acc_x, acc_y, acc_z, gyro_x, gyro_y, gyro_z)
# zitai = IMUupdate(acc_x, acc_y, acc_z, gyro_x, gyro_y, gyro_z) #q4
# zitai = one_filter(acc_x, acc_y, acc_z, gyro_x, gyro_y, gyro_z) #one_filter
# print(zitai)
s.send(f'pitch:{zitai[0]}, roll:{zitai[1]}, yaw:{zitai[2]}')
# zitai = bytearray(f'pitch:{zitai[0]}, roll:{zitai[1]}, yaw:{zitai[2]}') #pitch:, roll:, yaw:
time.sleep(0.01)
姿态解算代码其一如下:(我会在文末一并上传)
#coding:utf-8
import math
#IMU算法更新
Kp = 100 #比例增益控制加速度计/磁强计的收敛速度
Ki = 0.002 #积分增益控制陀螺偏差的收敛速度
halfT = 0.001 #采样周期的一半
#传感器框架相对于辅助框架的四元数(初始化四元数的值)
q0 = 1
q1 = 0
q2 = 0
q3 = 0
#由Ki缩放的积分误差项(初始化)
exInt = 0
eyInt = 0
ezInt = 0
def Update_IMU(ax,ay,az,gx,gy,gz):
global q0
global q1
global q2
global q3
global exInt
global eyInt
global ezInt
# print(q0)
#测量正常化
norm = math.sqrt(ax*ax+ay*ay+az*az)
#单元化
ax = ax/norm
ay = ay/norm
az = az/norm
#估计方向的重力
vx = 2*(q1*q3 - q0*q2)
vy = 2*(q0*q1 + q2*q3)
vz = q0*q0 - q1*q1 - q2*q2 + q3*q3
#错误的领域和方向传感器测量参考方向之间的交叉乘积的总和
ex = (ay*vz - az*vy)
ey = (az*vx - ax*vz)
ez = (ax*vy - ay*vx)
#积分误差比例积分增益
exInt += ex*Ki
eyInt += ey*Ki
ezInt += ez*Ki
#调整后的陀螺仪测量
gx += Kp*ex + exInt
gy += Kp*ey + eyInt
gz += Kp*ez + ezInt
#整合四元数
q0 += (-q1*gx - q2*gy - q3*gz)*halfT
q1 += (q0*gx + q2*gz - q3*gy)*halfT
q2 += (q0*gy - q1*gz + q3*gx)*halfT
q3 += (q0*gz + q1*gy - q2*gx)*halfT
#正常化四元数
norm = math.sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3)
q0 /= norm
q1 /= norm
q2 /= norm
q3 /= norm
#获取欧拉角 pitch、roll、yaw
pitch = math.asin(-2*q1*q3+2*q0*q2)*57.3
roll = math.atan2(2*q2*q3+2*q0*q1,-2*q1*q1-2*q2*q2+1)*57.3
yaw = math.atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3)*57.3
return pitch,roll,yaw
电脑服务端代码如下:
import socket
import serial
import sys
import time
#创建串口
ser = serial.Serial()
ser.port = 'COM1'
ser.baudrate = 115200
ser.open()
# 创建 socket 对象
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
port = 9999
# 绑定端口号
serversocket.bind(('192.168.137.1', port))
# 设置最大连接数,超过后排队
serversocket.listen(5)
# 建立客户端连接
print('\n'+'{:-^30}'.format('等待客户连接'))
clientsocket,addr = serversocket.accept()
print("连接地址: %s" % str(addr))
# print(clientsocket.recv(1024))
msg='HELLO WORLD! By HuaiYe怀也\r\n'
msg_back = 0
clientsocket.send(msg.encode('utf-8'))
while True:
msg_back = clientsocket.recv(1024)
ser.write(msg_back)
# print(msg_back.decode('utf-8'))
clientsocket.close()
虚拟串口软件是Configure Virtual Serial Port Driver。
视频如下:
[localvideo]bd353fd4ad93ff85aa17eb138b3e968f[/localvideo]
可以看出,效果拉跨,和别的大佬做的比起来,我就是依托答辩。
另外,这个任务遇到了一个很大的难题,那就是使用micropython固件连接网络,需要升级nina模块的固件,我在官网找到了升级教程,下载了arduino idle,使用了固件升级工具尝试了无数次,都没有成功。然后我就去arduino论坛翻啊翻,也没有解决。
最后根据我自己的尝试和推算,我终于发现了问题所在,那就是micropython的repl占用了与电脑usb通信的串口,所以固件一直刷不到nina上。解决办法是,找到一个不是micropython固件的.uf2文件,刷上去,然后再升级固件就可以了,最后再重新刷上micropython固件就可以使用了。
整个流程的示意图:
任务三:学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形:
这个任务我是一点头绪都没有,但是已经有大佬造的轮子了,有大佬写好了相应的驱动库了,我们会用就行了,而且还有另外的大佬已经搬运到eeworld论坛了,所以我主要参考的就是HonestQiao大佬的https://bbs.eeworld.com.cn/thread-1299974-1-1.html#pid3381260,里面有提到github上大佬写好的库,我去github上下载好库,然后用示例代码就可以跑起来了,自己稍微修改了点点。
代码如下:
from time import sleep
from wavsimple import wav
from machine import Pin
import st34dt05a as pdm
pcm_rate = 8_000 # Hz - default is 12kHz i.e. 3.072MHz bit-sample rate
pdm.bit_sample_freq = pcm_rate * 256
pdm_clk = Pin(23)
pdm_data = Pin(22)
w = wav('output.wav', SampleRate=pcm_rate)
record_flag = False
def buffer_handler(inactive_buf):
global record_flag
if record_flag:
buff = pdm.get_buffer(inactive_buf)
w.write(buff) #录制声音
for i,n in enumerate(buff): #答应数据,隔100打印一次
if i % 100 == 0:
print(n)
pdm.init(pdm_clk, pdm_data, handler=buffer_handler)
pdm.start()
sleep(1) # wait whilst StateMachine inits
record_flag = True
sleep(10)
record_flag = False
w.close()
可以用thonny的绘图器查看波形,我也按照一定间隔才打印出来,避免占用板子过多资源。然后程序会生成output.wav文件,我们可以用电脑播放。
流程示意图:
视频如下:
[localvideo]47b2529891bd5568cfaac988a38f2b7f[/localvideo]
但是我有一个疑问,就是为什么录制的声音像是开了二倍数一样?有没有懂得大佬可以解释。
打包的代码和库:
总结:
这次完成的不是很好,真是愧对于平台给我的机会啊。
- 2024-12-18
-
加入了学习《【得捷电子Follow me第2期】个人任务视频》,观看 【得捷电子Follow me第2期】个人任务视频
-
加入了学习《Arduino? Nano RP2040 Connect 任务视频》,观看 串口打印
- 2024-12-17
-
加入了学习《【Follow me第二季第4期】ARDUINO NANO RP2040 CONNECT》,观看 PDM功能演示-ARDUINO NANO RP2040 CONNECT
-
回复了主题帖:
【Follow me第二季第4期】任务一:极简环境+快速烧录+花样点灯+结果输出+小知识
HonestQiao 发表于 2024-12-14 21:25
micropython官方下载的版本即可,2022年就支持了的。
我运行提示我nina固件太低了,是1.48版本,要匹配到1.5版本才可以运行,然后我用arduino idle带的固件升级工具去升级nina的固件一直不成功,我都要哭了,大佬知道怎么回事吗?
- 2024-12-10
-
回复了主题帖:
【Follow me第二季第4期】任务三:PDM麦克风小知识+数据读取+波形呈现+wav存储
决定跟着大佬做这次作业了!刚好想用mpy做!!!谢谢大佬
-
回复了主题帖:
【Follow me第二季第4期】任务三:PDM麦克风小知识+数据读取+波形呈现+wav存储
感谢大佬分享!
-
回复了主题帖:
【Follow me第二季第4期】任务一:极简环境+快速烧录+花样点灯+结果输出+小知识
谢谢大佬!!!,我就想用mpy开发,网上教程很少,我只找到了一点点例程。大佬分享的干货让我得以顺利上手,谢谢!!!
另外,我在官网下的mpy固件好像用不了wifi例程,提示要我更新固件,是不是需要openmv才可以更新最新的固件
-
回复了主题帖:
【Follow me第二季第4期】任务二:IMU知识+IMU数据读取+IMU控制立方体
学习了!!!感谢大佬分享
- 2024-12-03
-
回复了主题帖:
【Follow me第二季第4期】Nano RP2040 Connect 开发板简介、环境搭建、工程测试
点赞👍,写的很详细,对我这种小白很友好呀。
- 2024-12-02
-
加入了学习《直播回放: DigiKey FollowMe 第二季 第4期 Arduino Nano RP2040 Connect 任务讲解》,观看 Arduino Nano RP2040 Connect 任务讲解
- 2024-02-02
-
加入了学习《【得捷电子Follow me第2期】个人任务视频》,观看 【得捷电子Follow me第2期】个人任务视频
-
加入了学习《【得捷电子Follow me第2期】个人任务视频》,观看 【得捷电子Follow me第2期】个人任务视频