• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Задержки os_event

sharikov

Active member
Планирую использовать os_event для посылки сообщений от обработчика прерывания.
Провел замеры времени от посылки до получения и чешу репу.

Код такой:
Код:
void mcp_int_handler(void* *para)
{
    uint32_t time = system_get_time();
    uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);


    if (gpio_status & BIT(MCPINT_PIN))
    {
        //disable interrupt
        //gpio_pin_intr_state_set(GPIO_ID_PIN(MCPINT_PIN), GPIO_PIN_INTR_DISABLE);
        //clear interrupt status
        GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(MCPINT_PIN));

        mcpintisr_var ++;
        system_os_post(USER_TASK_PRIO_1,MCP_INT, time);
    }
}

uint32_t maxdeltat = 0;
void mcp_poll_task(os_event_t *e)
{
    uint32 i, d;
    switch(e->sig)
    {
    case MCP_INT:
        i=system_get_time();
        d=(i >= e->par)? i - e->par : e->par - i;
        if (maxdeltat < d)
            maxdeltat = d;
        ets_uart_printf("mcp_poll_task: MCP_INT event \t delta T=%d \t max=%d\n", d, maxdeltat);
    break;
    default:
        ets_uart_printf("mcp_poll_task: unknown event\n");
    }  // switch(e->sig)
}

void ICACHE_FLASH_ATTR mcp_poll_task_init(void)
{
    system_os_task(mcp_poll_task, USER_TASK_PRIO_1, mcpQueue, sizeof (mcpQueue)/sizeof(os_event_t ));
    system_os_post(USER_TASK_PRIO_1, 0 , 0);
}

//Init function
void ICACHE_FLASH_ATTR user_init()
{
    uint8 rw_buffer[16];
    uint8 w_buffer[16];
    uint32_t i, i2;

    system_timer_reinit();
    set_cpu_freq(0);

    uart_init(BIT_RATE_230400, BIT_RATE_230400);
    os_delay_us(10000);

    ets_uart_printf("Current 'heap' size: %d bytes\n", system_get_free_heap_size());

    user_gpio_init();
    mcp_poll_task_init();
    hspi_init();
    ets_uart_printf("MCP reset = %d\n", mcp251x_hw_reset());

}
Результаты при редких импульсах на входе прерывания:
mcp_poll_task: MCP_INT event delta T=5 max=6
mcp_poll_task: MCP_INT event delta T=4 max=6
mcp_poll_task: MCP_INT event delta T=5 max=6
mcp_poll_task: MCP_INT event delta T=5 max=6
mcp_poll_task: MCP_INT event delta T=5 max=6
mcp_poll_task: MCP_INT event delta T=4 max=6
mcp_poll_task: MCP_INT event delta T=4 max=6
mcp_poll_task: MCP_INT event delta T=4 max=6
mcp_poll_task: MCP_INT event delta T=5 max=6
mcp_poll_task: MCP_INT event delta T=5 max=6
mcp_poll_task: MCP_INT event delta T=4 max=6
mcp_poll_task: MCP_INT event delta T=5 max=6
mcp_poll_task: MCP_INT event delta T=4 max=6
mcp_poll_task: MCP_INT event delta T=689 max=689
mcp_poll_task: MCP_INT event delta T=5 max=689
mcp_poll_task: MCP_INT event delta T=4 max=689
mcp_poll_task: MCP_INT event delta T=4 max=689

Тут в одном случае ос жевала сопли почти 700мс.

