【2024 DigiKey创意大赛】+ 用于车速估算的空速表制作
本帖最后由 顺竿爬 于 2024-10-13 13:31 编辑<p><strong>一、作品简介</strong></p>
<p>2SMPP03是一款气压计,这款气压计在外接空速管的基础上,可以作为空速计来使用。一般此类应用都会被应用在航模上,而我想到这种用法其实在汽车工业上也可以大有作为。<br />
汽车在隧道等GPS信号不佳的地方行驶时,对于里程和位置的估计,只能依靠转速表,陀螺仪,加速度计等传感器进行测量。这些传感器都有一个共同的问题,就是测不准,会受到其他因素干扰:比如里程表会受到胎压影响,惯性传感器会受到路面情况干扰等。因此需要多个传感器参与,使用不同的方法来测量,并将数据通过算法进行融合,以此减少误差。增加空速计,可以增加另一个观测速度及速度变化的途径,因此我们可以在极低成本的情况下,增加速度及位置估计的准确度。</p>
<p> </p>
<p>整个项目的硬件部分展示:</p>
<p> </p>
<p><strong>二、系统框图</strong></p>
<p></p>
<p>整个项目我使用购买的2SMPP03模组与自己设计的电路板制作出空速计模块,用ESP32-C6-DEVKITC-1-N8上的ADC外设读取空速计读数,并经过计算转换为车速,最后再通过串口输出至使用树莓派zero2w制作的车载电脑,完成车速的图形化显示。</p>
<p> </p>
<p><strong>三、各部分功能说明</strong></p>
<p>首先是硬件制作。2SMPP03空速计由于是最基础的电阻网络结构,因此还需要不少模拟电路外设才可以正常工作。</p>
<p><img src="https://bbs.eeworld.com.cn/data/attachment/forum/202408/20/233529q8eo0o04clemth68.png" /></p>
<p>外设电路设计一共需要三个运放。首先是仪表放大器,需要把2SMPP03输出的差分电压进行放大:</p>
<p> </p>
<p>电阻R8的作用是用来调节放大倍数。</p>
<p> </p>
<p>另外还需要一个电压跟随器,用来给仪表放大器提供参考电压。参考电压我设置为1/2*vcc,这样可以做到正负压双向测量。</p>
<p>最后一个运放是用来做一个恒流源,给2SMPP03提供恒流供电。这两个运放我使用一个双运放来完成。</p>
<p> </p>
<p> </p>
<p>在2SMPP03电源回路上也接一个变阻器,用来调整恒流值大小:</p>
<p> </p>
<p>这样电路原理图部分设计就完成了,绘制成电路板如下:</p>
<p> </p>
<p> </p>
<p>下面开始写ESP32-C6-DEVKITC-1-N8上的代码。代码读取ADC数据,进行计算后通过串口发送出去。这里主要需要注意的是计算方法。</p>
<p>首先根据2SMPP03规格书,可以找到电阻与气压的关系:</p>
<p> </p>
<p> </p>
<p>通过调整横流电阻,把电流调整到100uA,就可以得到上面的线性关系。</p>
<p>接着再通过调整仪表放大器的放大倍率,来使得输出电压匹配ESP32-C6-DEVKITC-1-N8的ADC量程范围。</p>
<p>最后我们找到风压与风速的关系:</p>
<p>wp = 0.5*r*(v^2)*1000/g</p>
<p>其中wp是风压,r是空气重度,g是重力加速度,v是风速。调整一下公式,就可以得到风速的计算公式:</p>
<p>v = (wp / 1000 / (0.5 * r / g))^0.5</p>
<p>使用这个公式,就可以完成代码编写:</p>
<pre>
<code class="language-cpp">void setup() {
Serial.begin(115200);
}
void loop() {
unsigned int sensorValue = analogRead(4);
if (sensorValue < 920) {
sensorValue = 920;
} else if (sensorValue > 1500) {
sensorValue = 1500;
}
unsigned int pressure = map(sensorValue, 920, 1500, 0, 390);
float volecity = sqrt((float)pressure / 1000 / (0.5 * 0.01225 / 9.8));
// print the results to the Serial Monitor:
// Serial.print("sensor = ");
Serial.println(volecity);
// wait 2 milliseconds before the next loop for the analog-to-digital
// converter to settle after the last reading:
delay(100);
}
</code></pre>
<p> </p>
<p>按照设计焊接好电路板:</p>
<p> </p>
<p> </p>
<p>我使用的是4号引脚,属于ADC1外设。因此接线时注意把信号线接到4号脚上</p>
<p></p>
<p> </p>
<p>最后是树莓派上位机的图形化显示源码。使用python自带的库就可以完成全部设计。</p>
<pre>
<code class="language-python">import tkinter as tk
from tkinter import Canvas
import serial
import math
root = tk.Tk()
root.title("SPEED")
ser = serial.Serial("/dev/ttyUSB0", 115200, timeout=1)
canvas = Canvas(root, width=400, height=400)
canvas.pack()
canvas.create_arc(
50, 50, 350, 350, start=225, extent=-270, outline="lightgrey", width=10
)
for i in range(0, 26, 5):
angle = 225 - (i / 25) * 270
x = 200 + 140 * math.cos(math.radians(angle))
y = 200 - 140 * math.sin(math.radians(angle))
canvas.create_text(x, y, text=str(i), font=("Arial", 10))
needle_length = 100
needle = canvas.create_line(200, 200, 200, 100, fill="red", width=3)
def update_gauge(speed):
angle = 225 - (speed / 25) * 270
x = 200 + needle_length * math.cos(math.radians(angle))
y = 200 - needle_length * math.sin(math.radians(angle))
canvas.coords(needle, 200, 200, x, y)
def read_serial():
try:
line = ser.readline().decode("utf-8").strip()
if line:
speed = float(line)
if 0 <= speed <= 25:
update_gauge(speed)
except Exception as e:
print(f"Error reading serial: {e}")
root.after(50, read_serial)
read_serial()
root.mainloop()
</code></pre>
<p> </p>
<p>将C6和树莓派的TX/RX交叉连接,并连接地线后,在树莓派上运行程序,最终显示效果如下:</p>
<p> </p>
<p><strong>四、作品源码</strong></p>
<div>PCB设计文件:</div>
<div>ESP32-C6-DEVKITC-1-N8代码:</div>
<div>树莓派zero2W代码:</div>
<p> </p>
<p><strong>五、作品功能演示视频</strong></p>
<p>d61646c707991c0dc81986c572f8ac1a<br />
</p>
<p><strong>六、项目总结</strong></p>
<p>项目的所有代码及设计文件均已在上面上传,所有的细节都写在本文中,下面附上word版的项目报告。</p>
<div></div>
<p> </p>
页:
[1]