RMT, 1-Wire Slave and timing woes in general

pmckeon
Posts: 9
Joined: Sat Aug 18, 2018 9:18 am

RMT, 1-Wire Slave and timing woes in general

Postby pmckeon » Wed Aug 12, 2020 10:40 am

I have a project that requires me to emulate a simple 1-Wire Slave device.

HoHo, no problem pmckeon! I hear you say, just use https://github.com/orgua/OneWireHub

Except it's part of an existing project I've mostly completed in the native Espressif IDF and that library was made to work with the Arduino framework. I did try compiling it under the IDF tools but there were far too many compiler errors and warnings than I want to deal with right now in trying to port it over, plus it's a bit heavy for my needs anyway.

Fortunately 1-Wire protocol is relatively simple, the timing as I have discovered not so much.

I had something that sort of worked using a pin interrupt and high resolution timers but I found overheads of some functions and calls were causing me to miss the 60μs time-slot required by the Master device.

So, similar to the above library and it's initial discussion here:
viewtopic.php?t=3655

I'm trying to use the RMT peripheral and have setup a test case to read the 1-Wire bus but I either get an initial burst of random data or simply no data at all instead of the expected Reset pulse of about 480-500μs.

I have no idea if it's the way I've setup the RMT configuration or something else entirely.

Code: Select all

static void gun_owbrmt_task(void *pvParameter)
{
    uint32_t length = 0;
    RingbufHandle_t rb = NULL;
    rmt_item32_t *items = NULL;

    rmt_config_t rmt_conf;
    rmt_conf.channel = RMT_CHANNEL_0;
    rmt_conf.rmt_mode = RMT_MODE_RX;
    rmt_conf.gpio_num = GPIO_OWBSLAVE_INPUT;
    rmt_conf.mem_block_num = 1;
    rmt_conf.flags = 0;
    rmt_conf.clk_div = 80;

    rmt_rx_config_t rx_conf;
    rx_conf.filter_en = true;
    rx_conf.filter_ticks_thresh = 30;
    rx_conf.idle_threshold = 77;
    rmt_conf.rx_config = rx_conf;
    rmt_config(&rmt_conf);
    rmt_driver_install(RMT_CHANNEL_0, 1000, 0);

    rmt_get_ringbuf_handle(RMT_CHANNEL_0, &rb);
    rmt_rx_start(RMT_CHANNEL_0, true);

    while(rb)
    {
        items = (rmt_item32_t *) xRingbufferReceive(rb, &length, portMAX_DELAY);
        length /= 4;

        for(int i=0; i < length; i++)
        {
            ESP_LOGI(TAG, "[%d]Pulse (%d), [%d]Pulse (%d)\n", items[i].level0, items[i].duration0, items[i].level1, items[i].duration1);
        }

        vRingbufferReturnItem(rb, (void *) items);
    }

    ESP_LOGE(TAG, "gun_owbrmt_task quit unexpectedly!");
    rmt_driver_uninstall(RMT_CHANNEL_0);
    vTaskDelete(NULL);
}

pmckeon
Posts: 9
Joined: Sat Aug 18, 2018 9:18 am

Re: RMT, 1-Wire Slave and timing woes in general

Postby pmckeon » Thu Aug 13, 2020 7:45 am

After a break and a bit of a rethink I finally got it working, though slightly puzzled why it didn't in previous tests.

I didn't initially fully understand the relationship between rmt_conf.clk_div and tick rate and now I do, I was never sure on the correct values to set for rx_conf.filter_ticks_thresh and rx_conf.idle_threshold, I mostly just copied values from other similar projects.

I now under stand that with APB Clock of 80MHz and Clock Divider of 80MHz = tick rate of 1μs so exact values can be used for the two threshold parameters. I got confused because elsewhere on this forum someone said it was 1ms not 1μs.

The second area of confusion was that I assumed based on the documentation that rx_conf.filter_en applied to both threshold values, now it seems in testing that it only effects rx_conf.filter_ticks_thresh. So disabling it didn't yield any different result.

The final solution was to set rx_conf.idle_threshold to > 500 and it started working, but I'm fairly certain in some of my early tests I had it set at 1000 and I still didn't receive any pulses.

Either way it's working and I'm happy.

Who is online

Users browsing this forum: MicroController and 90 guests