Теперь частые импульсы (дребезг от пинцета). Совсем весело:
попытка номер 1
mcp_poll_task: MCP_INT event delta T=4 max=689
mcp_poll_task: MCP_INT event delta T=2164 max=2164
mcp_poll_task: MCP_INT event delta T=4599 max=4599
mcp_poll_task: MCP_INT event delta T=7005 max=7005
mcp_poll_task: MCP_INT event delta T=9134 max=9134
попытка номер 2
mcp_poll_task: MCP_INT event delta T=4 max=9134
mcp_poll_task: MCP_INT event delta T=4 max=9134
mcp_poll_task: MCP_INT event delta T=5 max=9134
mcp_poll_task: MCP_INT event delta T=5 max=9134
mcp_poll_task: MCP_INT event delta T=4 max=9134
mcp_poll_task: MCP_INT event delta T=2198 max=9134
mcp_poll_task: MCP_INT event delta T=4612 max=9134
mcp_poll_task: MCP_INT event delta T=7096 max=9134
mcp_poll_task: MCP_INT event delta T=9452 max=9452
mcp_poll_task: MCP_INT event delta T=11855 max=11855
mcp_poll_task: MCP_INT event delta T=14365 max=14365
mcp_poll_task: MCP_INT event delta T=14664 max=14664

В случае частых испульсов есть предположение что тормозит ets_uart_printf.
 

pvvx

Активный участник сообщества
В случае частых испульсов есть предположение что тормозит ets_uart_printf.
ets_uart_printf и os_printf всегда встает, когда tx fifo полный и ожидает для вставки следующего символа. Т.е. после 127 символов идет посимвольная передача. Вы успешно измеряли вывод строки на BIT_RATE_230400 :)
Тут в одном случае ос жевала сопли почти 700мс.
Ага, а тут mcp_poll_task: MCP_INT event delta T=14664 max=14664 - 15 секунд? :)
 
Последнее редактирование:

sharikov

Active member
ets_uart_printf и os_printf всегда встает, когда tx fifo полный и ожидает для вставки следующего символа. Т.е. после 127 символов идет посимвольная передача. Вы успешно измеряли вывод строки на BIT_RATE_230400
Уберу ets_uart_printf и проверю еще раз.

Ага, а тут mcp_poll_task: MCP_INT event delta T=14664 max=14664 - 15 секунд?
14664 микросекунды. Выше тоже 700мкс а не 700мс.
 

pvvx

Активный участник сообщества
Тогда в чем вопрос? Не хватает 80MHz CLK CPU?
Use SDK 0.9.6:
bool system_overclock(void); // if(system_get_cpu_freq()==80) { cpu_overclock = 1, system_update_cpu_freq(160) }
bool system_restoreclock(void); // if(cpu_overclock) system_update_cpu_freq(80) else return 0
bool system_update_cpu_freq(uint32 cpu_freq); // 80 или 160 // ets_update_cpu_frequency + bit0 0x3FF00014
uint32 system_get_cpu_freq(void); // ets_get_cpu_frequency
Задержку между post и task можно сделать любую - достаточно на прерывание таймера повесить процедуру побольше и частоту прерываний от таймера задать менее 2us :)
А проще вообще запретить прерывания и вырубить WDT и крутить вечный цикл. Тогда task вообще никогда не отработает :)
Вычисление максимальной задержки между post и task не имеет никакого смысла без работающей итоговой задачи. На пустом SDK она одна, с задачей, нагружающей CPU - другая. Очень сильно зависит от кеширования flash (распределения текущего исполняемого кода в flah) и к какой периферии обращается ALU CPU. И т.д.. В итоге выйдет, что сегодня такая, а завтра другая - т.е. перетранслировали и поменяли распределение кода в flash :)
 
Последнее редактирование:

sharikov

Active member
Переделал. Код:
Код:
void mcp_int_handler(void* *para)
{
    uint32_t time = system_get_time();
    uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);


    if (gpio_status & BIT(MCPINT_PIN))
    {
        //disable interrupt
        gpio_pin_intr_state_set(GPIO_ID_PIN(MCPINT_PIN), GPIO_PIN_INTR_DISABLE);
        //clear interrupt status
        GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(MCPINT_PIN));

        mcpintisr_var ++;
        system_os_post(USER_TASK_PRIO_1,MCP_INT, time);
    }
}

