1、选题
《基于无线传感网的智能灌溉系统的研究与设计》
两个关键词:
1)无线传感网:具有感知、处理和无线通信能力的微型节点构成的网络
2)智能灌溉系统:其智能体现在,这个系统可以通过一定的编程,处理环境信息和人工指令,并基于信息处理结果,来控制是否灌溉、何时灌溉、灌溉水量等。
1)什么是智能灌溉系统?简单介绍
智能灌溉系统是一种基于物联网和传感器的自动化灌溉解决方案,通过传感器实时采集环境参数,结合数据与远程控制技术,监控灌溉
智能灌溉系统,其智能体现在,这个系统可以通过一定的编程,处理环境信息和人工指令,并基于信息处理结果,来控制是否灌溉、何时灌溉、灌溉水量等。
2)为什么要选这个题目?
1、具有现实意义,农业灌溉效率低、水资源浪费严重
2、符合专业毕业设计要求
2、简单介绍项目
以MSP430F149 芯片为核心,集成风速、风向及土壤 PH 值传感器,通过内置/外置 A/D 转换模块处理信号,结合 ESP8266 WiFi 模块实现环境数据远程传输至手机端,并利用 OLED 屏实时显示监测信息。
3、项目流程
1)分析项目
分析项目:要完成这个毕业设计,其核心就是一个可以集成多种传感器、并处理传感器信号的芯片。同时芯片还要具有控制电信号的能力,以达到“智能灌溉”的控制灌溉的目的,即输出一个水阀控制信号。
2)确定系统大致流程需要主芯片,几个传感器,液晶P显示OLED

芯片工作电压是3.3V,设计时用电脑USB接口供电。不同的模块需要接的电源也不一样。风速风向传感器接15V的电源适配器,Wifi模块和液晶显示模块接3.3V电源,PH值传感器模块接5V电源,A/D模块接入5V电源。
a.主芯片
主芯片选择:
本科生完成这个项目,只是一种实验研究,不需要拿出具体的可商用成品,因此技术选型上:
- 芯片应当具有较成熟的生态,要能兼容通用传感器
- 采购物料时,要能购买到该芯片的开发板,以有助于完成毕业设计
- 芯片应当避开STM32这种大众化的芯片,以避开查重
为什么没有用stm32芯片?
芯片选用MSP430,这是德州仪器的一款16位单片机芯片。相比于STM32,这个芯片的优势在于,16位芯片的功耗要更低。并且16位芯片的性能实现选题中所需要的功能已经足够了。
MSP430F149劣势?
当然劣势就是这个芯片在国内的资料较少,如果需要学习,最好的途径是直接打开德州仪器的官网,搜索MSP430F149,下载用户指南。
打开:https://www.ti.com.cn/zh-cn/microcontrollers-mcus-processors/msp430-microcontrollers/products.html
然后在这里筛选型号

MSP430F149常识

省去了我们引出IO口和AD电源的工作,可以通过USB下载程序。并且有一个标准 JTAG 接口(14 针), 支持硬件仿真。
tips-01-USB串口用途
USB可以下载程序是因为开发板的厂家在板子上集成了一块BSL。这样连接到电脑就可以被识别为一个CH340的COM串口。
但如果我们要通过串口通信,此时USB默认被BSL占用,无法将其他设备通过USB与芯片进行串口通信,我们就需要跳线来使用串口功能:

(一)ADC12 - AD转换模块(模数转换)
ADC12是MSP430芯片自带的模数转换模块,有8个引脚,芯片内部编号为A0-A7,可以读取8个电压信号。
外部端口为P6,引脚为P60-P67。
代码操作P6SEL寄存器。寄存器8位二进制,每一位操作对应的引脚开关。0/低位为关,1/高位为引脚使能。
代码实现:
定义:
定义缓冲区数组,AdBuff[4]
AdBuff 是一个 long 类型(4 个元素) 的数组,在 ADC 采样代码中,它用于存储 ADC 采样值(即电压值) 和 控制采样等待逻辑。
long AdBuff[4]; // 用于存储 ADC 采样数据
其中AdBuff[3]用来存放当前读取的电压值,每次读取都会被更新。
AdBuff[0] ~ AdBuff[2]用来存放对应的引脚的电压结果。
定义函数:
定义unsigned long SysAdDetect(uchar ch)
用来读取ADC12模块对应通道的数字信号,即电压值,避免重复代码
把电压值存入AdBuff数组对应的位置,如P60引脚电压值存入AdBuff[0],单位是mV毫伏,long整型。
P6SEL寄存器操作代码解析:
P6SEL |= (0x01<<ch);
P6SEL的值的变化控制了引脚启用,当P6SEL的第x位为高电平时,表示P6.x引脚生效,此时ADC12模块的存储寄存器中读取的就是该引脚(P6.x)的电压。
存储寄存器名称:ADC12MEM0
unsigned long SysAdDetect(uchar ch)
{
P6SEL = 0;
AdBuff[3] = 0;
AdBuff[ch] = 0;
P6SEL |= (0x01<<ch); // 使能ADC通道
ADC12CTL0 = ADC12ON + SHT0_8 + MSC; // 打开ADC,设置采样时间
ADC12CTL1 = SHP+CONSEQ_2; // 使用采样定时器
ADC12IE = 0x01; // 使能ADC中断
ADC12CTL0 |= ENC; // 使能转换
ADC12CTL0 |= ADC12SC; // 开始转换
_EINT();
while((AdBuff[3]==0)&&(AdBuff[ch]<=10000))
{
AdBuff[ch]++;
}
if(AdBuff[ch]>=10000)
{
AdBuff[ch]=0xFFFFFFFF;
}
else
{
AdBuff[ch]=AdBuff[3];
}
P6SEL =0;
ADC12CTL0 &=~(ADC12ON+SHT0_8+MSC); // 打开ADC,设置采样时间
ADC12CTL1 &=~(SHP+CONSEQ_2); // 使用采样定时器
ADC12IE &=~0x01; // 使能ADC中断
ADC12CTL0 &=~ ENC; // 使能转换
ADC12CTL0 &=~ADC12SC; // 开始转换
_DINT();
}
b.模块与传感器选型
ESP8266
ESP8266是一种集成了 Wi-Fi 功能的低成本无线通信模块,主要用于实现设备的网络连接和数据传输。其核心功能是通过 Wi-Fi 协议与互联网或局域网通信,支持 TCP/IP 协议栈,能够将传感器数据上传至云端或手机端,或接收远程指令,从而实现物联网(IoT)应用的无线控制与监控。
为什么不能直接在 MSP430 开发板上使用 Wi-Fi 模块?
- 硬件资源限制:
MSP430 是超低功耗微控制器,设计重点在于低能耗而非复杂通信。其外设接口(如 UART、SPI)和内存资源有限,可能无法直接驱动高带宽或协议复杂的 Wi-Fi 模块。ESP8266 需要稳定的串口通信(UART)和协议解析能力,而 MSP430 的实时处理能力可能不足。 - 协议栈与软件支持:
Wi-Fi 模块需运行完整的网络协议栈(如 TCP/IP、HTTP),而 MSP430 的存储空间(Flash/RAM)较小,难以承载复杂的网络协议和数据处理代码。ESP8266 内置协议栈,可通过 AT 指令简化控制,但仍需主控芯片具备较强的指令解析能力。 - 电源与功耗:
ESP8266 在通信时功耗较高(峰值电流可达 200mA+),而 MSP430 通常用于低功耗场景(如电池供电)。直接连接可能导致电源不稳定或超出开发板的供电能力。 - 接口兼容性:
ESP8266 默认通过 UART 通信,需占用 MSP430 的串口资源。若开发板未预留足够接口,或未配置电平转换电路(如 3.3V-5V),可能导致通信失败。
解决方案:
若需在 MSP430 上使用 Wi-Fi 功能,可通过以下方式实现:
- 模块化设计:将 ESP8266 作为独立通信单元,通过 UART 与 MSP430 交互,仅传输关键数据。
- 简化协议:使用 AT 指令控制 ESP8266,减少 MSP430 的协议处理负担。
- 电源管理:为 ESP8266 提供独立电源或优化供电电路,避免影响主控稳定性。
- 软硬件优化:选择低功耗模式(如 ESP8266 的 Deep Sleep)并优化代码,平衡功能与能耗。
通过合理设计,MSP430 与 ESP8266 可以协同工作,但需在资源分配、功耗控制和通信协议上进行针对性优化。
原理
ESP8266的三种工作方式
AP模式(热点模式)- ESP8266 模块作为热点,手机wifi设置里可以搜到
STA模式(基站模式)- ESP8266 模块作为客户端,通过串口控制指令连接手机热点/其他wifi
AP和STA共存模式(不考虑)
AT指令设置ESP8266模式
前期工作:将ESP8266-01模块与“串口转USB工具”连接好,连接电路图下图所示,多检查几次注意线是否接好。
我们用了5条线进行连接,要注意,ESP8266的CH_PD引脚一定要接3.3V高电平,否则模块不能工作!
例1-模块在AP模式下做TCP Server,也就是ESP8266当做热点,并成为一个TCP Server让别人来加入。
在串口调试助手上依次输入以下AT指令,要注意选择发送新行(否则有可能发什么在串口工具上返回什么),串口波特率默认为115200, 当模块在AP模块下做TCP Server时,默认的IP 为 192.168.4.1, 端口可自己设定为 8899(默认为 333),通过手机网络调试助手设置ip地址和端口号,分别进行接收和发送数据,如下面几幅图所示。
通过控制字(即通过两根串口引脚发送特定的数据),来配置ESP8266。
配置好后,模块和手机通过TCP协议通信,发送文本。
AT //测试模块正常工作
AT+CWMODE=2 //设置AP模式
AT+CWSAP="ESP8266Test","13141516",11,0 //设置AP名称和密码,设置后在手机端可以搜到
AT+CIPMUX=1 //设置多连接
AT+CIPSERVER=1,8899 //设置端口号,这个端口号在手机网络调试助手上要用到。
AT+CIPSTART="TCP","192.168.1.115",8899 // 设置IP地址和端口
AT+CIPSEND=0,10 //发送10个字节数据
手机操作:
首先连刚才在ESP8266上配置的热点:

