Улучшения
- улушчено отображение на OLED - убраны настройки шага частоты и количества повторов - сделан перебор только реализуемых частот - увеличена точность, на 1МГц 1.25%, в остальных до 1% - точное измерение TOTAL TIME
This commit is contained in:
@@ -8,17 +8,55 @@
|
||||
|
||||
uint32_t PulseReceiver::tickHz() const {
|
||||
#if OPTICAL_USE_RMT_DMA
|
||||
return CAPTURE_RESOLUTION_HZ;
|
||||
return captureResolutionHz_;
|
||||
#else
|
||||
return cpuTickHz_;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t PulseReceiver::plannedTickHz(uint32_t expectedHz, float expectedDutyPct) const {
|
||||
#if OPTICAL_USE_RMT_DMA
|
||||
if (!expectedHz || expectedDutyPct <= 0.0f || expectedDutyPct >= 100.0f)
|
||||
return CAPTURE_RESOLUTION_OPTIONS_HZ[0];
|
||||
uint32_t dutyX100 = static_cast<uint32_t>(expectedDutyPct * 100.0f + 0.5f);
|
||||
if (dutyX100 < 5000U) dutyX100 = 10000U - dutyX100;
|
||||
for (int i = static_cast<int>(countOf(CAPTURE_RESOLUTION_OPTIONS_HZ)) - 1; i >= 0; --i) {
|
||||
const uint32_t resolution = CAPTURE_RESOLUTION_OPTIONS_HZ[i];
|
||||
const uint64_t levelTicksX100 = static_cast<uint64_t>(resolution) * dutyX100;
|
||||
const uint64_t limitX100 = static_cast<uint64_t>(expectedHz) * 10000ULL * RMT_MAX_LEVEL_TICKS;
|
||||
if (levelTicksX100 <= limitX100) return resolution;
|
||||
}
|
||||
return CAPTURE_RESOLUTION_OPTIONS_HZ[0];
|
||||
#else
|
||||
(void)expectedHz; (void)expectedDutyPct;
|
||||
return cpuTickHz_;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PulseReceiver::begin() {
|
||||
#if OPTICAL_USE_RMT_DMA
|
||||
queue_ = xQueueCreate(RMT_QUEUE_BLOCKS, sizeof(SymbolBlock));
|
||||
return queue_ && configureRmt(CAPTURE_RESOLUTION_OPTIONS_HZ[0]);
|
||||
#else
|
||||
queue_ = xQueueCreate(256, sizeof(Edge));
|
||||
if (!queue_) return false;
|
||||
pinMode(GPIO_RX, INPUT);
|
||||
cpuTickHz_ = getCpuFrequencyMhz() * 1000000UL;
|
||||
attachInterruptArg(GPIO_RX, onGpio, this, CHANGE);
|
||||
return cpuTickHz_ != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if OPTICAL_USE_RMT_DMA
|
||||
bool PulseReceiver::configureRmt(uint32_t resolutionHz) {
|
||||
if (channel_ && captureResolutionHz_ == resolutionHz) return true;
|
||||
stop();
|
||||
if (channel_) {
|
||||
if (rmt_del_channel(channel_) != ESP_OK) return false;
|
||||
channel_ = nullptr;
|
||||
}
|
||||
rmt_rx_channel_config_t cfg = {};
|
||||
cfg.clk_src = RMT_CLK_SRC_DEFAULT; cfg.resolution_hz = CAPTURE_RESOLUTION_HZ;
|
||||
cfg.clk_src = RMT_CLK_SRC_DEFAULT; cfg.resolution_hz = resolutionHz;
|
||||
cfg.gpio_num = static_cast<gpio_num_t>(GPIO_RX);
|
||||
cfg.flags.invert_in = RX_SIGNAL_INVERTED;
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
@@ -30,20 +68,23 @@ bool PulseReceiver::begin() {
|
||||
cfg.mem_block_symbols = RMT_MIN_RECEIVE_SYMBOLS;
|
||||
cfg.flags.with_dma = false; // C3 uses hardware RMT ping-pong partial reception
|
||||
#endif
|
||||
if (!queue_ || rmt_new_rx_channel(&cfg, &channel_) != ESP_OK) return false;
|
||||
if (rmt_new_rx_channel(&cfg, &channel_) != ESP_OK) return false;
|
||||
rmt_rx_event_callbacks_t callbacks = {}; callbacks.on_recv_done = onRmt;
|
||||
return rmt_rx_register_event_callbacks(channel_, &callbacks, this) == ESP_OK;
|
||||
#else
|
||||
queue_ = xQueueCreate(256, sizeof(Edge));
|
||||
if (!queue_) return false;
|
||||
pinMode(GPIO_RX, INPUT);
|
||||
cpuTickHz_ = getCpuFrequencyMhz() * 1000000UL;
|
||||
attachInterruptArg(GPIO_RX, onGpio, this, CHANGE);
|
||||
return cpuTickHz_ != 0;
|
||||
#endif
|
||||
if (rmt_rx_register_event_callbacks(channel_, &callbacks, this) != ESP_OK) {
|
||||
rmt_del_channel(channel_); channel_ = nullptr; return false;
|
||||
}
|
||||
captureResolutionHz_ = resolutionHz;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool PulseReceiver::start(uint32_t expectedHz) {
|
||||
bool PulseReceiver::start(uint32_t expectedHz, float expectedDutyPct) {
|
||||
#if OPTICAL_USE_RMT_DMA
|
||||
const uint32_t resolutionHz = plannedTickHz(expectedHz, expectedDutyPct);
|
||||
if (!configureRmt(resolutionHz)) return false;
|
||||
#else
|
||||
(void)expectedHz; (void)expectedDutyPct;
|
||||
#endif
|
||||
resetStream();
|
||||
#if OPTICAL_USE_RMT_DMA
|
||||
// In partial RX mode the callback is delivered when this user buffer fills.
|
||||
@@ -54,19 +95,17 @@ bool PulseReceiver::start(uint32_t expectedHz) {
|
||||
receiveChunkSymbols_ = static_cast<uint16_t>(symbols);
|
||||
if (rmt_enable(channel_) != ESP_OK) return false;
|
||||
rmt_receive_config_t cfg = {};
|
||||
cfg.signal_range_min_ns = 1000000000UL / CAPTURE_RESOLUTION_HZ;
|
||||
cfg.signal_range_min_ns = 1000000000UL / captureResolutionHz_;
|
||||
const uint64_t maxNs = 4000000000ULL / (expectedHz ? expectedHz : 1);
|
||||
// A duration field is 15 bits. Keep the driver's end-of-signal threshold
|
||||
// strictly below that hardware limit (IDF rejects larger values).
|
||||
const uint64_t hardwareMaxNs = 32766ULL * 1000000000ULL / CAPTURE_RESOLUTION_HZ;
|
||||
const uint64_t hardwareMaxNs = static_cast<uint64_t>(RMT_MAX_LEVEL_TICKS) * 1000000000ULL / captureResolutionHz_;
|
||||
cfg.signal_range_max_ns = static_cast<uint32_t>(maxNs > hardwareMaxNs ? hardwareMaxNs : maxNs);
|
||||
cfg.flags.en_partial_rx = true;
|
||||
if (rmt_receive(channel_, receiveBuffer_,
|
||||
receiveChunkSymbols_ * sizeof(receiveBuffer_[0]), &cfg) != ESP_OK) {
|
||||
rmt_disable(channel_); return false;
|
||||
}
|
||||
#else
|
||||
(void)expectedHz;
|
||||
#endif
|
||||
running_ = true; return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user