Newhor 发表于 2024-11-25 07:38

【2024 DigiKey 创意大赛】自行车智能骑行助手

本帖最后由 Newhor 于 2024-11-27 09:38 编辑

<p><strong><span style="font-size:24px;">自行车智能骑行助手</span></strong></p>

<p><span style="font-size:16px;">作者:newhor</span></p>

<p> &nbsp;</p>

<p><span style="font-size:20px;"><b>一、作品简介</b></span></p>

<p>&nbsp;</p>

<p><span style="font-size:18px;"><b>简介</b></span></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;自行车智能骑行助手的想法是填补骑行配件功能的空缺,为户外骑行爱好者提供一个集胎压测量、体重监测分析及环境感知预警于一体的综合智能解决方案</p>

<p>市面上现有的骑行配件中,很少有监测骑行者长途骑行下的体重变化,胎压预警以及环境感知预警等功能。本作品主要特点如下:</p>

<p>①在骑行前,安装在自行车轮胎中的压力传感器采集的压力数据,可以监测轮胎的初始压力值,并通过ESP-NOW无线通信将数据传送到主控MCU,再通过前期的数据标定确定的函数关系,MCU将压力数据转换为胎压后,显示在屏幕上。当检测到胎压低于预设的安全范围(例如25PSI)时,智能助手会立即通过显示器提示骑行者进行胎压补充,确保骑行安全。具体实现包括:压力传感器安装在轮胎钢圈与内胎之间,测量初始压力值;ESP-NOW模块负责将传感器数据无线传输到主控MCU;主控MCU处理接收到的数据,并通过显示器显示给骑行者。</p>

<p>&nbsp;</p>

<p>②在长时间骑行时,系统通过采集安装在轮胎内的压力传感器的压力值,通过前期的标定,将其转化为体重值。结合骑行时间和BME680传感器提供的环境温度数据,系统通过算法计算一段时间内体重的变化量,如果体重变化量超过预设阈值,会触发警报,通过显示屏提醒用户,同时提供休息和补水建议。</p>

<p>&nbsp;</p>

<p>③通过拓展的BME680环境传感器,给骑行者提供户外骑行时的空气质量预警和高温预警。一旦发现空气质量下降或温度过高,智能助手将通过显示屏及时提醒骑行者采取相应措施,如减少运动强度或寻找遮阴处休息,确保骑行者的健康和安全。</p>

<p>&nbsp;</p>

<p>④通过车把端的MCU采集并记录BME680传感器在一段时间内的气压和湿度数据,MCU对这些数据进行分析,当检测到气压持续降低且空气湿度升高超过一定阈值时,提供下雨预警,通过显示器告警骑行者,建议提前返回或寻找避雨场所,确保骑行安全。</p>

<p>&nbsp;</p>

<p>⑤可记录骑行过程中的体重、胎压、环境变化数据保存在本地(后续添加手机端无线接收功能),并提供长期趋势分析,帮助骑行者更好地了解自身状况和改善骑行计划。</p>

<p>此外,该还系统具有强大的可拓展性,以后可以集成更多好玩的功能进来。</p>

<p>&nbsp;</p>

<p><strong>主要特点:</strong></p>

<ul>
        <li>胎压监测</li>
        <li>实时监测体重变化</li>
        <li>智能骑行建议</li>
        <li>恶劣天气预警</li>
        <li>可存储运动数据,分析长期数据</li>
        <li>硬件模功能块化设计,功能易扩展</li>
        <li>可太阳能充电</li>
        <li>开源</li>
</ul>

<p style="list-style-type:none">&nbsp;</p>

<p style="list-style-type:none"><span style="font-size:18px;"><b>照片</b></span></p>

<p style="list-style-type:none"><b>(1)车把数据接收显示端</b></p>

<p>&nbsp;&nbsp; &nbsp;</p>

<p>&nbsp;</p>

<p style="list-style-type:none"><b>(2)</b><b>轮胎数据采集发送端</b></p>

<p> &nbsp;<b>&nbsp;</b>&nbsp;&nbsp;<b>&nbsp;</b>&nbsp;&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><strong><span style="font-size:20px;">二、系统框图</span></strong></p>

