900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【物联网毕设】基于Arduino与树莓派的智能鱼缸【二】

【物联网毕设】基于Arduino与树莓派的智能鱼缸【二】

时间:2021-10-17 17:23:08

相关推荐

【物联网毕设】基于Arduino与树莓派的智能鱼缸【二】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

前言一、Arduino与树莓派进行通信二、树莓派把数据上传到服务器1.在树莓派上用Django搭建服务器2.在树莓派上搭建MySQL数据库3.树莓派把数据post到服务器上三、微信小程序通过服务器获取数据库的值总结

前言

本文主要讲的是智能鱼缸树莓派部分,也是我的毕业设计我认为最棘手的部分。

一、Arduino与树莓派进行通信

看过我上一篇文章的小伙伴们应该知道,现在我们已经实现了Arduino读取传感器的值,那我们怎么将它传给树莓派呢?(注:如果你手里是一块全新的树莓派,需要安装镜像源,实现远程访问等准备工作,推荐B站树莓派教程:/video/BV1bt411c7fC?share_source=copy_web只看前四节课就完全ok)

参考链接:树莓派与Arduino通信

在跟着这个帖子成功实现简单的通讯后(我用的是USB通讯),接下来要做的就是把我的Arduino里接收到的传感器的数据传给树莓派了。

上代码!

在Arduino IDE里写入下面这段代码,覆盖我上一篇文章里Arduino IDE上的代码(此代码在之前的基础上加入了Arduino向树莓派传数据的部分):

Arduino代码:

#include <OneWire.h>#include <DallasTemperature.h>#define tempPin 2// 温度传感器数据输出脚接开发板数字引脚2#define waterpower 7 //水位传感器VCC引脚#define waterpin A0 //水位传感器输出引脚#define oxygenpin A1//溶解氧传感器输出引脚OneWire oneWire(tempPin);DallasTemperature sensors(&oneWire);int temp_relaypin=3;//温度传感器继电器1引脚为3int waterup_relaypin=4;//水位传感器继电器引脚为4int waterdown_relaypin=5;//水位传感器继电器引脚为5int oxygen_relaypin=9;//溶解氧传感器继电器引脚为9float temperature;int oxygen;int water_level;int val=0;int incomedate = 0;void setup(void){Serial.begin(9600);//连接到电脑串口监视器sensors.begin();pinMode(temp_relaypin,OUTPUT);//设置继电器1为输出模式pinMode(tempPin,OUTPUT);//温度传感器输出模式pinMode(waterup_relaypin,OUTPUT);//继电器输出模式pinMode(waterdown_relaypin,OUTPUT);//继电器输出模式pinMode(waterpower,OUTPUT);//将水位传感器VCC引脚设置成输出模式pinMode(oxygen_relaypin,OUTPUT);//溶解氧继电器4输出模式 digitalWrite(waterpower,LOW);//先将水位传感器VCC引脚关闭}int readwatersensor(){digitalWrite(waterpower,HIGH);//将水位传感器VCC电源打开给传感器供电delay(10);val=analogRead(waterpin);//读取水位传感器A0引脚的值digitalWrite(waterpower,LOW);//将水位传感器电源关闭return val;//返回val值}void loop(void){//温度sensors.requestTemperatures(); // 发送命令获取温度temperature=sensors.getTempCByIndex(0);//溶解氧int analog=analogRead(A1);//读取模拟输入值oxygen=map(analog,0,1023,0,10);//将模拟输入0~1023等比映射到0mg/L~10mg/LanalogWrite(9,oxygen);//水位int level=readwatersensor();//让level=valwater_level=readwatersensor();//让water_level=valif(Serial.available()){incomedate = Serial.read();//获取串口接收到的数据if (incomedate == 't'){Serial.println(temperature); //向树莓派发送信息}else if (incomedate == 'w'){Serial.println(water_level); //向树莓派发送信息}else if (incomedate == 'o'){Serial.println(oxygen); //向树莓派发送信息}}//继电器控制加热棒if(temperature<25)//如果温度小于25度{digitalWrite(temp_relaypin, HIGH);//继电器1开,加热棒开}else{digitalWrite(temp_relaypin,LOW); //继电器1关,加热棒关; }delay(500);//继电器控制水泵if(water_level<550)//如果水位在传感器1CM之下{digitalWrite(waterup_relaypin, HIGH);//继电器2开,放水水泵开}else{if(water_level>640){digitalWrite(waterdown_relaypin, HIGH);//继电器3开,抽水水泵开}else{digitalWrite(waterup_relaypin, LOW);//继电器2关digitalWrite(waterdown_relaypin, LOW);//继电器3关}}//继电器控制增氧泵if(oxygen<5){digitalWrite(oxygen_relaypin, HIGH);//继电器4开,充氧泵开}else{digitalWrite(oxygen_relaypin, LOW);//继电器4关,充氧泵开}delay(500);}

