Python拟合SHARP红外测距传感器相关数据

最近网络环境一般化,一直安装不了Python相关的库。今天下午突然就人品爆棚,几次失败后终于成功安装了相关库:


小楊是在线安装的,命令如下:

python -m pip install --user numpy scipy matplotlib ipython jupyter pandas sympy nose

安装完Python后想起了前两天想拟合SHARP的GP2Y0A21YK0F红外测距传感器输出信号与距离的曲线关系,所以,动手咯!
前两天的文档可以先阅览一下,好理解下面的正文。相关文档链接如下:

1、数据采集并绘制曲线:


实测数据绘制图形与数据手册对比
代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize

x=np.arange(0,81,5)
y=np.array([0,3.1, 2.25, 1.62, 1.32, 1.13,0.91,0.79, 0.75, 0.68,0.62, 0.57,0.55, 0.49, 0.43,0.41,0.40])
plt.plot(x,y)
plt.show()

观察发现在传感器的有效测距范围10-80cm内,曲线与反比例函数接近。

2、拟合曲线
接下来截取有效测距范围内的数据,通过Python的scipy库中optimize提供的一个专门用于曲线拟合的函数curve_fit()进行曲线拟合:

得到:

a = 15.231176863349042
b = 0.35759398578213786

代码如下:

#构建函数y=a*(1/x)+b
#使用optimize.curve_fit函数求出a、b的值

import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize

def f_x(x, a, b):
    return a*(1/x)+b

plt.figure()

#拟合点
x=np.arange(5,81,5)
y=np.array([3.1, 2.25, 1.62, 1.32, 1.13,0.91,0.79, 0.75, 0.68,0.62, 0.57,0.55, 0.49, 0.43,0.41,0.40])

#绘制散点
plt.scatter(x[:], y[:], 30, "red")

#直线拟合与绘制
a, b = optimize.curve_fit(f_x, x, y)[0]
print(a)
print(b)
y1 = a*(1/x)+b
plt.plot(x, y1, "blue")


plt.title("HeGuang Studios")
plt.xlabel('X:cm')
plt.ylabel('Y:v')

plt.show()

通过上以上数据得到y与x关系如下:
y = 15.231176863349042/x + 0.35759398578213786;

3、拟合结果验证:
结合单片机验证拟合结果是否可行:


代码如下:

// Visual Micro is in vMicro>General>Tutorial Mode
// 
/*
    Name:       CeShi.ino
    Created:    2018/8/13 21:03:35
    Author:     禾灮\HeGuang
*/
void setup() {
  Serial.begin(9600);
  pinMode(14,INPUT);
  delay(45);
}

void loop() {
  float val = 5*analogRead(14)/1024.0;  
  long i = 1/((val - 0.35759398578213786)/15.231176863349042);
  Serial.print("Y(v):"); 
  Serial.println(val);
  Serial.print("X(cm):"); 
  Serial.println(i);
  Serial.println("*******************");  
  delay(5000);
}

数据还是有误差的,曲线拟合图中就可以看出。

4、改进完善


代码如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize

x=np.arange(0,81,5)
y=np.array([0,3.1, 2.25, 1.62, 1.32, 1.13,0.91,0.79, 0.75, 0.68,0.62, 0.57,0.55, 0.49, 0.43,0.41,0.40])
plt.plot(x,y)

#构建函数y=a*(1/x)+b+c*x
#使用optimize.curve_fit函数求出a、b、c的值

def f_x(x, a, b, c):
    return a*(1/x)+b+c*x

plt.figure()

#拟合点
x=np.arange(5,81,5)
y=np.array([3.1, 2.25, 1.62, 1.32, 1.13,0.91,0.79, 0.75, 0.68,0.62, 0.57,0.55, 0.49, 0.43,0.41,0.40])

#绘制散点
plt.scatter(x[:], y[:], 30, "red")

#直线拟合与绘制
a, b, c = optimize.curve_fit(f_x, x, y)[0]
print(a)
print(b)
print(c)
y1 = a*(1/x)+b+c*x
plt.plot(x, y1, "blue")


plt.title("HeGuang Studios")
plt.xlabel('X:cm')
plt.ylabel('Y:v')

plt.show()

得到:

a = 11.95996602305133
b = 0.8757100690367675
c = -0.00893829688786056


单片机实测结果:(这次能准确很多了)

代码如下:

void loop() {
    float y = 5.0*analogRead(14)/1024.0;
    float a = 11.95996602305133;
    float b = 0.8757100690367675;
    float c = -0.00893829688786056; 
    float D = pow((y - b),2)-4*a*c; 
    //float x1 = ((y - b) + sqrt(D))/(2*c);
    float x2 =((y - b) - sqrt(D))/(2*c);
    Serial.print("Y(v):"); 
    Serial.println(y);
    //Serial.print("X1(cm):"); 
    //Serial.println(x1);
    Serial.print("X(cm):"); 
    Serial.println(x2);
    Serial.println("*******************");  
    delay(5000);
}

感谢一直关注着禾灮成长进步的朋友们。你们的信任、支持和鼓励,鞭策着我们一路走到了今天。

感谢所有的合作伙伴,我们相互促进,共同见证了彼此的成长。

感谢所有曾经在禾灮彼此倚靠、相互鼓励、携手同心、砥砺同行的兄弟姐妹。这里承载了我们的青春与热血。

            禾灮,感谢有你。

未来,我们将一如既往,砥砺前行。

                                    禾灮·小楊
                                   2018.08.13

猜你喜欢

转载自blog.csdn.net/HeGuang68207/article/details/81814649