这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【Let'sdo第四期-液体流量检测仪DIY】-过程帖

共1条 1/1 1 跳转至

【Let'sdo第四期-液体流量检测仪DIY】-过程帖

菜鸟
2025-01-25 23:32:44     打赏

之前分享了液体流量检测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);

helloworld.png

二、流量传感器 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 显示正常:屏幕实时显示流量数据。

流量传感器工作正常:每秒输出的流量数据与实际流速吻合。

继电器控制水泵正常:水泵的开启与关闭逻辑清晰,测试稳定。继电器.png



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]