<ol>
        <li><span style="font-size:18px;"><b>硬件说明</b></span></li>
</ol>

<p>&nbsp;</p>

<p>主要物料</p>

<ul>
        <li value="50">控制器:ESP32-C6,ESP32-S2MINI</li>
        <li value="50">加速度传感器:4554、MMA8452</li>
        <li value="50">湿度空气传感器:BME680</li>
        <li value="50">显示屏幕:1.8寸TFT</li>
        <li value="50">充电管理芯片:TP4054</li>
        <li value="50">薄膜式压力传感器</li>
        <li value="50">锂电池、太阳能板</li>
</ul>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><b>硬件框图</b></span></p>

<p>主要分为车轮压力数据采集端、以及车把数据接收显示端,采用模块集成方式、方便更换与拓展。</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p><strong><span style="font-size:18px;">&nbsp;&nbsp;&nbsp;&nbsp;2.软件说明</span></strong></p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;软件分为4个部分:</p>

<ul>
        <li value="50">MCU数据处理</li>
        <li value="50">ESPNOW数据传输</li>
        <li value="50">传感器数据采样控制</li>
        <li value="50">液晶显示</li>
</ul>

<p> &nbsp;</p>

<p><strong><span style="font-size:20px;">三、各部分功能说明</span></strong></p>

<ol>
        <li><span style="font-size:18px;"><b>硬件功能</b></span></li>
</ol>

<p>(1)轮胎端:主要完成胎压数据采集、ESPnow数据发送等功能</p>

<p> &nbsp;</p>

<ul>
        <li value="50">轮胎端主控使用ESP32-S2MINI,这是一款乐鑫一款入门级开发板,搭载Xtensa&reg;32位LX7单核处理器,工作频率高达240MHz。可深度休眠,利用低功耗协处理器监测外设的状态变化或某些模拟量多的阈值,可通过外部中断唤醒,常用于可穿戴电子设备、智能家居等场景常用于物联网设备开发。在该作品中,利用其ADC功能,采集安装于轮胎内壁的薄膜式压力传感器的电压值,并通过ESPnow无线功能,实时将数据上传到车把端的MCU进行处理。</li>
        <li value="50">加速度传感器采用了基础型号MMA8452,加速度传感器的中断输出引脚,连接到轮胎端ESP32MINI上可支持休眠唤醒的IO口,并在采样程序中配置了休唤醒中断。当自行车静止一段时间后,ESP32MINI由于未检测到加速度传感器的运动中断,会进入深度休眠降低功耗,当检测到轮胎震动时,加速度传感器会立即产生运动中断唤醒MCU,开始采集压力数据,实现了轮胎端采样系统的低功耗。</li>
</ul>

<p align="justify">&nbsp;</p>

<p align="center"> &nbsp;</p>

<ul>
        <li value="50">压力传感器采用薄膜式,方便安装于轮胎与钢圈之间,当轮胎由于胎压或骑行者体重产生形变时,薄膜式压力传感器受到压力产生相应的形变,其电阻值产生相应变化,MCU通过电阻分压电路的方式进行ADC采样,将压力值转换为电压值。</li>
</ul>

<p> &nbsp;</p>

<ul>
        <li value="50">供电部分,配备了电池,并基于TP4054芯片设计了可多路供电的防反充电电路,通过添加多个二极管防止反充,实现开发板的USB接口以及太阳能板双充电模式。</li>
</ul>

<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;(2)车把端:主要完成数据接收,处理、以及数据显示等功能</p>

<p> &nbsp;</p>