uint32_t maxdeltat = 0;
uint32_t deltatcounter=0;
void mcp_poll_task(os_event_t *e)
{
    uint32_t i, d;
    switch(e->sig)
    {
    case MCP_INT:
        i=system_get_time();
        deltatcounter++;
        d=(i >= e->par)? i - e->par : e->par - i;
        if (maxdeltat < d)
            maxdeltat = d;
        gpio_pin_intr_state_set(GPIO_ID_PIN(MCPINT_PIN), GPIO_PIN_INTR_NEGEDGE /*GPIO_PIN_INTR_LOLEVEL*/);
    break;
    default:
        ets_uart_printf("mcp_poll_task: unknown event\n");
    }  // switch(e->sig)
}

extern uint32_t maxdeltat;
extern uint32_t deltatcounter;
LOCAL os_timer_t print_mcp_stat_timer;
LOCAL void ICACHE_FLASH_ATTR print_mcp_stat_timer_cb(void )
{
    ets_uart_printf("Max delta T = %d \t counter = %d\n", maxdeltat, deltatcounter);
}

//Init function
void ICACHE_FLASH_ATTR user_init()
{
    uint32_t i, i2;

    system_timer_reinit();
    set_cpu_freq(0);

    uart_init(BIT_RATE_230400, BIT_RATE_230400);
    os_delay_us(10000);

    ets_uart_printf("Current 'heap' size: %d bytes\n", system_get_free_heap_size());

    user_gpio_init();
    mcp_poll_task_init();
    hspi_init();
    ets_uart_printf("MCP reset = %d\n", mcp251x_hw_reset());

    os_timer_disarm(&print_mcp_stat_timer);
    os_timer_setfn(&print_mcp_stat_timer, (os_timer_func_t *)print_mcp_stat_timer_cb, (void *)0);
    os_timer_arm(&print_mcp_stat_timer, 1000, 1);
}
Результаты:
Прерывания по спаду, источник сигнала дребезг от пинцета.
Max delta T = 0 counter = 0
Max delta T = 0 counter = 0
Max delta T = 0 counter = 0
Max delta T = 6 counter = 1
Max delta T = 6 counter = 5
Max delta T = 6 counter = 25
Max delta T = 6 counter = 41
Max delta T = 6 counter = 42
Max delta T = 6 counter = 63
Max delta T = 6 counter = 105
Max delta T = 6 counter = 116
Max delta T = 6 counter = 136
Max delta T = 6 counter = 196
Max delta T = 6 counter = 205
Max delta T = 6 counter = 230
Max delta T = 6 counter = 256
Max delta T = 6 counter = 256
Max delta T = 6 counter = 262
Max delta T = 6 counter = 262
Max delta T = 6 counter = 262
Max delta T = 11 counter = 279
Max delta T = 14 counter = 322
Max delta T = 14 counter = 331
Max delta T = 1153 counter = 347
Max delta T = 1153 counter = 351
Max delta T = 1153 counter = 382
Max delta T = 1153 counter = 400
Max delta T = 1153 counter = 417
Max delta T = 1153 counter = 493
Max delta T = 1153 counter = 507
Max delta T = 1153 counter = 560
Max delta T = 1153 counter = 638
Max delta T = 1153 counter = 650
Max delta T = 1153 counter = 670
Max delta T = 1153 counter = 677
Max delta T = 1153 counter = 677


А если включить прерывания по уровню получается так:

