I tried to use RMT to capture and decode PPM signal popular in RC models. It is simple protocols where values are presented as low pulse. Low pulse can be in range 700-2300us, and high pulse is typically 300us.
All looks really simple and RMT should works for this but I get strange results, because to receive correct low value length I need to sum:
duration1 + duration0 - but why ?
For low pulse signal 1500us and high pulse 300us I got duration1 = 1200 and duration0 = 300. Strange is also when I change signal configuration and space between low pulses is eg. 250us I got results:
duration1 is 1250 and duration0 is about 250 - again sum is correct, but still don't know why I need to sum both pulses.
Here is full code for receiver.
Code: Select all
static const char *TAG = "ppmrx";
#define RMT_RX_CHANNEL 0 /*!< RMT channel for receiver */
#define RMT_RX_GPIO_NUM 2 /*!< GPIO number for receiver */
#define RMT_CLK_DIV 10 /*!< RMT counter clock divider */
#define RMT_TICK_US (80000000/RMT_CLK_DIV/1000000) /*!< RMT counter value for 10 us.(Source clock is APB clock) */
#define PPM_IMEOUT_US 3500 /*!< RMT receiver timeout value(us) */
/**
* @brief PPM receiver task
*
*/
static void ppm_rx_task(void *pvParameter)
{
int channel = RMT_RX_CHANNEL;
RingbufHandle_t rb = NULL;
//get RMT RX ringbuffer
rmt_get_ringbuf_handle(channel, &rb);
rmt_rx_start(channel, 1);
while(rb) {
size_t rx_size = 0;
int channels;
//try to receive data from ringbuffer.
//RMT driver will push all the data it receives to its ringbuffer.
//We just need to parse the value and return the spaces of ringbuffer.
rmt_item32_t* item = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, 1000);
if(item) {
channels = (rx_size / 4) - 1;
printf("PPM RX %d (%d) channels: ", channels, rx_size);
for (int i = 0; i < channels; i++)
printf("%04d ", ((item+i)->duration1 + (item+i)->duration0) / RMT_TICK_US);
printf("\n");
vRingbufferReturnItem(rb, (void*) item);
} else {
break;
}
}
vTaskDelete(NULL);
}
void ppmrx_init(void)
{
rmt_config_t rmt_rx;
rmt_rx.channel = RMT_RX_CHANNEL;
rmt_rx.gpio_num = RMT_RX_GPIO_NUM;
rmt_rx.clk_div = RMT_CLK_DIV;
rmt_rx.mem_block_num = 1;
rmt_rx.rmt_mode = RMT_MODE_RX;
rmt_rx.rx_config.filter_en = true;
rmt_rx.rx_config.filter_ticks_thresh = 100;
rmt_rx.rx_config.idle_threshold = PPM_IMEOUT_US * (RMT_TICK_US);
rmt_config(&rmt_rx);
rmt_driver_install(rmt_rx.channel, 1000, 0);
xTaskCreate(ppm_rx_task, "ppm_rx_task", 2048, NULL, 10, NULL);
ESP_LOGI(TAG, "PPM RX initialized\n");
}