<ul>
        <li value="50">车把端主控使用大赛提供的ESP32-C6开发板,是一款高性能、低功耗的单芯片解决方案。多达&nbsp;22 个 GPIO 引脚,支持&nbsp;SPI、I2C、UART&nbsp;等多种通信协议,具有 Wi-Fi 6 和 蓝牙低能耗(Bluetooth LE 5.2) 的支持,主要面向现代无线通信需求。该作品采用该模块作为主控接收端MCU,能满足ESPNOW无线功能高频的数据接收和处理需求,并同时实现了对多个传感器的数据采集处理,以及显示。</li>
        <li value="50">显示器使用ST7735驱动TFT屏,支持全彩显示、内容方向可调整,数据显示量够大,且观感更好。</li>
        <li value="50">加速度传感器模块使用的是大赛提供的4554,ICM-20948 是一款高性能的9轴运动传感器,具有高精度与低噪声等特点,在该作品中,该模块用于判断自行车实时的骑行状态,是加减速还是匀速,帮助MCU处理数据,消除加减速带来的轮胎形变时产生的误差数据。</li>
        <li value="50">环境传感器使用的是大赛提供的BME680模块,具有环境参数丰富,精度较高等特点。在该作品中,主要用于采样环境参数,包括温湿度、空气质量、大气压等。其中温度数据,用于辅助长时间骑行时体重变化量供相应的休息和补水建议;通过分析湿度和大气压数据下雨前的变化趋势,提前预测降雨的可能性,并通过屏幕向骑行者发出提醒;空气质量数据,实时转换为空气质量IAQ,给户外骑者相应的户外骑行建议。</li>
        <li value="50">供电电路与轮胎端一致,采用电池供电,并支持USB与太阳能板双充电。</li>
</ul>

<p><span style="font-size:18px;">2.<b>软件功能</b></span></p>

<p><b>&nbsp; &nbsp; (1)数据标定以及转换部分</b></p>

<p>在胎压数据标定时,由于传感器的精度以及受到安装位置的影响,会出现相同胎压下前后轮的压力传感器初始压力不一致的现象,故前后轮的压力数据分开进行标定。压力传感器安装于车轮内部后,通过带压力显示的打气筒给轮胎补充到多组不同的胎压值,得到对应胎压下的传感器压力数值,作为空载状态下,不同胎压与采集电压的数据组合,通过数据拟合得到相应的函数关系后,实现通过空载状态下电压计算出当前胎压数值的功能。</p>

<p>在体重数据标定时,通过记录多个不同体重骑行者,骑行时与空载的压力差值,与相应体重进行数据组合,然后进行数据拟合,得到电压差与骑行者体重函数关系。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;<strong>(2)数据滤波部分</strong></p>

<p align="center"> &nbsp;</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;骑行时压力传感器由于轮胎转动到不同的位置、路面颠簸、急加减速等因素,会产生部分误差数据。采用滑动平均法,对一段时间窗口内的数据进行平均,从而减少噪声或波动,使数据更加平滑。</p>

<p>&nbsp;</p>

<p><span style="font-size:20px;"><b>四、作品源码</b></span></p>

<p>&nbsp;</p>

<p><a href="https://download.eeworld.com.cn/detail/Newhor/635010">自行车智能骑行助手&mdash;&mdash;作品源码-嵌入式开发相关资料下载-EEWORLD下载中心</a></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;系统的硬件部分软件使用 micropython 进行开发,采用异步多任务形式。部分源码如下:</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;文件:task_TFTshow.py</p>

<pre>
<code class="language-python">import asyncio
from machine import Pin, SoftSPI
from time import sleep_ms
from global_var import *
from cfg import *


async def TFTshow():
    while True:
      if gv.int_flag == 1:
#             pass
            lcd.clear(0)
            lcd.rotate(180)
            lcd.drawText('系统初始化中'+str(gv.int_cnt*10)+'%',0,50,font,0x0f0)
            lcd.drawText('请在10S内推动自',0,70,font,0xff0)
            lcd.drawText('行车采集初始数据',0,90,font,0xff0)
            lcd.show()
      elif gv.str_flag == 1 or 2 or 3:
            lcd.clear(0)
            lcd.rotate(180)
            lcd.drawText('温度:'+str(round(gv.tmp,1))+'°',0,0,font,0x0f0)
            lcd.drawText('湿度:'+str(round(gv.hum,1))+'%',0,20,font,0xff0)
            lcd.drawText('气压:'+str(round(gv.pre,1))+'Pa',0,40,font,0x00f)
            lcd.drawText('IAQ:'+str(gv.IAQ)+gv.iaq_leve,0,60,font,0xff0)         
            lcd.show()
            await asyncio.sleep(2)
            
            ifgv.weight_int !=0:
                lcd.clear(0)
                lcd.rotate(180)
                lcd.drawText('初始胎压psi:',0,0,font,0x00f)
                lcd.drawText('前:'+str(gv.P1_int)+'后:'+str(gv.P2_int),0,20,font,0x00f)
                lcd.drawText('初始体重:'+str(gv.weight_int)+'kg',0,40,font,0x0f0)               
                lcd.drawText('实时体重:'+str(gv.weight)+'kg',0,60,font,0x0f0)               