Прерывания по уровню - непрерывные пока вход замкнут на землю.
Max delta T = 0 counter = 0
Max delta T = 0 counter = 0
Max delta T = 1075 counter = 93429
Max delta T = 1580 counter = 212404
Max delta T = 1621 counter = 331501
Max delta T = 1621 counter = 451244
Max delta T = 1621 counter = 570142
Max delta T = 1621 counter = 689087
Max delta T = 1623 counter = 809099
Max delta T = 1624 counter = 927999
Max delta T = 1624 counter = 997410
Max delta T = 1624 counter = 1033379
Max delta T = 1624 counter = 1033379
Max delta T = 1624 counter = 1033379
Max delta T = 1624 counter = 1033379
Max delta T = 1624 counter = 1071130
Max delta T = 1667 counter = 1189830
Max delta T = 1667 counter = 1309925
Max delta T = 1667 counter = 1428837
Max delta T = 1667 counter = 1547665
Max delta T = 2885 counter = 1667487
Max delta T = 2885 counter = 1726766
Max delta T = 2885 counter = 1726766
Max delta T = 2885 counter = 1726766
Max delta T = 2885 counter = 1726766

Тогда в чем вопрос?
Мне нужно выполнить чтение блока данных по spi не позднее 100 мкс после прерывания по входу GPIO. Данные потом отпрвляю по tcp (tcp2com), если tcp не поятнет то по udp (это хуже).
Сейчас проверяю вариант с посылкой сообщения функции поллинга.
Если по скорости вариант с сообщением не пройдет придется сооружать развесистые обработчики прерываний. Они по времени не длинные но сильно ветвящиеся.
Если ос блокирует прерывания более чем на 100 мкс моя задача отменяется. Будет потеря данных а такой продукт никому не нужен.
Цифра 100 мкс приблизительная но порядок величины именно такой.
 

pvvx

Активный участник сообщества
Цифра 100 мкс приблизительная но порядок величины именно такой.
Вы же видели, что любой os_printf останавливает всё. Замена функций вывода в них не гарантирует, что никто больше из ROM и SDK не полезет выводить в UART и на том всё и встанет. Там очень много служебных сообщений во все дыры и у них много безусловных выводов в UART и прочего :) Там много приветиков от Espressif. Уровень приоритета у task и timer очень низкий. Ваяйте свой оработчик на hard прерывании таймера - он стабилен. Для этого ссылку и давал... У вас задача то однозадачная и одного прерывания таймера для распределения там за глаза. Получите типа RTOS на две задачи - SDK будет крутится сама по себе, а процедуры обслуживания внешних ног в реалтайм (с всегда фиксированным временем отклика) - всегда успеете сказать внешнему что соединение прервано или там затор :).
А потеря данных всё равно будет - путь соединения от устройства до получателя неподвластен :) и время подтверждения пакетов TCP неизвестно, а стек TCP короток... повторные вхождения на передачу и в прочие функции SDK недопустимы - там не многозадачка. С вашей задачей вам сразу светит отказ от espconn и переход на работу напрямую с Lwip :)
 
Последнее редактирование:

sharikov

Active member
Ваяйте свой оработчик на hard прерывании ...
Написал тест на прерываниях: какое-то время работает а потом перестает срабатывать os_timer, мои прерывания при этом продолжают работать.
От периода следования прерываний зависит только время до отвала. При периоде прерываний 18us зависло через 794 секунды.
Тест в прерывании по низкому уровню gpio запускает обмен по spi и запрещает прерывания от gpio.
Обработчик прерывания от spi читает принятый байт и разрешает прерывания от gpio.
Параллельно раз в секунду тикает периодический os_timer - выводит текст в консоль.
Код обработчиков прерываний:
Код:
/*
* обработчик прерывания от выхода int mcp2515
* активен ТОЛЬКО когда на шине spi нет операций
*/
void mcp_int_handler(void* *para)
{
    //uint32_t time = system_get_time();
    uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);

    if (gpio_status & BIT(MCPINT_PIN))
    {
        // запрещаем прерывания по входу gpio
        // они будут разрешены после завершения обмена по spi
        gpio_pin_intr_state_set(GPIO_ID_PIN(MCPINT_PIN), GPIO_PIN_INTR_DISABLE);
        // сбрасываем флаг прерывания gpio
        GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(MCPINT_PIN));

        // разрешаем прерывания hspi
        CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_TRANS_DONE);  // сбросим флаг
        SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_TRANS_DONE_EN); // разрешаем прерывания hspi

        // запускаем автомат выгрузки принятых данных из mcp2515
        // первая операция - чтение регистра статуса
        mcp251x.mcp_rx_state = RXSTATE_RDSTAT_S;
        // выдаем команду READ STATUS
        // чтение статуса выполняется в обработчике прерываний hspi
        hspi_cr_start(INSTRUCTION_READ_STATUS, 1);
    }
}

