Page 1 of 1

Problem with RMT receiver

Posted: Tue Jan 23, 2018 7:20 am
by marbalon
Hi,
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");
}

Re: Problem with RMT receiver

Posted: Tue Jan 23, 2018 11:59 am
by WiFive
The information on this type of signal is encoded as the length of a pulse plus the length of the following pause.
https://sourceforge.net/p/arduinorclib/ ... %20Signal/

Re: Problem with RMT receiver

Posted: Tue Jan 23, 2018 12:27 pm
by marbalon
Pulses are usually around 500 microseconds in length, the pauses somewhere between 500 and 1500 microseconds. Add those together and you get channel values of 1000 to 2000 microseconds
Wrr, so everything is OK, sorry for this question.