在树莓派上新建一个post.py文件,写入:

树莓派代码:

import RPi.GPIO as GPIOimport serialimport timeimport json,requestsimport datetimeser = serial.Serial('/dev/ttyUSB0', 9600,timeout=1); #open named port at 9600,1s timeot#try and exceptstructure are exception handlerwhile 1:for i in range(2):send='t';ser.write(send.encode());#wrt a string to porttime.sleep(2);temperature = ser.readline().decode();#read a string from portprint(temperature);send='w';ser.write(send.encode());#wrt a string to porttime.sleep(2);water_level= ser.readline().decode();#read a string from portprint(water_level);send='o';ser.write(send.encode());#wrt a string to porttime.sleep(2);oxygen = ser.readline().decode();#read a string from portprint(oxygen);

注意树莓派代码第六行里的:/dev/ttyUSB0,还有人是/dev/ttyACM0,要知道你的是什么,把树莓派和Arduino用USB连接后,在树莓派终端输入: ls /dev/tty*查看两者连接端口的名字,多出哪个就是哪个。

for i in range(2): 的意思是让树莓派打印两次,因为经过实验,发现第一个值一直打不出来,咱也不知道为什么,硬件有时候就是玄学,所以就让这段代码循环两次,让树莓派和Arduino之间实现稳定的传值。

提醒一下之后post.py里还要写入一部分代码,也就是说目前上面的这段树莓派里的代码只是一部分,所以你试验的时候,可能会出现多余的头文件,然后树莓派的IDE报错,没事,暂时把没有用到的头文件注释掉就好了,后面会用得着的(我可真是太贴心了)。

运行结果:

注意这里是后期要放在论文里的截图,特意把第一个没有打出来的temperature盖住了(怕老师问我我答不上来),然后让程序循环了五次。

二、树莓派把数据上传到服务器

现在我们的树莓派已经得到了从Arduino上传过来的传感器数据了。接下来就是把数据上传到服务器,通过服务器写入到数据库了。首先,我们得有一个基于树莓派的服务器。其次,我们树莓派上得有一个MySQL数据库。然后,我们要把服务器和数据库连接起来。最后,把树莓派上的数据post到服务器。接下来我一部分一部分的细说。

参考链接:/weixin_52079689/article/details/109383872?spm=1001..3001.5506

1.在树莓派上用Django搭建服务器

参考链接:/damanchen/article/details/85224686

跟着这个链接,我们可以在树莓派上下载好Django。需要注意的是,你的树莓派要有python,我的3B里python默认的是python2。为了之后方便操作,我需要将python2换成python3,这个视情况而定,你不一定非得改。如果你也想改,推荐链接:/ylzmm/article/details/107827065

好的。现在我们的树莓派上已经有Django了,可以正式开始创建一个服务器了。

输入:

django-admin.py startproject fish_tank2#生成网站cd fish_tank2 python manage.py startapp index2#生成app

创建好后的截图:

配置功能:

需要说明以下我的项目名都是fish_tank,app都叫index。上面的项目和app是我为了演示新建的。名字会有变化。

fish_tank/setting