/*
* обработчик прерываний hspi
* осуществляет выгрузку принимаемых данных из mcp2515 в кольцевой буфер
*/
void hspi_int_handler(void* *para)
{
    enum spi_rx_state temp_rx_state;  // локальная копия volatile переменной
    uint32_t regvalue;

    if(READ_PERI_REG(0x3ff00020) & BIT4)
    {
        //following 3 lines is to clear isr signal
        CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI), 0x3ff);
    }
    else
        if (READ_PERI_REG(0x3ff00020) & BIT7)
        { //bit7 is for hspi isr,
            regvalue=READ_PERI_REG(SPI_SLAVE(HSPI));
            CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),
                    SPI_TRANS_DONE_EN |
                    SPI_SLV_WR_STA_DONE_EN |
                    SPI_SLV_RD_STA_DONE_EN |
                    SPI_SLV_WR_BUF_DONE_EN |
                    SPI_SLV_RD_BUF_DONE_EN);

            temp_rx_state = mcp251x.mcp_rx_state;
            switch (temp_rx_state)
            {
            // завершено чтение статуса
            case RXSTATE_RDSTAT_S:
                regvalue = READ_PERI_REG(SPI_W0(HSPI));
                //ets_uart_printf("RDSTAT_S\t 0x%x\n", regvalue);
                goto end_rx;

            // конец обмена по spi
            case RXSTATE_IDLE :
end_rx:
                //ets_uart_printf("IDLE\n");
                mcp251x.mcp_rx_state = RXSTATE_IDLE ;
                //system_os_post(USER_TASK_PRIO_1,MCP_INT, 0);
                // запрещаем все прерывания hspi
                CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),
                    SPI_TRANS_DONE_EN | SPI_SLV_WR_STA_DONE_EN |
                    SPI_SLV_RD_STA_DONE_EN | SPI_SLV_WR_BUF_DONE_EN |
                    SPI_SLV_RD_BUF_DONE_EN     );

                // сбрасываем флаг прерывания gpio
                GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(MCPINT_PIN));
                // разрешаем прерывание gpio
                gpio_pin_intr_state_set(GPIO_ID_PIN(MCPINT_PIN),
                    /*GPIO_PIN_INTR_NEGEDGE*/ GPIO_PIN_INTR_LOLEVEL);
                break;

            // ловушка недействительных состояний
            default:
                ets_uart_printf("default\n");
                goto end_rx;
            }  // switch
        }
}
У меня есть сомнение, не возникает ли рекурсия при повторных разрешениях прерывания gpio. Прерывание по уровню (мне так удобнее).
 

pvvx

Активный участник сообщества
Написал тест на прерываниях: какое-то время работает а потом перестает срабатывать os_timer, мои прерывания при этом продолжают работать.
os_timer при повторной загрузке (arm) пишет сообщение в порт и идет на вечный цикл while(1); чем перезагружает систему по WDT.
У меня есть сомнение, не возникает ли рекурсия при повторных разрешениях прерывания gpio. Прерывание по уровню (мне так удобнее).
Это сказать никто не может, кроме того, кто писал обработку :).
 

sharikov

Active member
Это сказать никто не может, кроме того, кто писал обработку
Упростил тест до циклического обмена только по hspi в прерывании. hspi сам по себе работает стабильно с циклом обращений 5,6us (1,6us обмен по spi и 4us обработчик прерывания).
Добавление в работу прерывания по низкому уровню gpio все рушит.
Нужны идеи как избежать рекурсии при разрешении прерывания по уровню gpio в обработчике прерывания hspi. Поскольку прерывание gpio у меня настроено по уровню оно возникает сразу в момент разрешения и видимо обработчик spi прерывается обработчиком gpio.
 

