• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

SDIO Client

Grem_line

New member
Хочу приспособить ESP8266 для передачи по WiFi потокового видео. Требуется связать модуль с вычислителем для того, чтобы передавать/принимать пакеты данных. При этом задача одного ESP8266 - просто принимать пакеты от вычислителя и выдавать в виде UDP-пакетов другому ESP8266. Второй должен принимать WiFi UDP-пакеты и выдавать своему вычислителю. Скорость обмена модуля с вычислителем должна быть как можно большей (где-то 40-50 Мбит/с). Думаю задействовать SDIO, только не знаю как. Сейчас экспериментирую с SPI. Но скорости маловато. В режиме сервера на выдачу из ESP удалось получить среднюю скорость около 40 (частоту SPI ставлю 80МГц), в режиме сервера на прием не выходит больше 12 Мбит/с при частоте 40МГц (на 80 не работает), а в режиме SPI-slave вообще беда - начинает сбиваться на частоте SPI больше 5МГц.
В качестве вычислителей использую CubieBoard2 под RTOS собственной разработки. Одна цифрует камеру, жмет в h.264 и выдает, а вторая принимает, декодирует и выводит на монитор HDMI. Модули ESP8266 (NodeMCU) программирую через ARDUINO-IDE.
На FullHd (1920x1080@30) и связью c WiFi модулями по SPI имею периодические тормоза.

Пробовал работать с ESP32 - почему-то показалось хуже. И соединение устанавливает дольше и через раз, и по скорости медленнее.

Кто-нибудь знает, как использовать SDIO-Client в ESP8266 для передачи данных?
Подскажите, где найти примеры или что-то в этом духе...
 

pvvx

Активный участник сообщества
Сейчас экспериментирую с SPI. Но скорости маловато. В режиме сервера на выдачу из ESP удалось получить среднюю скорость около 40 (частоту SPI ставлю 80МГц), в режиме сервера на прием не выходит больше 12 Мбит/с при частоте 40МГц (на 80 не работает), а в режиме SPI-slave вообще беда - начинает сбиваться на частоте SPI больше 5МГц.
Предельная долговременная скорость передачи в TCP с Flash в режиме Web сервера у ESP8266 с CPU на 160 МГц, составляет 1.1 мегабайт в сек (80 МГц -> 800..900 килобайт/c). TCP имеет дуплексную передачу - на каждые 2 пакета приходит ACK. При полной 1 к 1 дуплексной загрузке и 80 МГц реальный поток может упасть ниже 600 килобайт в сек в одну сторону. Ограничение имеет большую зависимость от кол-ва принятых/переданных пакетов и размера пакетов. ESP8266 не успевает программно обрабатывать большое кол-во UDP пакетов, очень много пакетов WiFi вообще скипается в приемной и передающей части дров его WiFi.
У ESP8266 phy HT20, а у ESP-32 - HT40. Это дает ESP-32 предельный долговременный поток TCP при передаче в одну строну к 1.6 мегабайт в сек, с пиками в 1.8 МБ/сек.
Передача данных с flash ни как не влияет на данные скорости, а flash включена на SPI.
UART - влияет, из-за медленной возни CPU с регистрами UART через тормозной fifo шины и дурацких лишних команд CPU сброса кэш, которого у него нет, да синхронизации шин, которые кроме лишних тактов CPU ничего не делают. Шина то на периферию контроллеров у ESP8266 всего 26 МГц.
При устранении лишних команд правильными опциями компилятору UART работает и на 10 Мбит, но это занимает большую часть времени занятости CPU ESP8266 и предельный трансфер дров WiFi и LwIP страдает на 50%. SPI немного лучше (в 2 раза минимум), за счет меньшего кол-ва обращений через медленную шину к регистрам контроллера SPI для получения того-же соотношения кол-ва байт в потоке.
На HT20 никаких видео потоков в природе не встречается. Ну если только "видео" не 64x64 точки и пару бит яркости с сенсора мышки :)
ESP-32 вообще программный тормоз, если код и данные не лезут в кэш XIP. Уровень производительности падает примерно до 10 МГц ARM.
Та и у данного семейства ESP нет нормального описания и вообще DMA. Без многолетней специфически заточенной оптимизации под них простых задач их обгоняют любые другие MCU с частотами в десяток МГц. Беда в компоновке SoC со множественным просчетами и ошибками Espressif, а не в типе ядра CPU.
Помучаетесь годик, доведете поток UDP в одну сторону у ESP-32 до 2-х МБайт в сек с 5% потерей и перегревом чипа. Это показывают его тесты (iperf).
 
Последнее редактирование:

Алексей.