这里是有关树莓派数据库的,要加这两句代码。

import pymysqlpymysql.install_as_MySQLdb()

[’*’]是为了让同一局域网下面不同ip都可以访问该服务器。

这是连接数据库。后面会讲到树莓派上搭建数据库,这里就是将数据库与服务器连接起来的代码。

fish_tank/urls.py

from django.conf.urls import urlfrom django.urls import path, includeurlpatterns = [#path('admin/', admin.site.urls),url(r'^sensor/', include('index.urls')),]

fish_tank/index/admin.py

from django.contrib import admin# Register your models here.from .models import *class SensorAdmin(admin.ModelAdmin):list_display = ('id', 'time', 'temperature','water_level','oxygen')admin.site.register(Sensors, SensorAdmin)

fish_tank/index/app.py

from django.apps import AppConfigclass IndexConfig(AppConfig):default_auto_field = 'django.db.models.BigAutoField'name = 'index'

fish_tank/index/models.py

from django.db import models# Create your models here.class Sensors(models.Model):time = models.DateTimeField(auto_now_add=False)temperature = models.CharField(max_length=10)water_level= models.CharField(max_length=10)oxygen = models.CharField(max_length=10)def __str__(self):return self.time

fish_tank/index/serializers.py(没有的文件就右键新建)

from rest_framework import serializersfrom index.models import Sensorsclass SensorSerializer(serializers.ModelSerializer):class Meta:model = Sensorsfields = ['time', 'temperature','water_level','oxygen']

fish_tank/index/urls.py

from django.conf.urls import urlfrom index import viewsurlpatterns = [url(r'^post', views.Sensors_api.as_view(),name='sensor.Sensors_api'),url(r'^get', views.SensorView.as_view(),name='sensor.Sensors_api'),]

这里新建了两个网址,post用来接收树莓派上传的数据,得到的是所有的数据;get用来显示最新的数据,因为我们只需要当前的数据。为什么要写成两个网址呢?是因为post用的接口和get不一样,get用的那个接口可以显示最新值,但是post的那个接口我没有找到如何显示最新的值的方法,所以就写了两个网址,一个用来接收数据,一个用来显示最新数据到服务器上,后续小程序也方便get到最新数据。

fish_tank/index/views.py

from rest_framework.response import Responsefrom rest_framework.views import APIViewfrom index.models import Sensorsfrom index.serializers import SensorSerializerfrom rest_framework import generics# Create your views here.class Sensors_api(generics.ListCreateAPIView):#queryset = Sensors.objects.last()queryset = Sensors.objects.all()serializer_class = SensorSerializerclass SensorView(APIView):def get(self, request, *args, **kwargs):sensor = Sensors.objects.last()obj = SensorSerializer(sensor)return Response(obj.data)

这里就可以看出来,我post用的是ListCreateAPIView这个接口,get用的是APIView这个接口。

到此,树莓派上成功搭建起了一个web服务器。

2.在树莓派上搭建MySQL数据库

在树莓派上设置安装MySQL,设置用户名密码,推荐链接:点我

注意这里设置的用户名密码要和setting里连接的一样。

建议在pc端下载Navicate,连接树莓派上的数据库,这样有了图形化界面,建表看着也舒心。

然后执行给数据库建表的两句代码:

参考链接:点我

python manage.py makemigrationspython manage.py migrate

Navicate与树莓派数据库连接成功:

到此,数据库和服务器全都创建成功,并且进行了连接。

3.树莓派把数据post到服务器上

在刚才树莓派post.py后面加上此代码:

# Post Data to webpagerqs_headers={'Content-Type': 'application/json'}requrl ='http://192.168.43.121:8000/sensor/post/'new_data = {"time": datetime.datetime.now(),"temperature": temperature,"water_level": water_level,"oxygen": oxygen}class ComplexEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, datetime.datetime):return obj.strftime('%Y-%m-%d %H:%M:%S')elif isinstance(obj, datetime.date):return obj.strftime('%Y-%m-%d')else:return json.JSONEncoder.default(self, obj)test_data = json.dumps(new_data, cls=ComplexEncoder)response = requests.post(url=requrl, headers=rqs_headers, data=test_data)time.sleep(50);

运行服务器:

记得要先进入项目的文件夹在文件夹在运行哦

运行:

python manage.py runserver 0.0.0.0:8000

在浏览器上输入:192.168.43.121:8000/sensor/post/和192.168.43.121:8000/sensor/get/

192.168.43.121是我树莓派的ip地址,你们输网址的时候要改成自己的ip地址。

运行post.py文件,可以看到post页面获取到了所有的值,get页面获取到了最新值,Navicat中可以看到数据库里更新了值。

post页面:

get页面:

Navicat连接数据库页面:

如果你不想手动点击post.py,而是想让它自动每60秒执行一次,可以:

sudo -icrontab -e */1 * * * * python /home/pi/Desktop/post.py #把这个命令加到最后一行,我设定的是每分钟运行一次,用的时候把注释去掉就好了。sudo /etc/init.d/cron restart

这个时候post.py里的while 1 就可以去掉了。我把自动执行的放到post2.py里,手动执行的放在post.py里,手动的方便调试,自动的最后使用。

至此,由arduino获取传感器数值,并传给树莓派,树莓派上传到服务器,通过服务器写入到数据库就完成了。

三、微信小程序通过服务器获取数据库的值

最后一步!!终于快写完了!!

我们要开发一个微信小程序,让小程序通过服务器获取到传感器的数值。

微信小程序课程推荐的B站链接:

下载微信开发者工具

注册账号,获取到appid

其实不用做那么复杂,只需要改两段代码,其他的默认就行:

index.wxml

<!--index.wxml--><view class="container"><view class="userinfo"><block wx:if="{{canIUseOpenData}}"><view class="userinfo-avatar" bindtap="bindViewTap"><open-data type="userAvatarUrl"></open-data></view><open-data type="userNickName"></open-data></block><button type="primary" bindtap="get_message">获取传感器数值</button><view>时间:{{message.time}}</view><view>温度:{{message.temperature}}</view><view>水位:{{message.water_level}}</view><view>溶解氧:{{message.oxygen}}</view><view>加热棒:{{message.temperature >25 ? '关': '开'}}</view><view>充氧泵:{{message.oxygen >5 ? '关': '开'}}</view><view>加水水泵:{{message.water_level <550 ? '开': '关'}}</view><view>抽水水泵:{{message.water_level >640 ? '开': '关'}}</view></view></view>

这里只加了一个按钮

index.js

// index.js// 获取应用实例const app = getApp()Page({data: {message:[],motto: 'Hello World',userInfo: {},hasUserInfo: false,canIUse: wx.canIUse('button.open-type.getUserInfo'),canIUseGetUserProfile: false,canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false},// 事件处理函数bindViewTap() {wx.navigateTo({url: '../logs/logs'})},onLoad() {if (wx.getUserProfile) {this.setData({canIUseGetUserProfile: true})}},getUserProfile(e) {// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗wx.getUserProfile({desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写success: (res) => {console.log(res)this.setData({userInfo: res.userInfo,hasUserInfo: true})}})},getUserInfo(e) {// 不推荐使用getUserInfo获取用户信息,预计自4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息console.log(e)this.setData({userInfo: e.detail.userInfo,hasUserInfo: true})},get_message(){var that = this;wx.request({url: 'http://192.168.43.121:8000/sensor/get',success(data){console.log(data.data)that.setData({message:data.data})}})},})

这里get数据。

在手机上运行的结果:(我点击按钮会出来传感器数值)

总结

终于写完了,最后再整体捋一遍

1、arduino获取传感器数值

2、arduino与树莓派进行通讯,树莓派获取传感器数值

3、树莓派将数值上传到服务器上,通过服务器写入数据库,服务器用Django写,然后与树莓派上数据库进行连接。

4、微信小程序通过服务器获取数据库值。

我去歇一会儿。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。