pvvx

Активный участник сообщества
Упростил тест до циклического обмена только по hspi в прерывании. hspi сам по себе работает стабильно с циклом обращений 5,6us (1,6us обмен по spi и 4us обработчик прерывания).
Добавление в работу прерывания по низкому уровню gpio все рушит.
Нужны идеи как избежать рекурсии при разрешении прерывания по уровню gpio в обработчике прерывания hspi. Поскольку прерывание gpio у меня настроено по уровню оно возникает сразу в момент разрешения и видимо обработчик spi прерывается обработчиком gpio.
Расставить приоритеты прерываний и/или запрещать их вовремя. Тут методов много - однозначно сказать нечего, но вход в аппаратное прерывание идет через OS обработчик вектора и рекурсия может быть неизбежна при неверных настройках... Т.е. вы не можете запретить прерывание в первых командах обработки этого прерывания.
 

sharikov

Active member
Т.е. вы не можете запретить прерывание в первых командах обработки этого прерывания.
В моем случае нужно запретить внутри обработчика прерывания и разрешить при выходе.
Сегодня точно убедился что это вложенные прерывания. Прерывание от GPIO возникает в момент обработки прерывания SPI.
Получается что в обработчике прерываний нельзя разрешать чужие прерывания - они могут сработать сразу же, возникнут вложенные прерывания и чип зависнет.
 

pvvx

Активный участник сообщества
В моем случае нужно запретить внутри обработчика прерывания и разрешить при выходе.
Сегодня точно убедился что это вложенные прерывания. Прерывание от GPIO возникает в момент обработки прерывания SPI.
Получается что в обработчике прерываний нельзя разрешать чужие прерывания - они могут сработать сразу же, возникнут вложенные прерывания и чип зависнет.
Ну не зависнет, а просто неверный алго :) Это решается приоритетами прерываний.
Почему вам не сделать прерывание по фронту и решить всё флагами (семафорами-светофорами :) )?
Причина интереса у меня в том, что вы решаете тему TCP2SPI. Вроде, аналогичные решения есть у http://www.usriot.com/ а у меня весит эта тема
 
Последнее редактирование:

sharikov

Active member
Это решается приоритетами прерываний.
Почему вам не сделать прерывание по фронту и решить всё флагами (семафорами-светофорами :) )?
Причина интереса у меня в том, что вы решаете тему TCP2SPI. Вроде, аналогичные решения есть у http://www.usriot.com/ а у меня весит эта тема
Еще бы понять как менять приоритет прерываний в рамках ограничений SDK и ROM bios.
По фронту есть риск пропустить прерывание. Также при работе по фронту сохраняется невозможность разрешения прерываний gpio из обработчика прерваний spi.
Я решаю тему CAN-bus 2 WiFi. Частный случай это CAN-bus <-> TCP2COM, работа по протоколу Canhacker (оно же slcan).
Кан контроллер mcp2515 подключен к hspi, выход int заведен на gpio.
На шине кан максимальный темп прихода пакетов по моим подсчетам составляет 55мкс. В mcp есть 2 буфера, т.е надо реагировать за 100мкс максимум с учетом времени на обмен данными. Это только прием без учета затрат времени на передачу.
Задержки посылки события в основную программу исключают работу с mcp из основной программы, нужно весь обмен с кан контроллером запихивать в прерывания spi.
 

pvvx

