之前分享了液体流量检测DIY项目的开箱贴,今天带大家看看实际制作的过程。从点亮OLED屏幕,到实现流量检测和抽水泵控制,这些环节都是项目的核心。以下是我的实践步骤和心得,希望对同样喜欢DIY的小伙伴有所帮助。
### **一、点亮OLED显示屏 (SSD1305)**
#### **1. 硬件连接**
OLED 显示屏 SSD1305 支持 I2C 和 SPI 接口,我选择了 I2C 接口来简化布线,连接如下:
* **VCC** → STM32 NUCLEO 的 3.3V
* **GND** → STM32 NUCLEO 的 GND
* **SCL** → STM32 的 PB8
* **SDA** → STM32 的 PB9
#### **2. 通信原理**
I2C 是一种主从通信协议,STM32 开发板作为主机,OLED 显示屏作为从机。通过 STM32 的 `HAL_I2C` 驱动库,可以发送命令和数据来控制 OLED。
* **命令模式** :用来配置显示屏的工作状态,比如初始化、设置对比度等。
* **数据模式** :用来刷新显示内容。
#### **3. 编程实现**
在 STM32CubeMX 中,配置 I2C1,并生成代码框架。然后添加以下逻辑:
**初始化 SSD1305 的程序** :
uint8_t ssd1306_Init(I2C_HandleTypeDef *hi2c) { // Wait for the screen to boot HAL_Delay(100); int status = 0; // Init LCD status += ssd1306_WriteCommand(hi2c, 0xAE); // Display off status += ssd1306_WriteCommand(hi2c, 0x20); // Set Memory Addressing Mode status += ssd1306_WriteCommand(hi2c, 0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid status += ssd1306_WriteCommand(hi2c, 0xB0); // Set Page Start Address for Page Addressing Mode,0-7 status += ssd1306_WriteCommand(hi2c, 0xC8); // Set COM Output Scan Direction status += ssd1306_WriteCommand(hi2c, 0x00); // Set low column address status += ssd1306_WriteCommand(hi2c, 0x10); // Set high column address status += ssd1306_WriteCommand(hi2c, 0x40); // Set start line address status += ssd1306_WriteCommand(hi2c, 0x81); // set contrast control register status += ssd1306_WriteCommand(hi2c, 0xFF); status += ssd1306_WriteCommand(hi2c, 0xA1); // Set segment re-map 0 to 127 status += ssd1306_WriteCommand(hi2c, 0xA6); // Set normal display status += ssd1306_WriteCommand(hi2c, 0xA8); // Set multiplex ratio(1 to 64) status += ssd1306_WriteCommand(hi2c, SSD1306_HEIGHT - 1); status += ssd1306_WriteCommand(hi2c, 0xA4); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content status += ssd1306_WriteCommand(hi2c, 0xD3); // Set display offset status += ssd1306_WriteCommand(hi2c, 0x00); // No offset status += ssd1306_WriteCommand(hi2c, 0xD5); // Set display clock divide ratio/oscillator frequency status += ssd1306_WriteCommand(hi2c, 0xF0); // Set divide ratio status += ssd1306_WriteCommand(hi2c, 0xD9); // Set pre-charge period status += ssd1306_WriteCommand(hi2c, 0x22); status += ssd1306_WriteCommand(hi2c, 0xDA); // Set com pins hardware configuration status += ssd1306_WriteCommand(hi2c, SSD1306_COM_LR_REMAP << 5 | SSD1306_COM_ALTERNATIVE_PIN_CONFIG << 4 | 0x02); status += ssd1306_WriteCommand(hi2c, 0xDB); // Set vcomh status += ssd1306_WriteCommand(hi2c, 0x20); // 0x20,0.77xVcc status += ssd1306_WriteCommand(hi2c, 0x8D); // Set DC-DC enable status += ssd1306_WriteCommand(hi2c, 0x14); // status += ssd1306_WriteCommand(hi2c, 0xAF); // Turn on SSD1306 panel if (status != 0) { return 1; } // Clear screen ssd1306_Fill(Black); // Flush buffer to screen ssd1306_UpdateScreen(hi2c); // Set default values for screen object SSD1306.CurrentX = 0; SSD1306.CurrentY = 0; SSD1306.Initialized = 1; return 0; }
关键函数
void ssd1306_UpdateScreen(I2C_HandleTypeDef *hi2c); void ssd1306_Fill(SSD1306_COLOR color); void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color); char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color); char ssd1306_WriteString(const char* str, FontDef Font, SSD1306_COLOR color); void ssd1306_SetCursor(uint8_t x, uint8_t y); void ssd1306_InvertColors(void); void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t index); // Function to write a number to the screen buffer void ssd1306_WriteNumber(int number, FontDef Font, SSD1306_COLOR color); void ssd1306_Clear(I2C_HandleTypeDef *hi2c);
点亮屏幕显示文字: 通过绘制字符或图像来点亮屏幕,以下是显示 “HelloWorld!” 的代码:
ssd1306_SetCursor(2 ,24); ssd1306_WriteString("HelloWorld",Font_11x18,White); ssd1306_UpdateScreen(&hi2c1);
二、流量传感器 YF-S401 的测量原理与实现
1. 工作原理
YF-S401 是基于霍尔传感器的液体流量传感器,内部有一个叶轮。当液体通过时,叶轮旋转产生脉冲信号,信号频率与流量成正比。
公式:流量(L/min) = 脉冲频率(Hz) / 7.5
2. 硬件连接
红线 (VCC) → STM32 的 5V
黑线 (GND) → STM32 的 GND
黄线 (信号输出) → STM32 的 PA1(TIM2 输入捕获通道2)
3. 编程实现
在 STM32CubeMX 中,配置 TIM2 为 输入捕获 ,捕获通道设置为 CH2。
* TIM2 init function */ void MX_TIM2_Init(void) { /* USER CODE BEGIN TIM2_Init 0 */ /* USER CODE END TIM2_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_IC_InitTypeDef sConfigIC = {0}; /* USER CODE BEGIN TIM2_Init 1 */ /* USER CODE END TIM2_Init 1 */ htim2.Instance = TIM2; htim2.Init.Prescaler = 63; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 99; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2; sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED; sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; sClockSourceConfig.ClockFilter = 0; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_IC_Init(&htim2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM2_Init 2 */ /* USER CODE END TIM2_Init 2 */ } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim == (&htim1)) { pluse_count = __HAL_TIM_GET_COUNTER(&htim2); // read 1s liuliang __HAL_TIM_SET_COUNTER(&htim2,0); //TIM2???? Flow_read(); // received =1; } }
三、继电器模块和抽水泵的连接
1. 继电器模块 DFR0017
继电器模块通过控制高压设备的通断来实现开关功能。STM32 的 GPIO 输出可以直接驱动继电器。
硬件连接:
继电器 IN → STM32 的 PA15
继电器 VCC → STM32 的 5V
继电器 GND → STM32 的 GND
继电器 COM → 抽水泵的电源正极
继电器 NO → 抽水泵的电源负极
2. 控制逻辑
设置 PA15为输出,通过拉高或拉低 GPIO 控制继电器的开关。
简单的开关程序:
void Pump_Control(GPIO_PinState state) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, state); }
测试逻辑: 打开水泵 5 秒后关闭
Pump_Control(GPIO_PIN_SET); // 打开 HAL_Delay(5000); Pump_Control(GPIO_PIN_RESET); // 关闭
测试结果
OLED 显示正常:屏幕实时显示流量数据。
流量传感器工作正常:每秒输出的流量数据与实际流速吻合。
继电器控制水泵正常:水泵的开启与关闭逻辑清晰,测试稳定。