【玄铁杯第三届RISC-V应用创新大赛】华山派老人跌倒智能识别报警装置的完成+汇总贴
[复制链接]
本帖最后由 eew_dy9f48 于 2023-11-3 09:27 编辑
huashan
本期是最后一期,将完成整个项目。前几期的帖子汇总如下:
【玄铁杯第三届RISC-V应用创新大赛】华山派开箱,硬件介绍与固件烧录
【玄铁杯第三届RISC-V应用创新大赛】华山派开发环境配置
【玄铁杯第三届RISC-V应用创新大赛】华山派外设接入,I2C与GPIO,蜂鸣器的使用,连接网络与接入邮件stmp服务
这一期,我们把上一期的内容连起来。首先,来到/mnt/data目录下,我们创建一个init.sh文件,用来做外设的初始化配置:
echo 470 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio470/direction
i2cset -y 3 0x68 0x6B 0x80
sleep 1
i2cget -y 3 0x68 0x75
i2cset -y 3 0x68 0x6B 0x00
sleep 1
i2cset -y 3 0x68 0x19 0x07
i2cset -y 3 0x68 0x1A 0x06
i2cset -y 3 0x68 0x1B 0x18
i2cset -y 3 0x68 0x1C 0x01
exit 0
上面的代码里,我们先初始化了GPIO,用来驱动蜂鸣器,接着初始化了MPU6050
接着,我们把初始化脚本添加进上次创建好的auto.sh文件中,文件中我添加了一些别的功能,比如上次提到的有线网卡MAC会变,我们把它固定下来,并检测网络连接。整个auto.sh文件的代码如下:
ifconfig eth0 down
ifconfig eth0 hw ether C2:2B:54:DA:BC:1B
ifconfig eth0 up
insmod /mnt/system/ko/3rd/8723ds.ko
ifconfig wlan0 up
/mnt/data/WiFi/wpa_supplicant -i wlan0 -Dnl80211 -c /mnt/data/WiFi/wpa_supplicant.conf &
udhcpc -b -i wlan0 -R &
/mnt/data/init.sh
function network()
{
ping -w 1 www.baidu.com > /dev/null
}
network
while [ $? -eq 1 ];
do
echo "网络不畅通,请检查网络设置!"
sleep 1
network
done
echo "网络畅通,你可以上网冲浪!"
echo $(ifconfig)
exit 0
这些都做好后,接好外设重启板子,完成后,就可以正式进入主程序的开发。
首先,先按照上个项目中的描述的,定义好我们发邮件和读取传感器数据相关的函数:
ip="smtp.qq.com 587"
user="email in Base64"
pass="app pwd in Base64"
sender="xxx@qq.com"
receiver="xxx@qq.com"
subject="HELP"
content="Please help me! Call xxxxxxxx"
mail(){
{
sleep 1
echo "helo test"
sleep 1
echo "auth login"
sleep 1
echo "$user"
sleep 1
echo "$pass"
sleep 1
echo "mail from:<$sender>"
sleep 1
echo "rcpt to:<$receiver>"
sleep 1
echo "data"
sleep 1
echo "from: $sender"
echo "to: $receiver"
echo "subject: $subject"
echo ""
echo "$content"
echo "."
sleep 1
echo "quit"
sleep 1
}|telnet $ip >> /tmp/mail.log
}
get_value(){
let "val=$(i2cget -y 3 0x68 $1)<<8|$(i2cget -y 3 0x68 $(echo "obase=16; $(($1+0x01))" | bc))"
if [ $val -gt 32767 ];
then
val=$(( $val - 65536 ))
fi
echo $val
}
echo "Initialized"
完成后,我们就可以编写主循环。先讲一下逻辑,我们站在地球上,无论什么姿势,我们都承受了一个G的重力加速度,指向地心。而传感器上的加速度计读到的数据是xyz轴三个方向的重力加速度。这里我们要清楚,这三个数字是向量而非标量,正负号代表的是方向。那么我们就可以很容易的算出三者的和向量,那么这个向量一定是永远指向地心,且大小为1G.
那么如果这个传感器装在人身上,如果人突然摔倒,那么势必会出现加速度的向量和先是突然小于1G,因为摔倒过程中是一个落体运动,运动加速度方向与地心方向有相同的分量。接下来人接触到地面,加速度向量和又会突然大于1G,因为此使原有速度突然变为0,将出现一个巨大的反向加速度。因此代码中我们只需要读取加速度计三轴的值,并计算出相应的向量和,检测这个向量和的变化,就可以知道人是否出现跌倒。
首先先在每次循环中读取传感器的读数:
ax=`get_value 0x3B`
ay=`get_value 0x3D`
az=`get_value 0x3F`
ax=$(echo "scale=2; $ax/16384" | bc)
ay=$(echo "scale=2; $ay/16384" | bc)
az=$(echo "scale=2; $az/16384" | bc)
ashock=$(echo "scale=2; sqrt(($ax*$ax)+($ay*$ay)+($az*$az))" | bc)
echo "$ashock"
接着,我们需要模拟一下跌倒的场景,然后让我们看看到底加速度变化的大小是多少,我们应该把阈值设置在哪里。先简单的把板子固定在盒子上:
接着运行上述循环,模拟摔倒时的样子,观察数据如何变化:
仔细观察输出的数据,我们可以看到数据的变化模式与预计的差不多:
根据多次尝试,我们可以把阈值设置在1.5G,这样平时走路时不会误触发,跌倒时也可以精准报警。
那么最后,我们需要完成程序主循环部分。原理很简单,循环检测加速度和向量,当大小超过1.5时进行报警,并发邮件。
while [ TRUE ]
do
ax=`get_value 0x3B`
ay=`get_value 0x3D`
az=`get_value 0x3F`
ax=$(echo "scale=2; $ax/16384" | bc)
ay=$(echo "scale=2; $ay/16384" | bc)
az=$(echo "scale=2; $az/16384" | bc)
#gx=`get_value 0x43`
#gy=`get_value 0x45`
#gz=`get_value 0x47`
#gx=$(echo "scale=2; $gx/16.4" | bc)
#gy=$(echo "scale=2; $gy/16.4" | bc)
#gz=$(echo "scale=2; $gz/16.4" | bc)
#temp=`get_value 0x41`
#temp=$(echo "scale=2; ($temp/340)+36.53" | bc)
ashock=$(echo "scale=2; sqrt(($ax*$ax)+($ay*$ay)+($az*$az))" | bc)
#gshock=$(echo "scale=2; sqrt(($gx*$gx)+($gy*$gy)+($gz*$gz))" | bc)
#echo "ax: $ax"
#echo "ay: $ay"
#echo "az: $az"
#echo "gx: $gx"
#echo "gy: $gy"
#echo "gz: $gz"
#echo "temp: $temp"
#echo "$ashock"
#echo "$gshock"
if [ `echo "$ashock > 1.5"|bc` -eq 1 ];
then
echo "TUMBLE DETECTED!!!"
echo 1 > /sys/class/gpio/gpio470/value
mail
echo "Email Sent"
else
echo 0 > /sys/class/gpio/gpio470/value
fi
done
完整代码放在了附件中,感兴趣的同学可以自行下载。
|