Активный участник сообщества
Еще бы понять как менять приоритет прерываний в рамках ограничений SDK и ROM bios.
От SDK это не зависит.
По фронту есть риск пропустить прерывание. Также при работе по фронту сохраняется невозможность разрешения прерываний gpio из обработчика прерываний spi.
Не считаю, что можно потерять прерывание. Контроллер запоминает что прерывание взведено, а разрешение его запускает на исполнение. Если решать флагами - то-же самое. Прервался и пометил. Хотите отрабатывайте, хотите не отрабатывайте.
Я решаю тему CAN-bus 2 WiFi. Частный случай это CAN-bus <-> TCP2COM, работа по протоколу Canhacker (оно же slcan).
Кан контроллер mcp2515 подключен к hspi, выход int заведен на gpio.
На шине кан максимальный темп прихода пакетов по моим подсчетам составляет 55мкс. В mcp есть 2 буфера, т.е надо реагировать за 100мкс максимум с учетом времени на обмен данными. Это только прием без учета затрат времени на передачу.
Задержки посылки события в основную программу исключают работу с mcp из основной программы, нужно весь обмен с кан контроллером запихивать в прерывания spi.
Задача очень время зависимая от качества соединения по TCP. В специальном бункере с экранами от всего мира работать будет :)
Есть большие проблемы с дуплексом, при мелких пакетах TCP. Будет очень низкий трафик - порядок до 10килобайт туда-сюда в секунду. Условно считайте, что у вас N передач по WiFi в секунду. N*размер пакета и есть трафик. Сбои вызывают повторы и согласования - следовательно трафик ещё падает и значительно, т.к. N у нас не большое на ESP8266 при дуплексе. Тем более оно стробированное-синхронное - если согласуете WiFi пакеты с TCP пакетами, когда каждый переданный пакет подтверждает принятый и т.д. по цепочке - это и есть максимальный трафик.
А так задача вроде просматривается - это случаем не чтение ЭБУ или как-там в автомашине? :) BT коробочка на разъем разве не устраивает?
Не ясно одно - почему используется mcp2515? Что не поставить MCU с набортным CAN? Цена то одинакова...
STM32F103, PIC24HJ...
 
Последнее редактирование:

sharikov

Active member
Задача очень время зависимая от качества соединения по TCP. В специальном бункере с экранами от всего мира работать будет :)
Есть большие проблемы с дуплексом, при мелких пакетах TCP. Будет очень низкий трафик - порядок до 10килобайт туда-сюда в секунду. Условно считайте, что у вас N передач по WiFi в секунду. N*размер пакета и есть трафик. Сбои вызывают повторы и согласования - следовательно трафик ещё падает и значительно, т.к. N у нас не большое на ESP8266 при дуплексе. Тем более оно стробированное-синхронное - если согласуете WiFi пакеты с TCP пакетами, когда каждый переданный пакет подтверждает принятый и т.д. по цепочке - это и есть максимальный трафик.
А так задача вроде просматривается - это случаем не чтение ЭБУ или как-там в автомашине?
Не ясно одно - почему используется mcp2515? Что не поставить MCU с набортным CAN? Цена то одинакова...
Дуплекс на максимальной скорости кан не вырисовывается уже по пропускной способности spi интерфейса. Имеются ввиду не голые мегабиты spi а с учетом передачи команд и чтения статуса. mcp2515 - контроллер очень плохой, возможно самый плохой кан контроллер из всех производимых.
минимально что хочется получить - однонаправленный обмен (прием или передача) без потери пакетов в "бункере с экранами". И нормальную работу на низких скоростях.
mcp2515 используется чтобы свести к минимуму количество контроллеров к которым надо писать прошивку.
Автомобили для меня не основное, у меня прицел на автомтатику - CanOpen.
Хотя... в esp есть уарт а значит теоретически можно прикрутить еще и K-line...
 

pvvx

