项目流水账
新的工作要开始接触stm32,之前虽然也跟着别的项目有所接触,但是没有自己从头到尾做过一遍,现在要一个人抗下所有了,只能自学,希望能遇到所有的问题,把stm32学完。
项目需求,用移远的ec600U模组和stm32实现数据的采集和上传 只是暂时的会不断更新。
用到的模块:ec600U stm32l010f4p6 mpu6050 w25q128 lc29h暂时只有这么多
因为硬件还有没有把板子搞出来,只能暂时淘宝买各种模块去搭建一个类似的平台
给到的资源:ec600U模组 stm32l076rz mpu6050 w25q128 l76k
方案一:直接用移远的模组外挂这些sensor和flash,便宜又方便,开发量小。
方案二:stm32+移远模组 有点烦人,做的事比较多。
方案一:
第一个周末:LK76是移远的模组 可以完美的打通,也是2小时的事,但是到了mpu6050就遇到了问题,研究了移远模组的python api所谓的iic功能,调试了一整天只能读到一组不会改变的数据,尽管看了很久他的iic协议还是不行,我自信我的代码没有错。最后查了一下硬件图,发现mpu6050的模组上拉的是3.3V的电,但是移远模组上拉要求1.8V的电,应该就是这个出了问题,无奈先放弃。
第二天,加载flash模组提供了spi的接口,但是读写的时候还是出了问题,有了之前mpu6050的经验我直接去看硬件的上拉,结果一样一个是3.3V一个是1.8V.没办法剩下的时间只能看看模组提供的api学习学习。看到EC600N有挂载文件的接口,但是EC600U没有,咨询了一下移远的技术支持,他们说ram太小了放不下这个接口。提出用eeprom去存,但是考虑到数据要存的比较多,可能不够所以直接放弃方案一,白瞎了2天,只调通了一个L76K。
贴一下调成功的代码记录一下,
import net import utime from machine import UART import ure import log import utime import _thread from machine import Pin from machine import UART log.basicConfig(level=log.NOTSET) # 设置日志输出级别 log = log.getLogger("Grey") # 获取logger对象,如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象 fixFlag = 0 stattus = None GNSS_Baud = 1 state = 1 readnum = 600 gpio1 = Pin(Pin.GPIO1, Pin.OUT, Pin.PULL_DISABLE, 0) if GNSS_Baud == 1: uart = UART(UART.UART1, 9600, 8, 0, 1, 0) elif GNSS_Baud == 2: uart = UART(UART.UART1, 115200, 8, 0, 1, 0) else: uart = UART(UART.UART1, 9600, 8, 0, 1, 0) def uart_read(): log.debug("uart_read start!") global state global readnum # while 1: while readnum: msgLen = uart.any() # 返回是否有可读取的数据长度 if msgLen: # 当有数据时进行读取 readnum -= 1 msg = uart.read(msgLen) utf8_msg = msg.decode() # 初始数据是字节类型(bytes),将字节类型数据进行编码 if "Usart End" in utf8_msg: break else: log.info("---------------start-----------------") log.info("uart_read msg: {}".format(utf8_msg)) log.info("---------------end-------------------") else: utime.sleep_ms(1) continue state = 0 log.debug("uart_read end!") ''' * 参数1:端口 注:EC100YCN平台与EC600SCN平台,UARTn作用如下 UART0 - DEBUG PORT UART1 – BT PORT UART2 – MAIN PORT UART3 – USB CDC PORT * 参数2:波特率 * 参数3:data bits (5~8) * 参数4:Parity (0:NONE 1:EVEN 2:ODD) * 参数5:stop bits (1~2) * 参数6:flow control (0: FC_NONE 1:FC_HW) ''' def uart_write(): log.debug("uart_write start!") count = 3 # 配置uart while count: count -= 1 utime.sleep(1) if GNSS_Baud == 1: write_msg = "$PCAS01,5*19\r\n".format(count) # 115200波特率 elif GNSS_Baud == 2: write_msg = "$PCAS01,1*1D\r\n".format(count) # 9600波特率 else: write_msg = "$PCAS01,5*19\r\n".format(count) # 115200波特率 uart.write(write_msg) # 发送数据 log.info("{}".format(write_msg)) log.debug("uart_write end!") def run(): log.debug("run start!") _thread.start_new_thread(uart_read, ()) # 创建一个线程来监听接收uart消息 _thread.start_new_thread(uart_write, ()) # 创建一个线程来监听执行uart_write函数 log.debug("run end!") class GnssGetData: # GPS数据采集及解析 def __init__(self, uartn, baudrate, databits, parity, stopbits, flowctl): if uartn == 0: UARTN = UART.UART0 elif uartn == 1: UARTN = UART.UART1 elif uartn == 2: UARTN = UART.UART2 elif uartn == 3: UARTN = UART.UART3 else: UARTN = UART.UART1 self.uart = UART(UARTN, baudrate, databits, parity, stopbits, flowctl) write_msg = "$PCAS03,1,1,1,1,1,1,1,1,0,0,,,0,0*02\r\n".format() # 115200波特率 uart.write(write_msg) utime.sleep(3) # Delay to read data stability # 读取GNSS数据并加以解析 def read_gnss_data(self): try: buf = self.uart.read(self.uart.any()) gps_data = buf.decode().strip("b") print("gps_data:",gps_data,"\n") self.r = ure.search("GNGGA(.+?)M", gps_data) print("self.r:",self.r,"\n") self.r1 = ure.search("GNRMC(.+?)M", gps_data) print("self.r1:",self.r1,"\n") self.r2 = ure.search("GPGSV(.+?)M", gps_data) print("self.r2:",self.r2,"\n") self.r3 = ure.search("GNVTG(.+?)M", gps_data) print("self.r3:",self.r3,"\n") global fixFlag if self.r1.group(0).split(",")[2] == 'A': # 有效定位 fixFlag = 1 else: fixFlag = 0 except: print("Exception:read gnss data error!!!!!!!!") raise # 获取GPS模块是否定位成功 @staticmethod def isfix(): global fixFlag return fixFlag # 获取GPS模块定位的经纬度信息 def get_location(self): if self.isfix() is 1: lat = float(self.r.group(0).split(",")[2]) // 100 + float( float(float(self.r.group(0).split(",")[2]) % 100) / 60) # lat_d = self.r.group(0).split(",")[3] # log = float(self.r.group(0).split(",")[4]) // 100 + float( float(float(self.r.group(0).split(",")[4]) % 100) / 60) # log_d = self.r.group(0).split(",")[5] # return lat, lat_d, log, log_d else: return None # 获取GPS模块授时的UTC时间 def get_utc_time(self): return self.r.group(0).split(",")[1] # 获取GPS模块定位模式 def get_location_mode(self): if self.r.group(0).split(",")[6] is '0': # print('定位不可用或者无效') return 0 if self.r.group(0).split(",")[6] is '1': # print('定位有效,定位模式:GPS、SPS 模式') return 1 if self.r.group(0).split(",")[6] is '2': # print('定位有效,定位模式: DGPS、DSPS 模式') return 2 # 获取GPS模块定位使用卫星数量 def get_used_sate_cnt(self): return self.r.group(0).split(",")[7] # 获取GPS模块定位可见卫星数量 def get_viewed_sate_cnt(self): return self.r2.group(0).split(",")[3] # 获取GPS模块定位方位角 范围:0~359。以真北为参考平面。 def get_course(self): return self.r2.group(0).split(",")[6] # 获取GPS模块对地速度(单位:KM/h) def get_speed(self): if self.r1.group(0).split(",")[7] == '': return None else: return float(self.r1.group(0).split(",")[7]) * 1.852 # 获取GPS模块定位大地高(单位:米) def get_geodetic_height(self): return self.r.group(0).split(",")[9] def showtime(): net.nitzTime() local_time = utime.localtime() stattus = '{0:0>4d}-{1:0>2d}-{2:0>2d} {3:0>2d}:{4:0>2d}:{5:0>2d}'.\ format(local_time[0], local_time[1], local_time[2], local_time[3], local_time[4], local_time[5]) print(stattus) utime.sleep(1)
下面是成功拿到的数据
gps_data: $GNGGA,083542.000,2807.70328,N,12059.06939,E,1,06,2.2,114.8,M,13.0,M,,*4B
$GNGLL,2807.70328,N,12059.06939,E,083542.000,A,A*46
$GNGSA,A,3,07,08,21,27,,,,,,,,,5.9,2.2,5.5,1*34
$GNGSA,A,3,26,35,,,,,,,,,,,5.9,2.2,5.5,4*3A
$GPGSV,2,1,05,01,34,181,,07,48,311,19,08,62,004,31,21,61,149,24,0*69
$GPGSV,2,2,05,27,34,038,32,0*58
$BDGSV,1,1,02,26,79,358,29,35,64,032,31,0*7E
$GNRMC,083542.000,A,2807.70328,N,12059.06939,E,0.00,315.13,030222,,,A,V*0F
$GNVTG,31
5.13,T,,M,0.00,N,0.00,K,A*26
$GNZDA,083542.000,03,02,2022,00,00*43
$GPTXT,01,01,01,ANTENNA OPEN*25
$GNGGA,083543.000,2807.70321,N,12059.06946,E,1,06,2.2,114.8,M,13.0,M,,*4B
$GNGLL,2807.70321,N,12059.06946,E,083543.000,A,A*46
$GNGSA,A,3,07,08,21,27,,,,,,,,,5.9,2.2,5.5,1*34
$GNGSA,A,3,26,35,,,,,,,,,,,5.9,2.2,5.5,4*3A
$GPGSV,2,1,05,01,34,181,,07,48,311,19,08,62,004,31,21,61,149,24,0*69
$GPGSV,2,2,05,27,34,038,32,0*58
$BDGSV,1,1,02,26,79,358,29,35,64,032,31,0*7E
$GNRMC,083543.000,A,28
07.70321,N,12059.06946,E,0.00,315.13,030222,,,A,V*0F
$GNVTG,315.13,T,,M,0.00,N,0.00,K,A*26
$GNZDA,083543.000,03,02,2022,00,00*42
$GPTXT,01,01,01,ANTENNA OPEN*25
$GNGGA,083544.000,2807.70314,N,12059.06954,E,1,06,2.2,114.9,M,13.0,M,,*48
$GNGLL,2807.70314,N,12059.06954,E,083544.000,A,A*44
$GNGSA,A,3,07,08,21,27,,,,,,,,,5.9,2.2,5.5,1*34
$GNGSA,A,3,26,35,,,,,,,,,,,5.9,2.2,5.5,4*3A
$GPGSV,2,1,05,01,34,181,,07,48,311
,19,08,62,004,31,21,61,149,24,0*69
$GPGSV,2,2,05,27,34,038,32,0*58
$BDGSV,1,1,02,26,79,358,29,35,64,032,31,0*7E
$GNRMC,083544.000,A,2807.70314,N,12059.06954,E,0.00,315.13,030222,,,A,V*0D
$GNVTG,315.13,T,,M,0.00,N,0.00,K,A*26
$GNZDA,083544.000,03,02,2022,00,00*45
$GPTXT,01,01,01,ANTENNA OPEN*25
$GNGGA,083545.000,2807.70311,N,12059.06960,E,1,06,2.2,114.9,M,13.0,M,,*4B
$GNGLL,2807.70311,N,12059.06960,E,083545.000,A,A*47
self.r: <match num=2>
self.r1: <match num=2>
self.r2: <m
atch num=2>
self.r3: <match num=2>
获取GPS模块是否定位成功:1(0表示失败,1表示成功)
获取GPS模块授时的UTC时间:083542.000
获取GPS模块定位模式:1(0表示定位不可用或者无效,1表示GPS、SPS 模式,2表示DGPS、DSPS 模式)
获取GPS模块定位使用卫星数量:06
获取GPS模块定位的经纬度信息:(28.12838800000001, 'N', 1
20.9844898333333, 'E')
获取GPS模块定位可见卫星数量:05
获取GPS模块定位方位角 范围:0~359。以真北为参考平面:181
获取GPS模块定位大地高:114.8米
获取GPS模块对地速度:0.0KM/h
时间线------------------------------------------------------------------------------------------------------------------2022/1/15
方案二:
第二个周末:之前没怎么做过stm32就要从头学一遍,真是苦了我。
1.首先要学习stm32cubemx去构建代码。https://www.bilibili.com/video/BV1m7411d78e?spm_id_from=333.999.0.0 这个小白教程还可以大致入门了,构建好了代码。
2.安装keil5.27 这个之前项目做过直接拿安装包装一下。但是下载pack是真的慢,https://blog.csdn.net/simon223/article/details/105090189 这个网址可以下载很多需要的包真是福音,Keil.STM32L0xx_DFP.2.2.0.pack 这个包是必下的。
3.https://blog.csdn.net/weixin_42741212/article/details/106220998 按照这个博客搞完然后编译一把,就差烧录验证了。
4.买了个正版stlink 血亏80。然后就是非常蛋疼的环节了。折磨了4个小时。
一开始这里什么都没有,然后add也找不到对应的stm32,然后安装了一个pack,Keil.STM32L0xx_DFP.2.2.0.pack 应该就是这个,然后选对device后,add才会有正确的选项。花费2小时。
然后更加坑爹的来了
st的评估板上留了一个jtag的接口,当然选择jtag去烧了简单方遍,然后就出现了上图,不管怎么调试,改驱动都无法正常使用jtag。折磨了半小时,我想起了提示的这句话在stm32 F0和L0上JTAG不可用,不知道是内部有设置还是什么的,直接放弃了jtag,用的
swd。https://blog.csdn.net/praguejing/article/details/107596701参考这个博客接好线。stlink就能搜索到接口了,直接一把入魂,小灯闪了,泪流满面。搭环境4小时,烧录验证1分钟。
5.第一个模块mpu6050.
下载了淘宝正点原子哥的xxx战舰代码。好家伙居然是标准库写的,一看我的代码是hal库的,直接没软用。就去百度淘https://blog.csdn.net/dodwind/article/details/88624941这个博客非常好,简洁明了。
https://github.com/Heimerdingerzzz/MPU6050 直接下载代码。好像都搞好了,佩服做32的资源就是多。
https://www.zhihu.com/tardis/sogou/art/191646577 这个博客是如何把DMP添加进编译 不管有没有用先添加起来。
https://blog.csdn.net/he__yuan/article/details/76559569?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param 这个博客是如何引用mpu6050.c的函数方法说了一下。暂时先把初始化先简单编译一遍。
报错了 .\test1\test1.axf: Error: L6218E: Undefined symbol hi2c1 (referred from inv_mpu.o).
原来是没有添加iic的接口
遇到小插曲 为什么在芯片引脚上设置iic会是single mapped signals 是因为后面的connectivity没有打开iic 我真是小白。
编译成功。今天就这样吧 太雷人了。明天再验。
时间线------------------------------------------------------------------------------------------------------------------2022/1/21
今天初三了,电脑修好了但是stm32的miniusb线丢了,先暂时不搞stm32,先把ec600u先研究一下。
ec600u发送数据给腾讯云,然后小程序腾讯练练接收腾讯云发送的数据。也就是mqtt的订阅和数据接收
选择腾讯云是因为之前买了个
点击新建项目
点击新建产品
点击自己新建的产品
新建自定义功能,比如当前的是板子上的aht10温湿度传感器
然后一直下一步到设备调试 新建一个设备
微信搜索小程序 腾讯连连 然后扫描上面设备的二维码
都创建好了以后去下载mqtt-fx,如下的博客https://blog.csdn.net/tiantang_1986/article/details/85101366
然后下载https://iot-exp-individual-1258344699.cos.ap-guangzhou.myqcloud.com/password%E7%94%9F