Active member
Grem_line,
Решал похожую задачу на esp32, уперся в неожиданные лаги, вроде и скорость нормальная, но лагает периодически без причины, на 264-ом кодеке можно принять часть запоздавших слайсов от предыдущего кадра, который уже восстановили с кривыми артефактами, и не все слайсы для текущего кадра и тоже восстановление дает неожиданные артефакты, в общем не продать решение.
а в режиме SPI-slave вообще беда - начинает сбиваться на частоте SPI больше 5МГц.
Пробовал работать с ESP32 - почему-то показалось хуже
На макете esp32 spi подключен слейвом проводами 15-20 см. работает на 12мегабит, беда закончилась когда таск работающий с spi запустил на первом ядре, на нулевом остались таски работающие с ip
 
Последнее редактирование:

Grem_line

New member
Предельная долговременная скорость передачи в TCP с Flash в режиме Web сервера у ESP8266 с CPU на 160 МГц, составляет 1.1 мегабайт в сек (80 МГц -> 800..900 килобайт/c).
Извините, не понял Вас. При чем тут TCP - я использую UDP пакеты для передачи видео по протоколу RTSP. Кроме того, мне вовсе не нужно забирать данные из Flash - данные поступают из внешнего контроллера по каналу SPI прямо в оперативную память ESP. Сейчас это сделано немного кривовато: ESP работает в режиме мастера, поэтому пришлось добавить лишний провод, по перепаду уровня на котором ESP узнает о наличии нового пакета, принимает его по SPI и выдает по WiFi в виде UDP-пакета. Сейчас все работает, но при больших объемах некоторые UDP-пакеты теряются. Получается, что система работает несколько секунд, потом происходит потеря и картинка замирает до прихода очередного ключевого кадра.
Мне думается, что проблема вызвана тем, что ключевые кадры не помещаются в один UDP-пакет, а при дроблении на сегменты приходят слишком часто - нужно попробовать вставить задержки между сегментами. Скорость передачи реально составляет около 8-9 МБит. После праздников буду пробовать.
 

Grem_line

New member
При выдаче UDP-пакетов вставил адаптивную задержку - чем длиннее пакет, тем больше. Все заработало более-менее прилично. Тем не менее, хотелось бы более быструю связь между ESP и вычислителем.
Так как же насчет SDIO-неужели никто не пробовал?
 

Алексей.

Active member
При чем тут TCP - я использую UDP пакеты для передачи видео по протоколу RTSP.
Это ваш выбор, rtsp кроме udp транспорта, есть ещё и tcp транспорт, с заголовком определяющим номер канала и длину данных.
Когда на esp32 в rtp потоке я терял udp пакеты, пробовал использовать tcp, потерь не стало, но лаги остались, забросил я его, медиатек как оказалось получше.
 

Grem_line

New member
Когда на esp32 в rtp потоке я терял udp пакеты, пробовал использовать tcp, потерь не стало, но лаги остались
Используйте механизм асинхронного обмена с подтверждением.
Как выяснилось, дело было не в бобине:)
Оказалось, что передача данных по WiFi на двух esp8266 идет абсолютно чисто, без каких-либо потерь пакетов. Я убедился в этом, добавив контроль целостности информации в принимающем esp.
Проблема обнаружилась в задаче приема пакетов SPI от esp в CubieBoard! Просто оказалось, что я запустил ее с более низким приоритетом, чем задачи декодирования и отображения :oops:
Простая установка наивысшего приоритета для этой задачи сходу решила все проблемы.
Вот уже третий час гоняю full-hd видео и пока ни одного сбоя.

Кстати, несмотря на то, что UDP-пакеты не требуют подтверждения, сама низкоуровневая передача любых адресных пакетов по WiFi осуществляется с подтверждением (и переотправкой пакета при отсутствии подтверждения). Поэтому не вижу смысла делать еще что-то вручную.
пробовал использовать tcp, потерь не стало, но лаги остались, забросил я его
Не наблюдаю (пока) никаких лагов, потерь, повторов и т.д. Правда, это esp8266. На esp32 у меня появились проблемы сразу: подключение к точке доступа на нем почему-то занимало секунд 20 и происходило через раз (на каждый второй раз выводилась какая-то ошибка, приходилось жать на ресет). На старом добром esp8266 подключение происходит с первой попытки, менее чем за секунду. Уж не знаю почему.
 

Grem_line

New member
скорость потока какая? И,правильно ли я понял, что это на Ардуино ИДЕ реализовано?
Скорость где-то около 7-8 Мбит/сек. ESP программировал под Ардуино ИДЕ.
CubieBoard - под RTOS собственной разработки.
Сегодня хочу попробовать поднять скорость - есть момент при выдаче пакетов esp8266 по USB:
Код:
  Del = 1;
  repeat:
   Udp.beginPacket(ip_addr,port);
   Udp.write(Buf,Length);
   if (0==Udp.endPacket())
   {
    delay(Del);
    Del++;
    if (Del > 32)
    {
      Serial.printf("Send fail!\n");
    } else goto repeat;
   }
