上篇文章:玩转RP2040之开箱测评与上电运行,介绍了RP2040的硬件和上电使用情况,本篇来进行软件开发环境的搭建。
RP2040支持Python或C语言开发,本篇使用Python来进行开发。
这款RP2040板子与树莓派的另一款产品Pico的处理器都是RP2040,因此可以参考RaspberryPi Pico的教程:
https://pico.wiki/index.php/2021/04/27/getting-started-with-raspberry-pi-pico-basic-intro.html
进入树莓派官网:https://www.raspberrypi.com/documentation/microcontrollers/micropython.html,下载对应的Python固件,我下载的固件名称为:rp2-pico-20221116-unstable-v1.19.1-682-gd1ed0f161.uf2
下载固件后,需要烧录到板子中,实际上,只需要将这个固件拖拽到板子中即可。
操作步骤为:
按下BOOT和RESET,然板子复位
松开RESET(BOOT仍按下),然板子进入BOOT
等电脑上弹出RPI-RP2的盘符(文件夹)后,可松开BOOT
然后把下载的python固件拖拽到这个盘中即可
拖拽成功后,盘符会自动消失,此时固件烧录工作即完成
注意,固件烧录后,板子自动的程序也会消失,所以此时再重启板子,会是黑屏状态。
Thonny为 一个面向初学者的Python IDE
去Thonny官网:https://thonny.org/ 下载Windows版的安装包,安装即可。
板子连接电脑,用Thonny打开Python例程,右下角切换到Pi Pico,然后点击左上角的下载键。
下载完成后,即可看到程序的运行结果:
注意,这种下载方式,程序还行没有固化到板子中,掉电重启后,程序也不在了,需要重新进行程序下载才能看到程序的运行。
研究了一下Thonny这个软件,发现可以将Python程序放到板子中,操作方法是点击菜单中的文件->另存为,会弹出一个窗口,提示保存到电脑还是Pico中,选择Pico后,即可保存python文件到板子中。
在保存的时候,还可以重命名文件,如我的重命名为main.py。注意到,保存到板子中的文件,Thonny中的文件名会显示一个中括号,并且Thonny窗口的顶部信息也会显示此文件在Pico中。
此时点击运行,运行的就是板子中的python程序,并且板子调电后,也能开机运行板子中的python程序,从而可以说明程序已经固化到板子中了。
上面的测试程序,整个代码都是在一个.py文件中,不便于代码分类管理。实际上,我们可以将代码按功能进行拆分,也是也可在板子中运行的。我这里将LCD和IMU的代码单独分离出来,整理为3个文件:
main.py
mylcd.py
myimu.py
注意,在运行时,需要将这3个文件都放到板子中再点击运行,不放到板子中,运行main.py,会报错找不到另外两个文件的。
main.py
from machine import Pin,I2C,SPI,PWM,ADC import mylcd import myimu import time Vbat_Pin = 29 #主函数 if __name__=='__main__': #LCD LCD = mylcd.LCD_GC9A01A() LCD.set_bl_pwm(65535) #IMU qmi8658=myimu.IMU_QMI8658C() #ADC Vbat= ADC(Pin(Vbat_Pin)) while(True): #read QMI8658 xyz=qmi8658.Read_XYZ() LCD.fill(LCD.white) LCD.fill_rect(0,0,240,40,LCD.red) LCD.text("RP2040-LCD-1.28",60,25,LCD.white) LCD.fill_rect(0,40,240,40,LCD.blue) LCD.text("Waveshare",80,57,LCD.white) LCD.fill_rect(0,80,120,120,0x1805) LCD.text("ACC_X={:+.2f}".format(xyz[0]),20,100-3,LCD.white) LCD.text("ACC_Y={:+.2f}".format(xyz[1]),20,140-3,LCD.white) LCD.text("ACC_Z={:+.2f}".format(xyz[2]),20,180-3,LCD.white) LCD.fill_rect(120,80,120,120,0xF073) LCD.text("GYR_X={:+3.2f}".format(xyz[3]),125,100-3,LCD.white) LCD.text("GYR_Y={:+3.2f}".format(xyz[4]),125,140-3,LCD.white) LCD.text("GYR_Z={:+3.2f}".format(xyz[5]),125,180-3,LCD.white) LCD.fill_rect(0,200,240,40,0x180f) reading = Vbat.read_u16()*3.3/65535*2 LCD.text("Vbat={:.2f}".format(reading),80,215,LCD.white) LCD.show() time.sleep(0.1)
myimu.py
from machine import Pin,I2C,SPI,PWM,ADC I2C_SDA = 6 I2C_SDL = 7 #IMU传感器--IIC接口 class IMU_QMI8658C(object): def __init__(self,address=0X6B): self._address = address self._bus = I2C(id=1,scl=Pin(I2C_SDL),sda=Pin(I2C_SDA),freq=100_000) bRet=self.WhoAmI() if bRet : self.Read_Revision() else : return NULL self.Config_apply() def _read_byte(self,cmd): rec=self._bus.readfrom_mem(int(self._address),int(cmd),1) return rec[0] def _read_block(self, reg, length=1): rec=self._bus.readfrom_mem(int(self._address),int(reg),length) return rec def _read_u16(self,cmd): LSB = self._bus.readfrom_mem(int(self._address),int(cmd),1) MSB = self._bus.readfrom_mem(int(self._address),int(cmd)+1,1) return (MSB[0] << 8) + LSB[0] def _write_byte(self,cmd,val): self._bus.writeto_mem(int(self._address),int(cmd),bytes([int(val)])) def WhoAmI(self): bRet=False if (0x05) == self._read_byte(0x00): bRet = True return bRet def Read_Revision(self): return self._read_byte(0x01) def Config_apply(self): # REG CTRL1 self._write_byte(0x02,0x60) # REG CTRL2 : QMI8658AccRange_8g and QMI8658AccOdr_1000Hz self._write_byte(0x03,0x23) # REG CTRL3 : QMI8658GyrRange_512dps and QMI8658GyrOdr_1000Hz self._write_byte(0x04,0x53) # REG CTRL4 : No self._write_byte(0x05,0x00) # REG CTRL5 : Enable Gyroscope And Accelerometer Low-Pass Filter self._write_byte(0x06,0x11) # REG CTRL6 : Disables Motion on Demand. self._write_byte(0x07,0x00) # REG CTRL7 : Enable Gyroscope And Accelerometer self._write_byte(0x08,0x03) def Read_Raw_XYZ(self): xyz=[0,0,0,0,0,0] raw_timestamp = self._read_block(0x30,3) raw_acc_xyz=self._read_block(0x35,6) raw_gyro_xyz=self._read_block(0x3b,6) raw_xyz=self._read_block(0x35,12) timestamp = (raw_timestamp[2]<<16)|(raw_timestamp[1]<<8)|(raw_timestamp[0]) for i in range(6): # xyz=(raw_acc_xyz[(i*2)+1]<<8)|(raw_acc_xyz[i*2]) # xyz[i+3]=(raw_gyro_xyz[((i+3)*2)+1]<<8)|(raw_gyro_xyz[(i+3)*2]) xyz = (raw_xyz[(i*2)+1]<<8)|(raw_xyz[i*2]) if xyz >= 32767: xyz = xyz-65535 return xyz def Read_XYZ(self): xyz=[0,0,0,0,0,0] raw_xyz=self.Read_Raw_XYZ() #QMI8658AccRange_8g acc_lsb_div=(1<<12) #QMI8658GyrRange_512dps gyro_lsb_div = 64 for i in range(3): xyz=raw_xyz/acc_lsb_div#(acc_lsb_div/1000.0) xyz[i+3]=raw_xyz[i+3]*1.0/gyro_lsb_div return xyz
mylcd.py
from machine import Pin,I2C,SPI,PWM,ADC import framebuf import time DC = 8 CS = 9 SCK = 10 MOSI = 11 RST = 12 BL = 25 #屏幕--SPI接口 class LCD_GC9A01A(framebuf.FrameBuffer): def __init__(self): self.width = 240 #屏幕宽度 self.height = 240 #屏幕高度 self.cs = Pin(CS,Pin.OUT) self.rst = Pin(RST,Pin.OUT) self.cs(1) self.spi = SPI(1,100_000_000,polarity=0, phase=0,sck=Pin(SCK),mosi=Pin(MOSI),miso=None) self.dc = Pin(DC,Pin.OUT) self.dc(1) self.buffer = bytearray(self.height * self.width * 2) super().__init__(self.buffer, self.width, self.height, framebuf.RGB565) self.init_display() self.red = 0x07E0 self.green = 0x001f self.blue = 0xf800 self.white = 0xffff self.fill(self.white) #先填充为白色 self.show() self.pwm = PWM(Pin(BL)) self.pwm.freq(5000) #省略......
将这3个文件保存到板子中的演示图如下,可以看到3个文件名都有中括号:
在main.py上运行,可以运行成功,说明程序在板子中运行正常。
本篇介绍了RP2040的Python软件开发环境搭建,并进行了程序烧录测试、代码固化到板子中测试,Python项目拆分为多个文件运行测试。Thonny这个软件第一次用,可能还有一些功能没探索到,大家有哪里使用心得欢迎讨论分享。
引用: dcexpert 发表于 2022-11-27 10:42 thonny可以通过串口输出数据,自动画出折线图,这个功能比较有用
又get到一个未探索的功能,有时间试试