连上以后打开TCP客户端软件,应用商店下的,一般叫网络助手之类的名字。
手机启动TCP客户端,连接刚才在ESP8266里配置的TCP服务端。填写IP地址和端口,连接后就可以发送和接收数据。

此处遇到的困难
初始化串口、设置波特率
解决方案:找厂商要资料,要样例,和特定的波特率,然后根据样例不断调整
PCF8591
为什么要使用PCF8591芯片连PH值传感器
PCF8591是外置A/D转换模块
1、资源优化:解决MSP430F149内置ADC(模数转换)通道或资源不足的问题
2、简化系统减少自定义电路设计复杂度,有可扩展性,为未来升级提供硬件冗余。
3、高精度要求:PH值的微小变化(如±0.1)可能对作物生长产生显著影响,其他传感器(如风速传感器)可能对精度要求较低或直接输出数字信号。且成本低
风速传感器
电流型输出信号转换计算
量程030m/s,420mA输出,当输出信号12mA时,计算当前风速。风速量程的跨度为30m/s,用16mA电流信号来表达,30m/s/16mA=1.875m/s/mA,即电流变化1mA风速变化1.875m/s.那么可以计算测量值测量值12mA-4mA=8mA.8mA*1.875m/s/mA=15m/s,则当前的风速=15m/s.
电压型输出信号转换计算
量程0~30m/s,以0-10V输出为例,当输出信号为5V时,计算当前风速。风速量程的跨度为30m/s,用10V电压信号来表达,30m/s/10V=3m/s/V,即电压每变化1V对应风速变化3m/s.测量值5V-0V=5V。5V*3/m/s/V=15m/s。则当前风速为15m/s。
风向传感器
量程0~360,以0-10V输出为例,当输出信号为5V时,计算当前风向。风向量程的跨度为360,用10V电压信号来表达,360/10V=36/V,即电压每变化1V对应风向变化36度.测量值5V-0V=5V。5V*36/V=180度。则当前风向为180度。
3)确定硬件电路设计,设计引脚,接线
先确定引脚,一次接几个引脚,然后写部分代码
一共有:风速传感器模块、风向传感器模块、PH值传感器模块、外置独立A/D模块、wifi模块、液晶显示模块
4)用IAR编写芯片代码
开发框架
该单片机使用较多的编程环境有IAR和CCS。
CCS是TI自己推出的开发编译环境,然而大学中IAR用的比较多,所以选择IAR。
IAR和C的区别:IAR很多写法和C语言不一样,有些输入输出引脚需要查表,学习新api,在while循环里通过iar提供的api,编写引脚判断条件
如何编写程序的
定义常量,定义管脚(SCL和SDA)高低电平——SCL(时钟信号)和SDA(数据信号),在 I2C 总线上,主设备通过控制这两个信号线来实现对从设备的控制和通信。
I2C 通信:设置I2C(串行总线,半双工通信方式)相关函数(起始、终止、有无应答,发送数据,读写数据)
****串口通信:初始化串口、发送串口数据(UART串口用于数据传输)
ADC采集:包含读取ADC转换值、读取PCF8591传感器数值
OLED****:在 OLED 屏幕 指定位置显示字符串信息。
wifi:
通过 ESP8266 WiFi 模块,将 风速、风向、PH 值 发送到 手机端 或 服务器
- 通过 UART0 向 PC 或 ESP8266 发送字符串数据
- 通过 UART1 向 WiFi 模块 发送数据。
主函数:
初始化 系统时钟、串口、OLED
循环定期读取传感器的传来的数字信号的值,调用ADC函数处理数字信号的值,读取值映射,调用oled和ESP8266函数,将结果展示在OLED 显示屏 ,并通过wifi模块实现无线传输
进入 <font style="color:#000000;">while</font> 循环,定期采集风速、风向、PH 值,并通过 OLED 显示 + 串口发送。
5)仿真与调试
4、难点:
1)对于OLED屏幕显示的问题
当时厂家给的OLED屏幕教程只涉及数字和英文字母,有一个困难点就是如何显示中文
通过自己上网搜索,问厂家,然后他们推荐了一个PCTOLCD2002,可以取字模,那我需要的就是把我所要涉及到的所有的汉字取字模,把中文字模放到oled的头文件里面
主函数调用oled显示屏幕的时候,又遇到问题,就是字有重影,还是中间有条线切割,倒着的。然后又是各种找资料发现本质上oled的显示字符的原理是用点亮点阵的来实现的,那么字符重影的问题就是相邻字的间距太小了,于是去主函数调整字符间距,并且在取字模的时候,需要设置取模走向和取模方式,比如我每个字的空间是8*16,那我第一个字符位置0~8,第二个字符位置就从10~18,然后解决了这个问题
收获就是,学习的过程就是边实践,在实践中遇到问题再去解决问题,才能真学会,学了一些嵌入式开发的知识
2)对于PCF8591的读取字节过程。 如何设置外置的A/D转换模块
/********************************************************************
函数名称:read1byte
功 能:从I2C总线读取一个字节
参 数:无
返回值 :读取的数据
********************************************************************/
uchar read1byte(void)
{
uchar ReadData = 0x00,i;
uchar flag;
for(i = 0;i < 8;i++)
{
SDA_H;
delay_us(5);
SCL_H;
SDA_IN;
delay_us(5);
flag = SDA_VAL;//菜端起来
ReadData <<= 1;//转桌子
if(flag) ReadData |= 0x01;//放菜
SDA_OUT;
SCL_L;
delay_us(5);
}
return ReadData;
}
读取一个字节时
PCF8591按位发送,MSP430按位接收