Если функция Udp.endPacket() возвращает 0 - значит пакет не выдан и нужно повторить выдачу. Сейчас перед повтором делается задержка, возрастающая с каждой неудачей. Нужно попробовать как-то это дело улучшить...
 

Сергей_Ф

Moderator
Команда форума
@Grem_line
не знаю как вам, но goto....
вот так поизящнее, имхо
Код:
Del = 0;
do {
   delay(Del++);
   Udp.beginPacket(ip_addr,port);
   Udp.write(Buf,Length);
} while(  0==Udp.endPacket() && Del<=32 );
if (Del >32 ) Serial.printf("Send fail!\n");
 

Grem_line

New member
не знаю как вам, но goto....
Это старая фишка, еще в 90-е одна солидная фирма проверяла качество ПО. В результате составили заключение, в котором писалось: "программа написана очень хорошо, так как в тексте нет ни одного goto".:)
Если посмотреть результат компиляции моего и вашего вариантов (ассемблер), уверяю, разницы не будет.
Хотя не спорю, ваш смотрится приятнее...
Есть правда один момент - вызов функции delay(0) тоже отъедает какое-то время. В этой функции вызываются обработчики WiFi и TCP/IP. Для esp8266 delay не просто тормозит скетч, а поддерживает систему, занимая при этом время даже при параметре, равном нулю.
Для повышения быстродействия лучше использовать не do-while, а while, чтобы не делать лишнюю задержку при первом проходе.

Померил битрейт сырого потока - на роликах, что гоняю, получается в пиках где-то до 6.5 Мбит/с. Это если измерять за секунду. Если усреднять за 10 секунд, получается порядка 2 Мбит/с.
 

Сергей_Ф

Moderator
Команда форума
а while, чтобы не делать лишнюю задержку при первом проходе.
тут на вкус и цвет, но просто while не получится - Udp.endPacket() не будет ещё определен при первом заходе. Можно немного переделать без delay перед и выходить из цикла по break, тогда.
Код:
Del = 1;
do {
   Udp.beginPacket(ip_addr,port);
   Udp.write(Buf,Length);
   if   ( 0==Udp.endPacket()) break;
   else delay(Del++);
} while(  Del<=32 );
if (Del >32 ) Serial.printf("Send fail!\n");
Померил битрейт сырого потока - на роликах, что гоняю, получается в пиках где-то до 6.5 Мбит/с. Это если измерять за секунду. Если усреднять за 10 секунд, получается порядка 2 Мбит/с.
Вот точно такие значения я получил в роутере на esp8266. Правда для TCP, но и на SDK. Мне сказали, что я вру :). Что то мне подсказывает, что дальнейшие ваши действия к улучшениям не приведут. Вы достигли теоретического потолка для esp3266 :)
 

Grem_line

New member
Что то мне подсказывает, что дальнейшие ваши действия к улучшениям не приведут. Вы достигли теоретического потолка для esp3266 :)
Похоже на то. Но это нормально, мне по ТЗ надо подключить камеру с разрешением 720p, похоже что получится. На худой конец, увеличу степень сжатия, или прорежу вдвое частоту кадров.
Просто я не вижу альтернативы ESP - другие модули WiFi работают по непонятным закрытым протоколам, если брать дрова из линукса, то вылазит такой клубок, который мне во век не размотать. С меня хватило написания собственного стека TCP/IP или собственного драйвера USB UHCI|OHCI|EHCI...
 

Grem_line

New member
@Сергей_Ф, тут появилась одна проблема: При больших пиковых нагрузках начинаются сбои - фактическая длина пакета отличается от той, которая записывается в заголовке. UDP пакеты то приходят короче, чем должны на несколько байт, то длиннее (всегда почему-то на 180 байт).
Это приводит к появлению артефактов на изображении. Если после выдачи каждого пакета вставлять задержку, то все нормально. Только как-то это криво. Если функция endPacket() возвращает 0, то пакет не выдан. Как я понимаю, очередь на выдачу переполнена. Сейчас я просто делаю задержку и повторяю выдачу. Наверное, есть ситуации, когда пакет выдается частично... Не знаете ли Вы какой-нибудь функции, чтобы до выдачи опеределить - есть ли свободное место для пакета?
 

Grem_line

New member
Как выяснилось, пакеты зарезаются не в WiFi, а при обменах по SPI. Я ставил скорость 80МГц, перевел на 40 и сбои практически ушли. Вона как!
 

Grem_line

New member
SDIO что в заголовке делает?
SDIO - это протокол обмена контроллера с периферией, более быстрый, чем SPI за счет того, что используются параллельно четыре линии данных. С помощью SDIO подключается не только флеш, но и большинство WiFi-модулей. Просто разобраться с тем, как работает готовый модуль WiFi по SDIO я чего-то не смог (надо поднимать весь WiFi), а ESP уже сам умеет работать с WiFi и его можно запрограммировать как угодно.
 
Сверху Снизу