#               lcd.drawText('体重差值:'+str(gv.weight_int-gv.weight)+'kg',0,80,font,0x00f)
                lcd.drawText('运动时长:'+str(round(gv.SportTime/60+0.7,1))+'min',0,100,font,0x00f)
                lcd.show()
                await asyncio.sleep(2)
                gv.SportTime+=2
            gv.SportTime+=2.1
      if gv.end_flag ==1:#运动结束
            lcd.clear(0)
            lcd.rotate(180)
            lcd.drawText('运动已结束',0,0,font,0x0f0)
            lcd.drawText('该次运动时长为',0,50,font,0xff0)
            lcd.drawText(str(round(gv.SportTime/60,1))+'min',0,70,font,0xff0)
            lcd.drawText('该次运动减重;',0,90,font,0xff0)
            lcd.drawText(str(gv.weight_int-gv.weightmin)+'kg',0,110,font,0xff0)
            lcd.show()
            import machine
            machine.reset()
      await asyncio.sleep(0.1)
# asyncio.run(TFTshow())
</code></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;文件:task_ESPnow.py</p>

<pre>
<code class="language-python">import network
import aioespnow
import asyncio
import neopixel
import binascii,time
from machine import Pin
from neopixel import NeoPixel
from time import localtime
from global_var import *
from cfg import *

np = neopixel.NeoPixel(Pin(8), 1)

# WLAN接口必须处于活动状态才能 send()/recv()
sta = network.WLAN(network.STA_IF) # 或 network.AP_IF
sta.active(True)
sta.disconnect() # 对于 ESP8266

e = aioespnow.AIOESPNow()
e.active(True)

peer = b'\xAA\xBB\xCC\xDD\xEE\xFF' # 配对设备wifi接口的MAC地址
e.add_peer(peer) # 发送前必须 add_peer()
# e.send(peer, '123')

def Pcvt1(x):
    if x&gt;=0 and x&lt;0.76:
      return 35
    if x&gt;=0.76 and x&lt;0.92:
      return 25
    if x&gt;=0.92 and x&lt;1.0:
      return 30
    if x&gt;=1.0 and x&lt;1.08:
      return 35
    if x&gt;=1.08 and x&lt;1.3:
      return 40
    if x&gt;=1.3 and x&lt;1.4:
      return 45
    if x&gt;=1.4:
      return 50
   
   
def Pcvt2(x):
    if x&gt;=0 and x&lt;1.12:
      return 20
    if x&gt;=1.12 and x&lt;1.19:
      return 25
    if x&gt;=1.19 and x&lt;1.24:
      return 30
    if x&gt;=1.24 and x&lt;1.26:
      return 35
    if x&gt;=1.26 and x&lt;1.28:
      return 40
    if x&gt;=1.28 and x&lt;1.32:
      return 45
    if x&gt;=1.32:
      return 50



def P_Vdata_int(r):#   初始电压平均
    global v1,v2,m,n
    print('接收的r字节数据为:',r,type(r))
    if r == 49:
      gv.V1 = float(r.decode('utf-8'))
      print('转换后的整数数据为V1:',gv.V1)
      v1 = gv.V1+v1
      n=n+1
      gv.Vint1 = round(v1/n,3)
      print('gv.Vint1',gv.Vint1 )
    elif r == 50:
      gv.V2 = float(r.decode('utf-8'))
      print('转换后的整数数据为V2:',gv.V2)
      v2 = gv.V2+v2
      m=m+1
      gv.Vint2 = round(v2/m,3)
      print('gv.Vint2',gv.Vint2)
      
