之前分享了液体流量检测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 显示正常:屏幕实时显示流量数据。
流量传感器工作正常:每秒输出的流量数据与实际流速吻合。
继电器控制水泵正常:水泵的开启与关闭逻辑清晰,测试稳定。
我要赚赏金
