恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

STM32非接触式水位检测实战:从ADC采集到OLED显示

  • 首页
  • 资讯中心
  • /
  • STM32非接触式水位检测实战:从ADC采集到OLED显示

相关资讯

基于STM32与DDS的电路特性测试仪:从电赛D题到工程实践 2026/9/8 1:35:51
VS2017下编译支持OpenSSL的libcurl库实战指南 2026/9/8 1:30:51
电力有限空间作业智能化升级:从气体检测到UWB定位的实战解析 2026/9/8 1:30:51

最新资讯

C#接入Zebra打印机完整指南:ZPL指令直发、中文乱码与现场排障
AI编程实测:写代码速度变快了,但开发者的时间都花在哪了?
MFC自绘信号灯实时显示二进制数状态:从GDI绘制到定时刷新
经典肌肉车与现代动力融合:1968道奇Charger的碳纤维与Hellephant引擎革命
PPO算法实战:用PyTorch训练LunarLander月球着陆器
Vim文本格式化全攻略:从自动换行到中文排版

今日推荐

Redis缓存与离线预计算在大数据处理中的实战应用
Android 12热启动闪屏排查:从冷热启动差异到官方SplashScreen避坑指南
加密资产价值投资:原理、方法与实战策略

本周热门

超人会飞不算本事:系统稳定依赖清晰规则与边界设计
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
基于CNN的调制信号识别:MATLAB实现时频图分类实战

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

STM32非接触式水位检测实战:从ADC采集到OLED显示