点击connect 显示绿色就表示连接成功。然后看到腾讯云上的设备也显示在线。
上报后拿到右边的调试日志
然后把这个放到mqtt-fx内
然后publish 就可以在腾讯练练的设备里看到对应的改变了,其他的功能我先不研究。
然后把当前的ec600u板子上带的aht10的数据传到腾讯小程序上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import log import ujson import utime import _thread from machine import I2C import utime as time from TenCentYun import TXyun import checkNet from misc import Power productID = r "QOE7J6I5SH" # 产品标识 devicename = r "test" # 设备名称 devicePsk = r "spLipjbdCp62dPk+D1rH3A==" # 设备密钥(一型一密认证此参数传入 None) ProductSecret = None # 产品密钥(一机一密认证此参数传入 None) # 输入发布 Topic DEF_TOPIC_PUB = r "$thing/up/property/{}/{}" . format (productID, devicename) # 输入订阅 Topic DEF_TOPIC_SUB = r "$thing/down/property/{}/{}" . format (productID, devicename) CLIENT_TOKEN_STR = "7df3c076-40e1-49e4-8689-2a11df7dc1c3" PROJECT_NAME = "QuecPython_TencentYun_example" PROJECT_VERSION = "1.0.0" checknet = checkNet.CheckNetwork(PROJECT_NAME, PROJECT_VERSION) log.basicConfig(level = log.INFO) txyun_log = log.getLogger( "TenCentYun" ) class aht10class(): i2c_dev = None i2c_addre = None # Initialization command AHT10_CALIBRATION_CMD = 0xE1 # Trigger measurement AHT10_START_MEASURMENT_CMD = 0xAC # reset AHT10_RESET_CMD = 0xBA def write_data( self , data): self .i2c_dev.write( self .i2c_addre, bytearray( 0x00 ), 0 , bytearray(data), len (data)) pass def read_data( self , length): r_data = [ 0x00 for i in range (length)] r_data = bytearray(r_data) self .i2c_dev.read( self .i2c_addre, bytearray( 0x00 ), 0 , r_data, length, 0 ) return list (r_data) def aht10_init( self , addre = 0x38 ): self .i2c_dev = I2C(I2C.I2C1, I2C.STANDARD_MODE) # 返回 i2c 对象 self .i2c_addre = addre self .sensor_init() pass def aht10_transformation_temperature( self , data): r_data = data temperature = ((r_data[ 2 ] & 0xf ) << 16 ) | ( r_data[ 3 ] << 8 ) | r_data[ 4 ] temperature = (temperature * 200.0 / ( 1 << 20 )) - 50 I2C_log.info( "current temp is {0}°C" . format ( round ( temperature, 1 ))) return temperature def aht10_transformation_humidity( self , data): r_data = data # 根据数据手册的描述来转化温度 humidity = (r_data[ 0 ] << 12 ) | ( r_data[ 1 ] << 4 ) | ((r_data[ 2 ] & 0xF0 ) >> 4 ) humidity = (humidity / ( 1 << 20 )) * 100.0 I2C_log.info( "current humi is {0}%" . format ( round ( humidity, 1 ))) return humidity def sensor_init( self ): # calibration self .write_data([ self .AHT10_CALIBRATION_CMD, 0x08 , 0x00 ]) time.sleep_ms( 300 ) # at last 300ms pass def ath10_reset( self ): self .write_data([ self .AHT10_RESET_CMD]) time.sleep_ms( 20 ) # at last 20ms def Trigger_measurement( self , val): # Trigger data conversion self .write_data([ self .AHT10_START_MEASURMENT_CMD, 0x33 , 0x00 ]) time.sleep_ms( 200 ) # at last delay 75ms # check has success r_data = self .read_data( 6 ) # check bit7 if (r_data[ 0 ] >> 7 ) ! = 0x0 : I2C_log.info( "Conversion has error" ) else : temp = self .aht10_transformation_temperature(r_data[ 1 : 6 ]) humi = self .aht10_transformation_humidity(r_data[ 1 : 6 ]) val[ 0 ] = round (temp, 1 ) val[ 1 ] = round (humi, 1 ) def network_checknet(): while True : try : checknet.wait_network_connected( 30 ) utime.sleep_ms( 2000 ) txyun_log.info( 'network_checknet ... ...' ) except BaseException: txyun_log.info( 'network_checknet: Not Net, Resatrting...' ) utime.sleep_ms( 200 ) Power.powerRestart() def sub_cb(topic, msg): # 云端消息响应回调函数 TXyun_log.info( "subscribe recv:" ) TXyun_log.info(topic.decode(), msg.decode()) def main1(): tenxun = TXyun(productID, devicename, devicePsk, ProductSecret) # 创建连接对象 tenxun.setMqtt() tenxun.setCallback(sub_cb) tenxun.subscribe(DEF_TOPIC_SUB) tenxun.start() # i2c_obj = I2C(I2C.I2C0, I2C.STANDARD_MODE) # 返回 i2c 对象 ath_dev = aht10class() ath_dev.aht10_init() while True : val = [ 0 , 1 ] ath_dev.Trigger_measurement(val) send_data = ''' {{"clientToken": "{}", "method": "report", "params": {{ "lac": 0, "cid": 0, "mnc": 0, "mcc": 0, "networkType": 1,"temp": {}, "shidu": {} }} }}''' . format (CLIENT_TOKEN_STR, val[ 0 ], val[ 1 ]) send_data = ujson.loads(send_data) s = ujson.dumps(send_data) TXyun_log.info(s) tenxun.publish(DEF_TOPIC_PUB, s) utime.sleep_ms( 2000 ) if __name__ = = "__main__" : log.basicConfig(level = 99 ) CheckNet_log = log.getLogger( "CheckNet" ) TXyun_log = log.getLogger( "TXyun_log" ) I2C_log = log.getLogger( "AHT10" ) checknet = checkNet.CheckNetwork(PROJECT_NAME, PROJECT_VERSION) checknet.poweron_print_once() try : checknet.wait_network_connected( 30 ) _thread.start_new_thread(network_checknet, ()) except BaseException: CheckNet_log.info( 'Not Net, Resatrting...' ) utime.sleep_ms( 200 ) Power.powerRestart() txyun_log.info( 'txyun_log.info yepc over ' ) print ( 'print yepc over ' ) main1() |
今天就这样了 ,晚上看看如何自己搭建一个mqtt服务器。
时间线------------------------------------------------------------------------------------------------------------------2022/2/3
先加一个简单的printf打印,之前一直没加。初始化一个uart然后把这个huart1对应的加进去就好了。
#include <stdio.h>
/* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
/* USER CODE END 4 */
时隔一个月,入职也一个月了。都做的差不多了,又临时要修改方案了,真是操蛋,之前做的也只是项目的预热,板子一出来全都不一样了,fuck。
板子还是没到,但是还是叫我提前写代码,然后板子到了再调试。
先总结一下之前的做的把。
第一版 mpu6050+ec600U+w25q128+l76k mpu6050和w25q128在stm32上,l76k在ec600u上。
第二版 mpu6050+ec600U+w25q128+l76k 把外部传感器全部接到了 stm32上,剩下ec600u和stm32通信 ,要解决l76k和stm32的工作
第三版 L26-DR+ec600U+w25q128 把外部传感器全部接到了 stm32上,剩下ec600u和stm32通信 直接给我换了个gps的芯片,然后imu的芯片也去掉了L26-DR自带imu。这个是最终的版本。终于定下来~~
这个星期前几天还在弄mpu6050的dmp的问题,搞了2天好了,结果不要了。
先记录一下这个
mpu6050 之前做的能读到7个原始数据了,说明通了,现在搞姿态处理。
有2种方法 1是姿态融合需要自己去写算法,网上案例有参考一下就好了,但是对性能有点要求需要点算力。2是dmp,一个官方提供的黑盒子把,数据原始数据就可以得到姿态,移植一下就好了。
吐槽:这里当然是想用dmp的,简单移植一下就好了,但是当时这个printf一直是坏了,mpu_dmp_init初始化的时候一直卡住了 也不知道哪里有问题,一开始是以为dmp_load_motion_driver_firmware卡在这里了百度了很多有什么说中断,什么速度设置什么的,一直搞不定,卡了一天后来printf弄好了,加了点打印再试了一下,可以dmp_load_motion_driver_firmware成功了,但是这个过程非常非常非常慢,然后卡在自检这里,因为是接的模块杜邦线各种接根本不能稳定,然后干脆直接跳过自检等正式板子到,最后可以拿到姿态数据了,千辛万苦本来高高兴兴终于搞完一个模块,结果最终板子出来说直接用L26-DR,不用imu了。我直接气炸。这2天白忙活了。
至于或者融合算法我之前也是dmp一直初始化失败也是焦虑得半夜睡不着查到的。
https://www.zhihu.com/tardis/sogou/art/228805569 这个博客有说,还挺详细挺好。最后dmp能用了就直接用dmp了。这种算法什么的对工程研究起来简直浪费时间。
更新玩之前的
现在就是重新开始第三版了 蓝受..... 只给了我2周去搞代码,说2周后机子到了就要快速搞好。这周白瞎了2天就3天的时间做w25q128.
之前因为ec600u不支持外挂w25q128,导致我后面也没有去看这个,由于L26-DR暂时没有芯片,之前也没有搞过类似gps的芯片,那个l76k也是用的现成的代码,看了下文档决定,先做简单的flash。
w25q128基于stm32的例子网上例子非常多,写的好点的也就原子哥的,不过他那个不是hal写的,想直接拿过来用也比较麻烦
还好找到了个博客写的还不错
http://www.mcublog.cn/stm32/2021_01/stm32cubemx-spi-flash-w25q128/ 这个基本实现简单的读写。
涉及到的源码github是https://github.com/nimaltd/w25qxx 用的这个大叔的代码,后面fatfs的时候还改了不少。。。。
上面的都通了以后,就是要加一个管理flash的小系统了,这个我选择了一个比较小巧的fatfs。
网上找了很多的例子,还是一头雾水不知道怎么去修改,就看了下面的几个博客,很多的博客都没有讲到位最终移植部位在哪里。起码要把w25q128的什么初始化,读写接口给移植进去把,但是具体的都没有详细讲到,但是最后还是有个比较好的让我看到了关键点 就是第一篇这个讲的比较好,能让人通俗易懂。
1.https://blog.csdn.net/redeemer_Qi/article/details/108644860
2.https://blog.csdn.net/weixin_42653531/article/details/103745344
3.https://blog.csdn.net/qq_39772670/article/details/109824810
4.https://www.cnblogs.com/cage666/p/9178326.html
最关键的就是这几个初始化读写的移植,发现上面那个w25qxx的源码和上面这篇参考的这篇博客的函数名不一样,这就麻烦了鬼知道他用的是那个源码,但是直觉应该是正点原子的,然后看了一下果然,名字一点都不差的,但是正点原子的并不是单纯的w25q128的驱动源码,里面还添加了什么gpio的配置什么的。再加上我之前用的那个代码已经调通了能简单读写了,没办法只能看正点原子的代码用当前的代码去封装读写函数。就剩最后编译了。还是个大坑。
就是去配置ffconfig.h的时候。我也不看了直接按照博客的去配置,结果出现了如下的报错
newpro\newpro.axf: Error: L6218E: Undefined symbol ff_convert (referred from ff.o).
百度了一下就说什么的都有,什么包含头文件啊参数传递错误声明函数什么的。可能也是夜深了,突然脑子一动,我先不按博客的修改试试呢,然后就出现了各种奇怪的报错,然后这个报错问题还是好解决的,最后正常的编译成功,后来我在不经意中看到了2.https://blog.csdn.net/weixin_42653531/article/details/103745344 这个文档的最后可改进的地方,可能是在自定义的头里面 有些变量会影响编译。然后我就暂时先编译过了,等下周一再去测试能不能行。
还有我看了一下L26-DR的几个文档,发现这个gps好像和别的gps返回的数据有点不一样的,如果只是和普通的gps芯片一样的化返回的也就那几个参数和数据,分析的源码我也在github参考的下了一份。千万要一样啊 ,不一样那就完犊子了。我一个人有点难受了。
后续:
1.检测一下这个存储能不能完成功能。下周一就知道了。
2.L26-DR这个芯片要在stm32上工作起来,参考的例子估计是没有了 要自己调了,先暂时拿l76k用着,但是好像这2个很多不一样,弄好了也没意义。这个感觉要被搞很久很久。
3.stm32和L26-DR的通信,用的是uart,这个简单,ec600u那边的uart收发的代码之前调试的都可以了。
4.还有就是把这个数据通过ec600u和mqtt传出去。这个暂时用腾讯云是可以的,但是目前具体要通过什么方式或者什么样的服务器还不知道,可以延后一下。
据说只有2个月的时间去实现,然后就我一个人做,咋看不多的东西,但是没有机器再加上我是个stm32的小白,之前也没做过这种项目,期间还有其他c++的东西叫我写,好苦啊~~~~
时间线------------------------------------------------------------------------------------------------------------------2022/3/5
又来更新了,板子千呼万唤始出来,终于在上周五到了,出乎意料的坑,没有usb,只有一个sw的烧录接口,其他什么都没有了,stm32的芯片还给换了 导致后面出了大毛病。
遇到的问题:
1.没有和那种开发板一样把usb引出来,很多针脚都没有引出来,还要买漆包线,焊枪去飞线。(这个也能忍了)
2.因为之前写好的ec600u的代码是在开发板上的用的是python的版本,但是现在只留了串口,只能通过at指令去配置。(之前写的代码全部白瞎了)
3.l26-dr这个芯片也没有引出串口的针脚,目前是没有验证的方法,只能飞完线,然后通过电脑的串口去试验,没做过没啥经验,只能先试,再写。
首先遇到的问题就是没有usb接出来,导致异常不习惯,芯片换了stm32l010f4,flash和sram都是比较小的,关键是sram,只有2k导致后面的fatfs移植不上去,还有稍微申请一个大一点的buf就会编译不过。这2个都是血淋淋的教训,之前没做过也没往硬件上想,相信硬件会换一个和之前一样的32芯片,结果完全不是。
我在移植fatfs的时候一直以为是自己配置出现了问题,老编译不过,最后才想到硬件,去查了一下被坑了一晚上。最后fatfs这个就先不做了,等换芯片新板子到。
由于sram很小导致,创建接收gps的buf也只能建800bytes,信息都抓不全。
2.没有了usb,只能通过at指令去发送数据给ec600u。
硬件坚持不加usb,最终还是要用at写。心想一个测试板子这不加那不加的,又没有最后定版。
大概查了一下AT指令,意思就是通过串口发送指令给芯片。解决的思路,首先用电脑串口去模拟实现mqtt的功能,然后再用代码实现。
博客参考 https://www.cnblogs.com/asnail/p/12810359.html 简单的AT指令的讲解,再加上FAE提供的文档。
暂时配置成这样。后来试了一下,只配置后面的也可以。
AT+CESQ
AT+CGATT?
AT+QMTCFG="version",0,4
AT+QMTCFG="pdpcid",0,3
AT+QMTCFG="ssl",0,0,0
AT+QMTCFG="keepalive",0,60
AT+QMTCFG="session",0,0
AT+QMTCFG="timeout",0,20,3,1
AT+QMTCFG="will",0,0
AT+QMTCFG="recv/mode",0,0
AT+QMTCFG="qmtping",0,10
AT+QMTCFG="send/mode",0,0
----------------------------------------------------------
AT+QMTOPEN=0,"101.34.201.128",1883
AT+QMTCONN=0,"6ba02edb371340278a329fde1a6ed37e"
AT+QMTSUB=0,1,"topic/pub",0
AT+QMTPUBEX=0,1,0,0,"topic/pub",10
这里卡了很久,因为在输入AT+QMTOPEN=0,"101.34.201.128",1883后要赶紧输入AT+QMTCONN=0,"6ba02edb371340278a329fde1a6ed37e" 否则会导致链路层错误,卡了我整整2小时。当连上去的那一刹那,整个人都舒服了。
电脑串口成功了,那代码就灰常简单了。
uint8_t at0[]="at\r\n";
uint8_t at1[]="AT+QMTOPEN=0,\"101.34.201.128\",1883\r\n";
uint8_t at2[]="AT+QMTCONN=0,\"6ba02edb371340278a329fde1a6ed37e\"\r\n";
uint8_t at3[]="AT+QMTSUB=0,1,\"topic/pub\",0\r\n";
uint8_t at4[]="AT+QMTPUBEX=0,1,0,0,\"topic/pub\",10\r\n";
uint8_t buf[]="yepc hello word\r\n";
HAL_UART_Transmit(&huart2, at0,sizeof(at0)-1,0xffff);
HAL_Delay(500);
HAL_UART_Transmit(&huart2, at1,sizeof(at1)-1,0xffff);
HAL_Delay(500);
HAL_UART_Transmit(&huart2, at2,sizeof(at2)-1,0xffff);
HAL_Delay(500);
HAL_UART_Transmit(&huart2, at3,sizeof(at3)-1,0xffff);
memset(at4,0,sizeof(at4));
sprintf(&at4[0],"AT+QMTPUBEX=0,1,0,0,\"topic/pub\",%d\r\n",sizeof(buf)-1);
HAL_UART_Transmit(&huart2, at4,sizeof(at4)-1,0xffff);
//printf("sizeof:%d\r\n",sizeof(at4)-1);
HAL_Delay(200);
HAL_UART_Transmit(&huart2, buf,sizeof(buf)-1,0xffff);
这样就成了 因为没有拿到具体要传的东西,现在通了,就先放着了。等具体需求下来了再完善下。
3.就剩最后一个gps模块了。
因为没有飞线我现在也没有稳定连上串口去修改配置,但是出厂是有配置的
这样我就读到了数据,大致就下面的样子
$PSTMDRSENMSG,30,3291759960,428,-1941,16468*0C
$PSTMDRSENMSG,31,3291759960,-67,158,8*06
$PSTMDRSENMSG,30,3291828170,429,-1946,16460*02
$PSTMDRSENMSG,31,3291828170,57,-76,35*06
$PSTMDRSENMSG,30,3291896364,413,-1942,16474*08
$PSTMDRSENMSG,31,3291896364,36,30,18*23
$PSTMDRSENMSG,30,3291964557,406,-1940,16464*05
$PSTMDRSENMSG,31,3291964557,-59,27,-17*29
$PSTMDRSENMSG,30,3292032772,411,-1938,16469*0D
$PSTMDRSENMSG,31,3292032772,20,-68,17*0D
$PSTMDRSENMSG,30,3292100983,423,-1955,16461*0F
$PSTMDRSENMSG,31,3292100983,-28,-95,-5*34
$PSTMDRSENMSG,30,3292169305,406,-1945,16477*05
$PSTMDRSENMSG,31,3292169305,-57,45,-14*27
$GPRMC,205125.000,V,0000.00078,S,00000.00072,E,,,060924,,,N*69
$GPGGA,205125.000,0000.00078,S,00000.00072,E,0,00,99.0,-12.93,M,0.0,M,,*6F
$GPVTG,,T,,M,,N,,K,N*2C
$GNGSA,A,1,,,,,,,,,,,,,99.0,99.0,99.0*1E
$GNGSA,A,1,,,,,,,,,,,,,99.0,99.0,99.0*1E
$GNGSA,A,1,,,,,,,,,,,,,99.0,99.0,99.0*1E
$GPGLL,0000.00078,S,00000.00072,E,205130.000,V,N*53
$PSTMANTENNASTATUS,-1,0,0,0*7D
$PSTMDRCONFID,100.16,100.16,182.3160,0.1145,0.00,0.5669,0.000602,0.050000,100.0000,100.2,100.2,-1.6,0.0*1F
$PSTMDRGPS,-0.000013071,0.000012036,0.00000,0.00000,99.000,99.000,99.000,0.000,0.000,0.00000,-12.9*42
$PSTMDRSTEP,15,1.64763,0.00173,0,0,1.000,1.000,1*2F
$PSTMDRSTYPE,3*58
$PSTMDRUPD,0.0,0.0,1.1,0.00,-1.955,0.000,-0.000002,0.000000,0.0*75
$PSTMDRSTATE,3295170100,-0.0000041,-0.0000062,-0.32,0.00,1.6483,0.7582,0.02290,-0.000002,0.000000,-12.9*61
$PSTMDRCAL,0,0,0,0,ff,1,1,N*0C
$PSTMDRAHRS,-13.0,5.8,0.0,14.000,0.425,0.0*20
$PSTMDRGNSA,0,0,0,0,0,0.00,0.00,0.00,0.00,0.00,21.00,10.00,0.10,35.00*0C
$PSTMDREPE,141.42,-1.00*72
$PSTMDRDEBUG,-1.0,2.0,0.3,0.0,0.0,0.0*70
然后查了一下资料,据说只要用到$GPGGA和$GPRMC 就可以得到定位的信息。等飞完线就把其他的都关掉,就开这2个还有PSTMDRSENMSG
然后就是分析数据,这个我在GitHub上找到了代码
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App