Активный участник сообщества
И нормальную работу на низких скоростях.
mcp2515 используется чтобы свести к минимуму количество контроллеров к которым надо писать прошивку.
MCU нужен для организации буфера и протокола связи с ESP8266. ПО на нем выходит не сложное - паковать пакеты CAN в потоковую передачу и держать буфера. Для этого наверно лучше будет тот MCU, который дешевле и у которого больше набортной ОЗУ - типа STM32... Я тоже в последнее время занимаюсь автоматикой всяких промышленных станций, но CAN использую только со своими собственными протоколами... MCP2515 мы стаивили когда ещё MCU со встроенным CAN были дороги или сложно-доступны и сразу от них отказались с доступностью PIC18 с CAN...
 
Последнее редактирование:

pvvx

Активный участник сообщества
Откопал свою древнюю плату, оставшуюся от отладки какого-то устройства почти десять лет назад :). На неё стоит PIC18F258 + SI9200. Покопал архивы и нашел свою прошивку для USB2CAN переходника (там был PIC18 + FT232). Изменил (!) и странслировал на MPLAB X IDE v2.30 и прошил PICkit 3 в ту макетку! :eek:
Подключил RX-TX к ESP-8266 со своей Web-свалкой и запустил - работает! Благо был ещё свой отладочный монитор (тоже дремучий - на паскале) для соединения по TCP и передачей-приемом CAN по почти аналогичному формату, правда не для той версии, а для другой (подписи не те к пакетам CAN ставит :) )... И в наличии было два устройства, переговаривающихся по CAN :) Короче всё работает - снифирит любые пакеты на шине CAN на задаваемой скорости и передает всё что угодно туды-сюды, но это сплошная некромансия!
canxxxx.gif
Код:
TCP Connected to 192.168.4.1 : 12345
Tx: 55,02,30,80 - Открыть канал
Blk: 55,87,40,40,41,14,03,00,00,C0 INF
Blk: 55,A7,40,40,40,05,9C,A4,0A,00 INF
Blk: 55,87,40,40,41,81,00,C0,00,00 INF
Blk: 55,A7,40,40,40,06,E1,19,03,00 INF
Blk: 55,A7,40,40,40,80,00,C0,00,00 INF
Blk: 55,87,40,40,41,0E,67,1A,BC,00 INF
Blk: 55,87,40,40,41,0D,69,0A,BC,00 INF
Tx: 55,90
Blk: 55,96,0B,0B,00,13,13,92,42 MAN_CMD_GET
Blk: 55,A7,40,40,40,0F,B7,3B,BC,00 INF
Blk: 55,87,40,40,41,09,65,C0,BC,00 INF
Blk: 55,A7,40,40,40,18,00,00,BC,00 INF
Blk: 55,87,40,40,41,0A,00,00,BC,00 INF
Blk: 55,A7,40,40,40,17,00,00,BC,00 INF
Blk: 55,87,40,40,41,0B,00,00,BC,00 INF
Blk: 55,A7,40,40,40,16,00,00,BC,00 INF
Blk: 55,87,40,40,41,10,FC,3C,BC,00 INF
Blk: 55,A7,40,40,40,15,00,00,BC,00 INF
Blk: 55,87,40,40,41,07,00,00,BC,00 INF
Blk: 55,A7,40,40,40,01,00,00,00,00 INF
Blk: 55,87,40,40,41,08,00,00,BC,00 INF
Blk: 55,A7,40,40,40,13,03,00,00,C0 INF
Blk: 55,87,40,40,41,11,00,00,BC,00 INF
Blk: 55,A7,40,40,40,00,00,FF,00,00 INF
Blk: 55,87,40,40,41,0C,00,00,BC,00 INF
Blk: 55,A7,40,40,40,03,15,06,00,00 INF
Blk: 55,87,40,40,41,02,00,00,00,00 INF
Blk: 55,A7,40,40,40,04,F9,01,00,00 INF
TCP Disconnected. BytesReceived:352, BytesSent:6
Если что из этого дремучего набора надо - в личку :)
Только где счас взять PIC18F258 - я не знаю :) Их в своё время заменили на PIC18F2580... :)
 
Последнее редактирование:
Сверху Снизу