3)OLED如何平衡传感器读取和屏幕刷新的问题
**一开始,为了在OLED上显示传感器值变化的内容****,**设置一个buton值(0表示有信号输入,1表示没信号输入 ),初始置1(西风),后面判断,如果有信号输入,button置0(东风),刷新屏幕,此时出现问题,只有在第一次有信号变化时,屏幕会刷新。后面每次信号变化都不再刷新,值不再变化;
**分析原因****:**虽然外层while(1)一直在循环,一直在读取信号,但是由于上述程序是覆盖信号,覆盖只有第一次有效
设想情况:1、读一次传感器刷新一次(问题:不管输入信号变没变,都一直刷新,刷新次数太多,屏幕不停地闪)
2、设置delay,读一次等一秒再刷(不能根本解决问题,屏幕还会闪,显示屏幕delay会影响输入信号,程序在执行耗时动作在等,不会响应其他信号)
**最后尝试取非做法****:**在while(1)函数最外层定义previousbutton这个前次状态变量,默认置1(西风),在循环函数内部,判断传感器信号是否发生改变的条件为,本次接收的变量button是是否和前次状态previousbutton相同,若不同,说明输入信号发生改变,再去刷新屏幕,这样减少了屏幕刷新次数
5、总结项目成败,如何优化
成功点:1、OLED和手机上确实显示了数据,达到目标
2、自己代码能力有所提升,了解了这些芯片和器件
3、学习的过程
优化点:1、把灌溉系统做成可自主配置的,可以多接入一些传感器,检测哪些参数由管理者自主调节控制
2、可以接水泵,通过算法检测控制浇水
3、可以通过软件结合Ai给一些浇灌合理建议