1. 前言
许多人喜欢在家里、办公室等地方养鱼,以缓解学习、生活、工作带来的压力,提高生活质量。为了节省鱼友的时间、劳动力,增加养鱼的乐趣;为此,本文基于STM32单片机设计了智能鱼缸。鱼缸可实现水温检测、水质检测、自动或手动换水、大气照明变换、自动或手动喂食等功能的控制系统,可通过控制键一键控制。
(1)STM32系统板
(3)水质检测传感器: 测量水中溶解固体的含量,反应水质。
(4)步进电机: 作为鱼饲料投食器
(5)RGB氛围灯: 采用RGB 三色灯,照明鱼缸。
(6)抽水电动电机: 用于鱼缸充氧、换水、加水等。
水产养殖水质常规检测的传感器有哪些?水产养殖水质常规检测的传感器有水质ph传感器、溶解氧传感器和温度传感器。
(1)水质ph传感器: ph传感器是一种由传感器和二次表组成的高智能在线连续监。可配备三复合或两复合电极,以满足各种使用场所。配备纯水和超纯水电极,电导率小于3μs/cm水质(如化学补给水、饱和蒸汽、凝结水等)pH值测量。
(2)溶解氧传感器: 氧气的消耗量与存在的氧含量成正比,而氧是通过可透膜扩散进来的。传感器与专门设计的监测溶氧的测量电路或电脑数据采集系统相连。 溶解氧传感器可用于空气校准。一般校准需要很长时间。使用后应注意维护。如果在养殖水中工作时间过长,必须定期清洗膜并进行额外维护。 在许多水产养殖中,溶解氧可以通过每天测量几次来理解。对于池塘和许多水槽养殖系统。溶解氧水平不会迅速变化,池塘一般每天检测2~3次。 对于高密度养殖系统,增氧泵故障可能不到1h会导致鱼虾等大面积死亡。这些高密度养殖系统需要足够的设备或每小时多次自动测量溶氧。
(3)温度传感器: 温度传感器有多种结构,包括热电偶、电阻温度传感器和热敏电阻。热电偶技术成熟,应用广泛,供应充足。热电偶的选择必须满足温度范围要求,其材料与环境兼容。 电阻温度传感器(RTDs)其原理是金属电阻随温度而变化。大多数电阻温度传感器(RTDs)由铂、镍或镍合金制成,其线性比热电偶好,热切更稳定,但容易破碎。 热敏电阻是电阻与温度负相关的半导体。热敏电阻比RTD热电偶更敏感,更容易破碎,不能承受大温差,但这在水产养殖中不是问题。
2. 硬件选型
2.1 STM32开发板
主控CPU采用STM32F103RCT6.这个芯片包括48 KB SRAM、256 KB Flash、2个基本定时器,4个通用定时器,2个高级定时器,51个通用定时器IO五串口,两串口DMA控制器、3个SPI、2个I2C、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口,芯片容量大,配置高,整体符合硬件选型设计。目前选择的开发板有一个1.4寸的TFT-LCD可显示当前传感器数据和一些运行状态信息的彩屏。
2.2 杜邦线
2.3 PCB板
2.4 步进电机
2.5 抽水马达
2.6 水温检测传感器
测温采用DS18B20,DS18B20是一种常用的数字温度传感器,输出数字信号,体积小,硬件成本低,抗干扰能力强,精度高。
DS18B20数字温度传感器接线方便,包装后可应用于管道、螺纹、磁铁吸附、不锈钢包装、各种型号LTM8877,LTM8874等等。
主要根据应用场合的不同而改变其外观。封装后的DS18B20可用于各种非极限温度场合,如电缆沟测温、高炉水循环测温、锅炉测温、机房测温、农业温室测温、洁净室测温、弹药库测温等。耐磨耐碰,体积小,使用方便,包装形式多样,适用于各种狭小空间设备的数字测温和控制。
2.7 水质检测传感器
TDS (Total Dissolved Solids)、中文称为总溶解固体,又称溶解固体,又称总溶解固体,表明1升水肿容量为毫克溶解固体,一般来说,TDS值越高、表示水中含有溶解物越多、水就越不洁净、虽然在特定情况下TDS它不能有效地反映水质,但作为一速检测的参数,TDS也可作为水质反映参数的有效参数。常用的TDS检测设备为TDS笔,虽然价格低,使用简单,但不能将数据传输到控制系统,长期在线监线监测,进行水质状况分析,使用特殊仪器,虽然可以传输数据,精度高,但价格很贵,为此TDS传感器模块、即插即用、使用简单方便、测量激励源采用交流信号,可有效防止探头极化,延长探头寿命,增加输出信号的稳定性TDS探头为防水探头,可长期入水测量。本产品可用于生活用水、水培等领域的水质检测。有了这个传感器,它很容易DIY–套TDS探测器,轻松检测水的清洁度。
温度校正系数T校正计算公式如下:T修正=1 0.02*(T-25>T位是温度校正系数,T测量溶液的温度。
注:
(1)TDS 有时也使用测量单位mg/L表示,与ppm 转换关系为1mgL=1ppm;
(2)TDS 通常与电导率有相通的关系,有时TDS也可用于表示电导率,两者之间的关系: 1ppm =2uS/cm,中 uS/am电导率单位。
(3)国家标准GB5749-2006《生活饮用水卫生标准》规定饮用自来水TDS 有限要求:溶解总固体=1000ppm
校准方法 由于TDS探头的个体差异或温度补偿不足会导致测量值误差较大。因此,为了获得更准确的TDS 测量前必须校准值。此外,建议连接温度传感器进行温度补偿,以提高测量精度。具体操作方法如下。
第一步: 连接TDS探针和温度传感器; 第二步: 记录标准TDS 溶液或用TDS测量待测溶液的笔TDS值,记录为TDS标i准值o 第三步: 给TDS将传感器模块供电TDS 放入探针和温度传感器TDS标准溶液或已知 TDS在待测溶液中,测试传感器模块AO口输出电压值记录为V测量s。测量当前测试溶液的值记录T T将测量电压值V 测量和T测试代入TDS计算标准曲线公式和温度校正系数。
3. STM32程序设计
3.1 硬件连线
硬件连接方式: 1. TFT 1.44 寸彩屏接线 GND 电源地 VCC 接5V或3.3v电源 SCL 接PC8(SCL) SDA 接PC9(SDA) RST 接PC10 DC 接PB7 CS 接PB8 BL 接PB11 2. 板载LED灯接线 LED1---PA8 LED2---PD2 3. 板载按键接线 K0---PA0 K1---PC5 K2---PA15 4. DS18B20温度传感器接线 DQ->PC6 : 3.3V - : GND 5. 步进电机 ULN003控制28BYJ-48步进电机接线:
ULN2003接线:
IN-D: PB15 d
IN-C: PB14 c
IN-B: PB13 b
IN-A: PB12 a
+ : 5V
- : GND
6. 抽水电机
GND---GND
VCC---5V
AO----PA4
7. 水质检测传感器
AO->PA1
+ : 3.3V
- : GND
8. RGB灯
PC13--R
PC14--G
PC15--B
3.2 硬件原理图
3.3 汉字取模
3.3 程序下载
下载软件在资料包里。点击开始编程之后,点击开发板的复位键即可下载程序进去。
3.4 mian.c代码
需要完整代码和资料包的可以去这里下载:https://download.csdn.net/download/xiaolong1126626497/85896081
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "oled.h"
#include <string.h>
#include <stdlib.h>
#include "font.h"
#include "motor.h"
#include "ds18b20.h"
#include "rtc.h"
#include "adc.h"
/* */
/* 函数功能: 更新时间框架显示,在RTC中断里调用 */
char TimeBuff[20];
void Update_FrameShow(void)
{
//绘制电子钟时间
Gui_DrawFont_GBK16(0,0,RED,0,(u8*)" ");
sprintf(TimeBuff,"%d/%d/%d %d:%d:%d",rtc_clock.year,rtc_clock.mon,rtc_clock.day,rtc_clock.hour,rtc_clock.min,rtc_clock.sec);
Gui_DrawFont_GBK16(0,0,RED,0,(u8*)TimeBuff);
}
//JTAG模式设置,用于设置JTAG的模式
//mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
#define JTAG_SWD_DISABLE 0X02
#define SWD_ENABLE 0X01
#define JTAG_SWD_ENABLE 0X00
void JTAG_Set(u8 mode)
{
u32 temp;
temp=mode;
temp<<=25;
RCC->APB2ENR|=1<<0; //开启辅助时钟
AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]
AFIO->MAPR|=temp; //设置jtag模式
}
u16 DS18B20_data=0; //加热芯的温度
u16 DS18B20_temp;
char data_buff[100];
u16 adc_data=0; //水质检测
int main1()
{
USART1_Init(115200); //串口1初始化-打印调试信息
Moto_Init(); //步进电机初始化
while(1)
{
Motorcw_ring(1,300); //电机正转1圈
delay_ms(5000);
printf("电机转动...\r\n");
}
}
int main()
{
u8 key=0;
u32 time_cnt=0;
u32 time_rgb=0;
u32 time1=0; //定时换水
u32 time2=0; //定时投喂食物
JTAG_Set(JTAG_SWD_DISABLE); //释放PA15
LED_Init(); //LED灯初始化
KEY_Init(); //按键初始化
USART1_Init(115200); //串口1初始化-打印调试信息
Lcd_Init(); //LCD初始化
Lcd_Clear(0); //清屏为黑色
LCD_LED_SET; //通过IO控制背光亮
DS18B20_Init(); //DA18B20温度传感器
Moto_Init(); //步进电机初始化
AdcInit(); //水质传感器
printf("DS18B20检测:%d\r\n",DS18B20_Check());
//实时水温显示
LCD_ShowChineseFont(0,16*2,16,HZ_FONT_16[0],RED,0);
LCD_ShowChineseFont(16,16*2,16,HZ_FONT_16[1],RED,0);
LCD_ShowChineseFont(16*2,16*2,16,HZ_FONT_16[2],RED,0);
LCD_ShowChineseFont(16*3,16*2,16,HZ_FONT_16[3],RED,0);
//实时水质显示
LCD_ShowChineseFont(0,16*3,16,HZ_FONT_16[4],RED,0);
LCD_ShowChineseFont(16,16*3,16,HZ_FONT_16[5],RED,0);
LCD_ShowChineseFont(16*2,16*3,16,HZ_FONT_16[6],RED,0);
LCD_ShowChineseFont(16*3,16*3,16,HZ_FONT_16[7],RED,0);
printf("正在初始化RTC实时时钟.\r\n");
// RTC_Init();//RTC初始化,一定要初始化成功
while(1)
{
//按键可以手动控制开启窗帘和LED灯
key=KEY_Scan();
if(key)
{
printf("key=%d\r\n",key);
}
//手动投喂食物
if(key==2)
{
printf("手动投喂食物.\r\n");
LED2=0;
Motorcw_ring(1,300); //电机正转1圈
LED2=1;
}
//手动换水
if(key==1)
{
printf("手动换水.\r\n");
//抽水3秒
MOTOR=1;
delay_ms(3000);
MOTOR=0;
}
//轮询时间到达
if(time_cnt>200)
{
time_cnt=0;
LED1=!LED1;
//读取加热芯温度
DS18B20_temp=DS18B20_Read_Temp();
printf("水温:%d.%d\r\n",DS18B20_temp>>4,DS18B20_temp&0xF);
sprintf(data_buff,"%d.%d",DS18B20_temp>>4,DS18B20_temp&0xF);
//LCD屏实时显示
Gui_DrawFont_GBK16(72,16*2,RED,0,(u8*)" ");
Gui_DrawFont_GBK16(72,16*2,RED,0,(u8*)data_buff);
//水质检测
adc_data=GetAdcCHxDATA(1);
sprintf(data_buff,"%d",adc_data);
printf("水质质量:%s\r\n",data_buff);
Gui_DrawFont_GBK16(72,16*3,RED,0,(u8*)" ");
Gui_DrawFont_GBK16(72,16*3,RED,0,(u8*)data_buff);
}
DelayMs(10);
time_cnt++;
time2++;
time1++;
time_rgb++;
if(time_rgb>=100 && time_rgb<=200)
{
printf("模式1\r\n");
RGB_R=1;
RGB_G=0;
RGB_B=0;
}
else if(time_rgb>=200 && time_rgb<=300)
{
printf("模式2\r\n");
RGB_R=0;
RGB_G=1;
RGB_B=0;
}
else if(time_rgb>=300 && time_rgb<=400)
{
printf("模式3\r\n");
RGB_R=0;
RGB_G=0;
RGB_B=1;
}
else if(time_rgb>=400)
{
time_rgb=0;
}
//定时投喂食物
//5个小时投喂一次
if(time2>100*60*60*5)
{
time2=0;
Motorcw_ring(1,300); //电机正转1圈
}
//定时换水,2天换一次水
if(time1>100*60*60*24*2)
{
time1=0;
MOTOR=1;
delay_ms(3000);
MOTOR=0;
}
}
}