发布时间:2026/9/8 1:35:51
STM32非接触式水位检测实战:从ADC采集到OLED显示 做单片机项目传感器采集完了怎么显示永远是一个绕不开的环节。最近在调试一套非接触式水位检测方案拿STM32F103C8T6做核心配上HS-S37A水位传感器和一块0.96寸的I2C接口OLED屏从接线、CubeMX配置、底层驱动到显示界面把整套流程完整跑了一遍。做完之后我觉得这套实验很有代表性它几乎涵盖了单片机开发最常见的几个知识点ADC采集、I2C通信、OLED驱动、软件滤波、标定换算。不管你是刚学STM32的朋友还是想给现有项目加水位检测功能这篇都可以直接拿去参考。先说我为什么选这套组合。HS-S37A是非接触式的传感器不用接触水隔着塑料或玻璃容器壁就能检测干净卫生也几乎没有维护成本OLED用I2C接口只占两根IO线驱动成熟。整个系统的核心价值一句话就能说清把容器里有多少水这件事变成屏幕上能直观看到的百分比和进度条。下面按我的实验顺序把硬件、软件和踩坑过程都展开讲。1. HS-S37A传感器的原理与输出特性先搞清楚再动手1.1 非接触式电容检测是怎么回事HS-S37A这类非接触式水位传感器本质上是一个电容感应装置。水和空气的介电常数差异非常大空气的介电常数约为1水大约是80。当容器内的水位上升、水靠近传感器感应面时传感器电极与周围环境构成的等效电容会发生明显变化。模块内部的信号调理电路把这种电容变化转换成电压变化最终从输出引脚送出来。这个原理和手机触摸屏的电容感应有些类似。手指含水导体靠近时引起电容变化屏幕判断出触摸位置。HS-S37A则是用水位高度影响电容从而给出一个随水位连续变化的电信号。因为检测的是电场变化传感器不需要接触液体本身隔着非金属容器壁就能工作。这个传感器表面与容器壁之间不能有金属是硬性条件后面我会详细说。另外传感器感应面需要紧贴容器外壁中间尽量不要留空气间隙。我用透明的亚克力水箱测试效果很稳定如果容器壁太厚灵敏度会下降实测超过10mm后信号变化就不太明显了。1.2 输出引脚定义与电气特性HS-S37A模块通常引出四个引脚有些板子还会标注丝印用之前最好用万用表确认一下避免接错引脚功能说明VCC电源正极常见支持3.3V~5V具体看批次和模块丝印GND电源地与STM32共地DO数字输出开关量水位超过模块上电位器设定的阈值时翻转AO模拟输出连续电压随水位变化接STM32的ADC引脚模块上一般会有一个小电位器专门用来调节DO比较阈值。用螺丝刀旋转可以改变触发点适合做报警器。AO输出的电压范围大致在0V到供电电压之间但具体是水位越高电压越高还是越低不同批次会有差异需要实测确认。这里有一个新手最容易踩的坑把AO接到了STM32的普通GPIO上然后等一个变化电平结果读到的全是0或1。DO和AO必须分清做连续水位显示用的是AO做阈值报警用DO。还有一种做法是DO和AO一起用阈值触发中断、模拟量做连续监测后面扩展部分会提到。1.3 跟接触式、浮球式水位传感器的选择差异做水位检测的方案很多接触式电极、浮球开关、光电式、压力式都见过。对比一下各自的优缺点你就知道非接触式的价值在哪里类型优点缺点典型场景浮球开关结构简单便宜机械运动易卡死、有残留水垢水箱高低水位报警接触式电极成本低电极易腐蚀、水垢影响精度导电液体检测光电式响应快、无机械件需要透光容器或开孔安装管路液位检测非接触式电容不接触液体、无腐蚀、免维护精度受容器壁材质和厚度影响饮水机、加湿器、医疗设备我这次选HS-S37A的直接原因是不用开孔。之前用浮球开关装在水箱侧壁开孔处时间长了总担心漏水。非接触式是贴装方案安装后想挪位置也方便。代价是它的连续测量精度一般用来做阈值判断或者粗略的百分比显示完全够用但如果你想精确到毫米级的水位高度它并不适合。2. 实验接线与工程初始化这一步错了后面全白搭2.1 完整硬件清单STM32F103C8T6最小系统板一块最常见的蓝色板子HS-S37A非接触式水位传感器模块一个0.96寸I2C接口OLED屏一块SSD1306主控128x64分辨率ST-Link V2调试器一个用于下载和调试USB转串口模块一个CH340或CP2102都行UART调试打印用杜邦线若干、面包板或者洞洞板一个非金属容器亚克力水箱或塑料瓶测试用水万用表、螺丝刀关于调试器多说一句ST-Link V2和J-Link都可以但驱动要装对。ST-Link用官方的ST-Link驱动J-Link用SEGGER的JLink驱动。如果你电脑上两个驱动都装过插上设备后建议去设备管理器确认枚举出来的是哪一类避免调试器识别混乱。2.2 接线对照表部件引脚接STM32HS-S37AVCC3.3VHS-S37AGNDGNDHS-S37AAOPA1OLEDVCC3.3VOLEDGNDGNDOLEDSCLPB6I2C1_SCLOLEDSDAPB7I2C1_SDAST-LinkSWDIOPA13ST-LinkSWCLKPA14ST-LinkGNDGNDST-Link3.3V3.3V可选USB转串口TXPA10USART1_RXUSB转串口RXPA9USART1_TXUSB转串口GNDGNDPA1是ADC1_IN1这是F103上很常用的ADC通道。OLED接在I2C1上PB6/PB7是默认复用功能。这里要特别提醒几个点第一传感器VCC我建议接3.3V而不是5V。如果模块5V供电AO输出范围可能会到5V直接进STM32的ADC会超量程有烧引脚风险。第二USB转串口的GND必须和STM32共地不然串口打印全是乱码。第三ST-Link的SWDIO/SWCLK接线反了会直接导致连接失败后面下载时报错。2.3 STM32CubeMX配置要点ADC通道与I2C外设用STM32CubeMX生成工程版本不同界面略有差异但逻辑一致。以下是几个关键配置项每个我都会解释为什么这么设置。SYS - DebugSerial Wire。这个必须选不选的话生成的工程会把SWD引脚当普通IO处理第一次程序下载进去后第二次下载就可能报no stm32 target found。我在实验里专门故意踩过一次这个坑后面排错部分详细讲。RCC - HSECrystal/Ceramic Resonator。使用板载8MHz晶振作为HSE时钟源之后通过PLL倍频到72MHz主频。ADC1 配置ModeIN1对应PA1ADC参数里Resolution选12位默认Sampling Time建议选55.5 Cycles以上我实际用239.5 Cycles读值明显更稳。原因后面讲开启连续转换模式Continuous Conversion ModeI2C1 配置I2C Speed ModeFast Mode400KHz地址模式默认7-bitUSART1 配置ModeAsynchronousBaud Rate1152008数据位1停止位无校验时钟树里确认APB1总线时钟是36MHzI2C1挂在APB1上CubeMX会自动算好分频系数不用手动调。生成代码时记得选Generate peripheral initialization as a pair of .c/.h files per peripheral这样每个外设独立成文件后面加代码好管理。3. OLED驱动的核心逻辑懂了这个才能自由改显示3.1 SSD1306初始化序列该怎么配SSD1306是一款非常经典的OLED控制芯片几乎所有0.96寸OLED模块都用它。它内部有一块128x64的显存GDDRAM每个bit对应屏幕上一个像素点。I2C模式下外部主控通过I2C总线往这块显存写数据屏幕就显示出来了。上电之后SSD1306默认是不显示的需要发送一串初始化命令。命令序列各家代码略有差异但有几个命令是必须的少了显示屏就不工作。我用的初始化序列如下static uint8_t ssd1306_init_cmds[] { 0xAE, // 关闭显示 0xD5, 0x80, // 显示时钟分频/振荡器频率 0xA8, 0x3F, // 多路复用率64行 0xD3, 0x00, // 显示偏移0 0x40, // 起始行0 0x8D, 0x14, // 电荷泵使能 0x20, 0x00, // 水平寻址模式 0xA1, // 段重映射 0xC8, // COM扫描方向 0xDA, 0x12, // COM引脚硬件配置 0x81, 0xCF, // 对比度 0xD9, 0xF1, // 预充电周期 0xDB, 0x40, // VCOMH电压 0xA4, // 按显存内容显示 0xA6, // 正常显示模式 0xAF // 开启显示 };其中0x8D 0x14是电荷泵使能这一步尤其重要。OLED工作需要内部升压电路如果没开电荷泵屏幕会一直黑着无论你往显存里写多少数据都没用。我曾经调一块新屏幕检查了所有接线都没问题最后发现是初始化序列里漏了这条命令。3.2 HAL库发送命令和数据的两种方式I2C传输SSD1306数据时第一个字节是控制字节用来区分后续内容是命令还是数据0x00后面的字节是命令0x40后面的字节是显存数据在HAL库下写命令有两种常见方式。我用的是HAL_I2C_Master_Transmitvoid oled_write_cmd(uint8_t cmd) { uint8_t buf[2]; buf[0] 0x00; buf[1] cmd; HAL_I2C_Master_Transmit(hi2c1, OLED_ADDR 1, buf, 2, 100); }写数据类似只是控制字节改成0x40void oled_write_data(uint8_t *data, uint16_t len) { uint8_t buf[1025]; buf[0] 0x40; memcpy(buf 1, data, len); HAL_I2C_Master_Transmit(hi2c1, OLED_ADDR 1, buf, len 1, 100); }注意OLED_ADDR 1这步。SSD1306的7位I2C地址通常是0x3C而HAL库的Master_Transmit接口需要的是8位地址即7位地址左移一位所以实际传入0x78。很多新手在这里卡住以为OLED地址是0x78直接传进去结果通信一直失败。如果模块上SA0引脚被拉高地址会变成0x3D左移后是0x7A。还有一种方式是用HAL_I2C_Mem_Write它内部会自动处理寄存器地址但本质上也是先发控制字节再发数据。两种方式效果一样我习惯用Master_Transmit因为逻辑更直观。3.3 显存缓冲画点、画线、进度条的实现思路SSD1306的显存按页划分纵向8个像素为一页所以128x64的屏幕共8页每页128字节总共1024字节。水平寻址模式下往显存写数据时地址自动递增从左上角开始横向逐字节填充。我采用显存缓冲的方式在内存中维护一个1024字节的buffer所有绘图操作先改buffer最后一次性刷到屏幕。这样可以避免频繁的I2C写操作减少闪烁。uint8_t oled_buf[1024]; void oled_draw_pixel(uint8_t x, uint8_t y, uint8_t on) { if (x 127 || y 63) return; uint16_t idx x (y / 8) * 128; if (on) oled_buf[idx] | (1 (y % 8)); else oled_buf[idx] ~(1 (y % 8)); }全量刷新函数void oled_refresh(void) { oled_write_cmd(0x21); oled_write_cmd(0); oled_write_cmd(127); oled_write_cmd(0x22); oled_write_cmd(0); oled_write_cmd(7); oled_write_data(oled_buf, 1024); }字符显示可以做一个5x8的ASCII字库存放在const数组里取模方式网上很多工具可以生成。汉字显示则需要16x16点阵字模显示的时候按2字节一行、逐页写入。进度条绘制也很简单先画一个矩形边框然后按百分比计算填充宽度逐列用垂直直线填充。4. 核心代码实现从ADC采集到水位百分比的计算全过程4.1 ADC采样与滑动滤波的实现ADC每次转换的原始值并不稳定尤其当传感器信号本身有波动时。直接把这个值拿来换算百分比屏幕上会跳得没法看。我用了20次滑动平均效果很理想。#define FILTER_LEN 20 uint16_t filter_buf[FILTER_LEN]; uint8_t filter_idx 0; uint32_t filter_sum 0; void filter_init(void) { memset(filter_buf, 0, sizeof(filter_buf)); } void filter_add(uint16_t val) { filter_sum - filter_buf[filter_idx]; filter_buf[filter_idx] val; filter_sum val; filter_idx (filter_idx 1) % FILTER_LEN; } uint16_t filter_get_avg(void) { return (uint16_t)(filter_sum / FILTER_LEN); }为什么采样周期要设置得很长STM32F103的ADC是逐次逼近型内部有采样保持电容。如果信号源输出阻抗较大采样时间太短会导致保持电容充不满转换结果整体偏大且不稳定。把采样时间从默认的1.5 Cycles调到239.5 Cycles后原始ADC值的跳动范围能缩小一半以上。代价是采样速度下降但水位检测本来就不需要高采样率稳定性优先。在主循环里定时取一次ADC值加入滤波器if (HAL_GetTick() - last_sample 50) { last_sample HAL_GetTick(); HAL_ADC_Start(hadc1); if (HAL_ADC_PollForConversion(hadc1, 10) HAL_OK) { filter_add(HAL_ADC_GetValue(hadc1)); } HAL_ADC_Stop(hadc1); }这里用HAL_ADC_StartPollForConversion而不是一直开着连续转换是为了让ADC采样和主循环刷新节奏一致。实际上CubeMX里也可以直接开连续转换模式主循环里直接读取转换完成标志两种方式都行。4.2 两点标定法把ADC值映射成水位百分比拿到稳定的ADC值之后需要把它转换成人类能看懂的水位百分比。这一步就是标定。我在实验里用的是两点线性标定把容器里的水全部倒空等传感器输出稳定记录ADC值记为ADC_EMPTY把水加到想要标定的最高水位比如容器满水记录ADC值记为ADC_FULL之后任意时刻ADC值在这两个点之间做线性映射#define ADC_EMPTY 1250 #define ADC_FULL 2670 uint8_t map_to_percent(uint16_t adc_value) { int32_t percent; percent ((int32_t)adc_value - ADC_EMPTY) * 100 / (ADC_FULL - ADC_EMPTY); if (percent 0) percent 0; if (percent 100) percent 100; return (uint8_t)percent; }要注意一个问题不同批次的HS-S37AAO输出方向可能不一样。有的模块水位越高电压越高ADC值变大有的则是水位越高电压越低。所以标定前先在OLED或串口上看一下ADC原始值的变化方向确认是正相关还是负相关再决定映射公式。如果发现方向反了把分子改成ADC_EMPTY - adc_value就行。另外两个标定点不能相隔太近。假设空水时ADC值为1500满水时1600中间只有100个LSB的跨度那1%水位只对应1个LSB稍微有点噪声就会在百分比上剧烈跳动。最好让满水时的ADC值比空水时至少大300~500灵敏度才够用。实测中如果发现变化量太小检查传感器是否贴紧容器壁、容器壁是否太厚或者水量是否真的覆盖到了感应区域。4.3 主循环逻辑与OLED实时刷新主循环做的事情很清晰定时采集ADC值做滤波换算电压和百分比刷新OLED显示。电压值可以直接算float voltage (float)adc_value * 3.3f / 4095.0f;电压显示用于排查供电和接线问题很有用。如果电源电压正常传感器输出电压应该在预期范围内波动一旦出现0V或满量程3.3V不变基本可以判断是传感器没贴好或者信号线接触有问题。OLED显示布局我设计成四行第0行标题字符串第2行ADC原始值和电压值第4行水位百分比第5行进度条图形while (1) { uint16_t adc filter_get_avg(); float volt (float)adc * 3.3f / 4095.0f; uint8_t percent map_to_percent(adc); char buf[20]; oled_clear(); oled_show_string(0, 0, Water Level:); sprintf(buf, ADC%d %.2fV, adc, volt); oled_show_string(0, 2, buf); sprintf(buf, %d%%, percent); oled_show_string(0, 4, buf); oled_draw_progress(0, 5, 128, percent); oled_refresh(); printf(ADC%d, %.2fV, %d%%\r\n, adc, volt, percent); HAL_Delay(100); }刷新间隔我放在100ms人眼看进度条很平滑同时也给I2C和ADC采样留足时间。如果你打算把间隔缩短到10ms要注意I2C每次全量刷新1024字节在400KHz下大约需要20ms刷新太快反而会积压通信显示效果变差。oled_draw_progress函数实现进度条void oled_draw_progress(uint8_t x, uint8_t y, uint8_t width, uint8_t percent) { uint8_t fill (uint16_t)width * percent / 100; // 画边框 for (uint8_t i 0; i width; i) { oled_draw_pixel(x i, y, 1); oled_draw_pixel(x i, y 7, 1); } for (uint8_t j 0; j 8; j) { oled_draw_pixel(x, y j, 1); oled_draw_pixel(x width - 1, y j, 1); } // 填充 for (uint8_t i 1; i fill; i) { for (uint8_t j 1; j 7; j) { oled_draw_pixel(x i, y j, 1); } } }进度条直观一眼就能看出当前容器里大概有多少水。5. 实测中的意外与排查这些坑我替你踩过了5.1 no stm32 target found下载失败的本质原因我调试过程中遇到的第一个大坑就是下载程序时弹出error: no stm32 target found!。这个报错本质上是调试器通过SWD接口和芯片建立通信时目标芯片没有任何回应。排查顺序我建议这样来确认驱动和设备枚举正常。插上ST-Link打开设备管理器应该能看到对应的驱动设备。如果显示黄色感叹号重装驱动。J-Link和ST-Link驱动不要混装容易冲突。检查接线。SWDIO必须接PA13SWCLK必须接PA14GND必须共地。用万用表蜂鸣档量一下杜邦线两端的导通性排除线断了的情况。确认目标板供电。用万用表量芯片VDD引脚和GND之间是否有3.3V。ST-Link的3.3V输出可以给板子供电但要注意有些大功率板子只靠调试器的供电不够稳定。检查BOOT0。如果BOOT0被拉高芯片上电后进入系统存储器模式不运行用户程序。SWD在系统存储器模式下通常还能连上但如果跳线接触不良、电压飘忽也会导致连接失败。正常运行时BOOT0应该接低电平。复位线。部分ST-Link固件和调试配置下连接时需要访问NRST引脚尤其是芯片进入低功耗模式或者SWD引脚被复用成普通IO时。把ST-Link的NRST接到板子的NRST引脚能解决很多顽固问题。最隐蔽的情况是SWD引脚被用户代码复用成普通GPIO。比如你第一次下载程序后程序运行起来把PA13/PA14配置成了普通输出模式SWD调试接口就被占用了这会导致第二次下载时调试器找不到目标。解决方法是按住板子上的复位键不放点击Keil的下载按钮在芯片复位期间用户程序还没跑起来抢到总线控制权。或者把BOOT0拉高再上电让芯片进入系统存储器模式绕过用户代码然后执行整片擦除。我当时就遇到过一次最后是拉高BOOT0、连接后在ST-Link Utility里执行擦除芯片恢复正常。所以CubeMX里SYS-Debug选Serial Wire这一步真的不要漏。5.2 传感器输出电压反跳、漂移的处理第二个常见问题是ADC读值不稳定甚至在某个范围内反复跳。我遇到过三种情况电源噪声。如果传感器和STM32共用一个电源而电源纹波比较大ADC结果会明显跳动。实验中我在传感器VCC引脚和GND之间加了一个0.1uF陶瓷电容再用一个10uF电解电容并联读数立刻稳定了不少。如果条件允许ADC的参考电压VREF也可以加一级LC滤波效果更好。接线过长和线材质量。杜邦线超过20cm且没有屏蔽时容易引入电磁干扰。传感器AO信号线尽量短不要和电源线、电机驱动线绑扎在一起。实验板旁边如果有水泵、继电器之类的感性负载切换瞬间会产生尖峰干扰水位计的读数会在那一刻跳变。软件滤波策略不当。滑动平均窗口太小滤不掉脉冲噪声窗口太大会让响应变迟钝。我试过10次、20次、50次窗口20次在这个场景下比较平衡。如果你遇到偶发的尖峰干扰还可以在滑动平均之前加一个简单的中值滤波去掉最大和最小值再平均效果更干净。5.3 OLED不出字或花屏的几种可能OLED显示异常优先级最高的怀疑对象是I2C地址和初始化序列。我用I2C扫描程序把总线上所有设备地址打印出来非常管用for (uint8_t addr 1; addr 127; addr) { if (HAL_I2C_IsDeviceReady(hi2c1, addr 1, 1, 10) HAL_OK) { printf(Found I2C device at 0x%02X\r\n, addr); } }如果地址扫描不到设备大概率是接线或者上拉电阻的问题。OLED模块的板载I2C上拉电阻通常已经有不需要额外加。如果自己飞线连接裸屏SDA和SCL必须接2.2K~4.7K上拉电阻到VCC否则I2C通信不稳定。屏幕能亮但显示乱码或花屏通常是显存地址错位。检查初始化命令里的起始行、段重映射和COM扫描方向配置是否正确尤其注意0x21列地址设置命令的起始和结束参数是否正确。显存刷新时如果页地址范围写错显示内容会整体偏移或者上下颠倒。还有一个容易忽略的点HAL库的I2C超时时间。全量刷新1024字节显存时如果超时参数设得太短比如默认的10msI2C传输会超时中断刷新显示的内容残缺。我统一把超时设成100ms全量刷新能稳定完成。如果你用的是中断或者DMA方式传输还要处理好传输完成的同步标志否则刷新过程中数据会被截断。6. 实验扩展这套架构还能直接改造出哪些小项目6.1 加水泵自动控水系统最直接的扩展是加一个继电器模块控制小型水泵或电磁阀。设定一个低水位阈值和一个高水位阈值形成滞回控制水位低于30%时打开水泵加水水位达到85%时关闭水泵滞回区间防止水泵在下限附近频繁启停。继电器线圈需要外部供电触点侧驱动水泵注意电磁干扰对传感器的屏蔽。这个方案用在鱼缸自动补水、加湿器水箱管理上都行。DO输出引脚正好可以配合这个场景DO调好阈值后直接接外部中断水位到达报警点瞬间触发回调而不是靠主循环轮询响应更快也更省CPU。6.2 多点水位检测如果容器比较高单一传感器只能检测一个局部区域的水位。可以在不同高度贴多片HS-S37A各自接到不同的ADC通道程序里做分段判断。比如三片传感器分别贴在低、中、高三个位置组合状态能粗略判断出空、低、中、满四个档位。这种方案比连续百分比显示更可靠因为每片传感器只做有水/无水的开关判断不受连续测量线性度不高的限制。6.3 界面升级与无线化显示部分可以继续丰富用16x16点阵显示汉字标题在OLED上绘制一条水位历史曲线每隔一段时间采样一个点滚动显示最近半小时的水位变化趋势。曲线绘制其实就是把水位百分比映射到纵坐标左移绘制逻辑不复杂。如果想把数据上报到手机可以用ESP8266或ESP32通过串口和STM32通讯把ADC值、电压值、水位百分比打包成简单的自定义协议发出去。这样OLED本地显示保留手机端远程查看就从一个实验变成一个完整的小项目了。整套实验做完我对STM32的HAL库工程结构、ADC采样特性和I2C协议的理解比之前深了不少。尤其是标定这一步它让我意识到传感器不是插上去就能用的手册给的电气参数只是基础实际安装环境才是决定精度的关键。如果你也打算复刻这个实验建议先不要把精力放在优化显示界面上而是用串口把ADC原始值打出来观察不同水位下数值的变化规律等你看懂了传感器的脾气后面的百分比映射、报警阈值、自动控制都是水到渠成的事。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号