def P_Vdata(x):#取峰值
    global r
    gv.st_cnt+=1
    if gv.st_cnt&lt;=x:
      if r == 49:
            gv.V1 = float(r.decode('utf-8'))
      elif r == 50:
            gv.V2 = float(r.decode('utf-8'))
      if gv.V1 &gt; gv.V1max:
            gv.V1max = gv.V1
      if gv.V2 &gt; gv.V2max:
            gv.V2max = gv.V2
    else:
      gv.st_cnt = 0
      gv.V = gv.V1+gv.V2-gv.Vint1-gv.Vint2
      print('========gv.V:',gv.V)
      gv.weight = WGTcvt(gv.V)
      if gv.weight&lt;gv.weightmin:
            gv.weightmin = gv.weight
   

def WGTcvt(y):
    if y&gt;0.1:
      t = 57+y*12
    elif y&lt; 0.1 and y &gt;0.05:
      t = 57+y*21
    elif y &lt;0.05 and y&gt;0.01:
      t = 57+y*31
    elif y &lt;0.01:
      t = 57+y*61
    print('^^^^^^^^^t',t)
    return t
   

async def e_recv():
    global r
    while True:
      if e.any():
            host, msg = e.recv()
            if len(msg)&gt;=5 and len(msg)&lt;=15:
                if msg[:2] == b'cc':
                  print('msg',msg)
                  np = (0, 30, 0)
                  np.write()   
                  gv.int_cnt +=1
                  print('gv.int_cnt',gv.int_cnt)
                  if gv.int_cnt &lt;= 10:#初始化时间10S
                        #gv.int_flag = 1
                        P_Vdata_int(msg)
                        print('gv.int_flag :',gv.int_flag)
                  elif gv.int_cnt&gt;10 and gv.str_flag ==0:
                        gv.int_flag = 0
                        gv.str_flag = 1
                        print('gv.str_flag:',gv.str_flag)
                  else:
                        pass
                  
                        
                        
                  if gv.str_flag == 1:#初始化结束,胎压转换
                        gv.P1_int = Pcvt1(gv.Vint1)
                        print('gv.P1_int',gv.P1_int)
                        gv.P2_int = Pcvt2(gv.Vint2)
                        print('gv.P2_int',gv.P2_int)
                        gv.str_flag = 2
                        print('gv.str_flag :',gv.str_flag)
                  
                  if gv.str_flag == 2:#开始测量初始体重
                        print('---------------gv.str_flag :',gv.str_flag)
                        gv.waitcnt+=1
                        if gv.waitcnt&gt;=100:
                            r = msg
                            P_Vdata(10)#取50次数据的峰值
                            if gv.weight&gt;0 and gv.st_cnt ==0:
                              gv.weight_int = gv.weight
                              print('gv.weight_int',gv.weight_int)
                              gv.weight = 0
                              gv.str_flag = 3
                  if gv.str_flag == 3:#开始测量运动后体重
                        print('```````````gv.str_flag:',gv.str_flag)
                        r = msg
                        P_Vdata(20)#每100次数据更新一次体重

                  r = localtime()
                  s = '{:04}-{:02}-{:02} {:02}:{:02}:{:02} &gt; {}'.format(r, r, r, r, r, r, str(msg))
                  f = open('称重数据1.txt', "a", encoding="UTF-8")
                  f.write( s+'\n')
                  f.close()
                  
                  await asyncio.sleep(0.05)
                  np = (0, 0, 0)
                  np.write()
                else:
                  print('msg head error')
            else:
                print(' msg len error')
      else:
            print('等待数据,请在5秒内启动车辆')
            gv.endcnt+=1
            if gv.endcnt&gt;=100:#(5秒内未收到数据,运动结束)
                gv.endcnt = 0
                gv.end_flag = 1

      await asyncio.sleep(0.05)

# asyncio.run(e_recv())

</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:20px;"><b>五、</b><b>作品功能演示视频</b></span></p>

<p><a href="https://www.bilibili.com/video/BV1hLBSY8E14/">自行车智能骑行助手&mdash;&mdash;得捷大赛作品演示视频_哔哩哔哩_bilibili</a></p>

