AMPS:非阻塞模块和I/O代理

本文介绍了AMPS框架中非阻塞模块与I/O代理模块的区别及工作原理,重点解析了I/O代理模块的设计思路,包括其事件调度器与线程池的工作流程,以及如何处理大量的I/O请求。

  AMPS中模块分为非阻塞、阻塞和I/O 代理两种类型。

  •   无阻塞模块:如发送和接收网络消息,或者读写文件。
  •   阻塞模块和I/O代理:
               有些场景下阻塞可能无法实现,例如DNS查询或者数据库交互。这种场景下,AMPS要求开发者以I/O代理的形式创建模块,I/O代理准备I/O请求,并花大量时间等待操作完成,它由一个事件调度器和一个线程池组成。池中的每个线程关联一个事件队列,在空闲状态下线程在事件队列中保持阻塞,调度器被主事件管理器作为事件句柄注册。它从池中选择一个线程,并且分发一个接收事件到与线程关联的队列。这样设计的优点是当有大量的I/O请求时,可以将其一并保存在队列中。每个线程执行同样的代码,一旦由于队列中的新事件线程唤醒后,它调用事件句柄进行处理,而句柄可能在I/O操作期间阻塞,此时这个线程为阻塞事件提供服务,而程序继续处理未被分发的事件。



  在上图中,当模块1请求一个由模块2提供的服务时,(模块2为一个I/O代理,由一个线程池和一个分发函数组成,分发函数以回调函数的形式注册给事件管理器,线程池包括4个线程),由模型1产生的请求R1通过事件调试程序路由给模块2,并且它的分发函数被调用,分发函数在线程池中选择一个线程(如线程2),并将请求传给此线程,线程开始处理这个请求,当I/O操作完成后,它产生一个响应事件RES1并路由回给模块1(模块1注册了此事件类型)。

#include "InlineCurrent.h" #include "esp_log.h" #include "driver/adc.h" #include "esp_adc/adc_oneshot.h" #include "hal/adc_types.h" #define _ADC_VOLTAGE 3.3f #define _ADC_RESOLUTION 4095.0f #define _ADC_CONV (_ADC_VOLTAGE / _ADC_RESOLUTION) CurrSense::CurrSense(adc_channel_t channelA, adc_channel_t channelB, adc_channel_t channelC, float shunt_resistor, float amp_gain) : channelA(channelA), channelB(channelB), channelC(channelC), adc1_handle(nullptr), _shunt_resistor(shunt_resistor), amp_gain(amp_gain) { // 计算电流转换系数 volts_to_amps_ratio = 1.0f / _shunt_resistor / amp_gain; gain_a = volts_to_amps_ratio * -1; gain_b = volts_to_amps_ratio * -1; gain_c = volts_to_amps_ratio; } float CurrSense::readADCVoltageInline(adc_channel_t channel) { if (!isChannelValid(channel) || adc1_handle == nullptr) { return 0.0f; } int raw_adc; if (adc_oneshot_read(adc1_handle, channel, &amp;raw_adc) != ESP_OK) { ESP_LOGE("CurrSense", "ADC read failed for channel %d", channel); return 0.0f; } return raw_adc * _ADC_CONV; } void CurrSense::configureADCInline() { // 配置 ADC1 单元 adc_oneshot_unit_init_cfg_t init_config1 = { .unit_id = ADC_UNIT_1, .clk_src = ADC_RTC_CLK_SRC_DEFAULT, .ulp_mode = ADC_ULP_MODE_DISABLE }; if (adc_oneshot_new_unit(&amp;init_config1, &amp;adc1_handle) != ESP_OK) { ESP_LOGE("CurrSense", "Failed to create ADC1 unit"); return; } adc_oneshot_chan_cfg_t config = { .atten = adc_atten, .bitwidth = adc_width }; // 配置通道A if (isChannelValid(channelA) &amp;&amp; adc_oneshot_config_channel(adc1_handle, channelA, &amp;config) != ESP_OK) { ESP_LOGE("CurrSense", "Failed to configure channel A"); } // 配置通道B if (isChannelValid(channelB) &amp;&amp; adc_oneshot_config_channel(adc1_handle, channelB, &amp;config) != ESP_OK) { ESP_LOGE("CurrSense", "Failed to configure channel B"); } // 配置通道C(如果有效) if (isChannelValid(channelC) &amp;&amp; adc_oneshot_config_channel(adc1_handle, channelC, &amp;config) != ESP_OK) { ESP_LOGE("CurrSense", "Failed to configure channel C"); } } void CurrSense::calibrateOffsets() { const int calibration_rounds = 1000; offset_ia = 0.0f; offset_ib = 0.0f; offset_ic = 0.0f; // 多次采样求平均(消除噪声) for (int i = 0; i < calibration_rounds; i++) { if (isChannelValid(channelA)) offset_ia += readADCVoltageInline(channelA); if (isChannelValid(channelB)) offset_ib += readADCVoltageInline(channelB); if (isChannelValid(channelC)) offset_ic += readADCVoltageInline(channelC); vTaskDelay(pdMS_TO_TICKS(1)); } if (isChannelValid(channelA)) offset_ia /= calibration_rounds; if (isChannelValid(channelB)) offset_ib /= calibration_rounds; if (isChannelValid(channelC)) offset_ic /= calibration_rounds; } void CurrSense::init() { // 配置ADC configureADCInline(); // 校准零偏移 calibrateOffsets(); } void CurrSense::getPhaseCurrents() { // 计算各相电流(减去偏移后转换) current_a = isChannelValid(channelA) ? (readADCVoltageInline(channelA) - offset_ia) * gain_a : 0.0f; current_b = isChannelValid(channelB) ? (readADCVoltageInline(channelB) - offset_ib) * gain_b : 0.0f; current_c = isChannelValid(channelC) ? (readADCVoltageInline(channelC) - offset_ic) * gain_c : 0.0f; }给出修改后的代码
最新发布
08-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值