<p>7cc8994b5fdfb34a822f81dc96acf77b<br />
&nbsp;</p>

<p><span style="font-size:20px;"><b>六、项目总结</b></span></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;参加这次活动之前,刚好买了一辆自行车,加入了骑行者的队伍,然后计划购买一些配件来改装车辆,和同事讨论时,想到胎压测量以及骑行时的体重监测等场景,在市面上没有找到类似功能的产品,所以想尝试做一下这个功能的作品,看看是否能够实现预期的效果。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;此次作品将最初想法能大致实现了,可以完成测量胎压和体重等功能,但由于各方面的限制,数据精度上但是还有很多不足,例如传感器精度不足以及线性度不够、安装位置无法保证受力均衡、轮胎的自然转动带来的数据波动,都会影响最后得到的数据精度。由于时间关系,还有运动数据上传到手机功能暂未实现,这个后续再添加。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;通过参加本次活动,收获还是不小的,真真切切的感受到了从一个想法到一个作品做好的难度,需要考虑的东西太多了,做到一半才发现很多东西与预想的差别很大,可能写程序、画板子还是其中最容易的环节,例如此次作品中,一个合适的传感器的选择和安装固定的方式,在前期就花了很多时间。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;最后,感谢得捷和EEworld,组织了这次活动,让大家的想法可以有个很好的机会来实现,并且能学习到很多其他人的有趣想法。</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><a href="https://bbs.eeworld.com.cn/thread-1290206-1-1.html">【2024 DigiKey 创意大赛】物料开箱帖 - DigiKey得捷技术专区 - 电子工程世界-论坛</a></p>

<p><a href="https://bbs.eeworld.com.cn/forum.php?mod=viewthread&amp;tid=1299906&amp;page=1&amp;extra=#pid3376376">【2024 DigiKey 创意大赛】自行车智能骑行助手 - DigiKey得捷技术专区 - 电子工程世界-论坛</a></p>

<p>&nbsp;</p>

<div></div>

<p><a href="https://gitee.com/newhor/zhinengqixing.git" target="_blank">https://gitee.com/newhor/zhinengqixing.git</a></p>

<p>&nbsp;</p>

chejm 发表于 2024-11-25 20:10

<p>楼主分享的技术知识非常有实用价值,值得收藏学习借鉴</p>

秦天qintian0303 发表于 2024-11-26 12:17

<p>这压力检测直接放进去了?不漏气吗?&nbsp;&nbsp;</p>

wangerxian 发表于 2024-11-26 18:47

秦天qintian0303 发表于 2024-11-26 12:17
这压力检测直接放进去了?不漏气吗?&nbsp;&nbsp;

<p>可能传感器是夹在内胎和外胎之间</p>

Newhor 发表于 2024-11-26 21:30

wangerxian 发表于 2024-11-26 18:47
可能传感器是夹在内胎和外胎之间

<p>先将轮胎气放光,然后夹在钢圈和内胎之间,然后再充气固定的 &nbsp;</p>

wangerxian 发表于 2024-11-27 09:02

Newhor 发表于 2024-11-26 21:30
先将轮胎气放光,然后夹在钢圈和内胎之间,然后再充气固定的 &nbsp;

<p>原来如此,这样确实也能检测胎压,不过在骑行的过程压力会变化吧</p>

Newhor 发表于 2024-11-27 09:30

wangerxian 发表于 2024-11-27 09:02
原来如此,这样确实也能检测胎压,不过在骑行的过程压力会变化吧

<p>分为了两个阶段,初始未骑行的状态的测量值转换为胎压,骑行中的值转换为体重,用了一些算法对进行骑行时的数据进行滤波处理</p>

wangerxian 发表于 2024-11-27 13:22

Newhor 发表于 2024-11-27 09:30
分为了两个阶段,初始未骑行的状态的测量值转换为胎压,骑行中的值转换为体重,用了一些算法对进行骑行时 ...

<p>明白了,还能变相的称体重,想法确实很好。</p>
页: [1]
查看完整版本: 【2024 DigiKey 创意大赛】自行车智能骑行助手