DOOM Watch на ESP32. Часть 1

    Попробовав разработку с готовыми модулями ESP32 захотелось сделать что-то маленькое и нативное. Решил сделать часы. Сначала подумал о ESP32-PICO-D4. Поскольку в ней только 4Mb flash под программу, решил сделать полноценную версию с расширением до 16Mb flash и 8Mb SRAM. Что бы на часах можно запустить первый Doom. В общем чтобы было все на полном фарше!



    Что не сделано или требует доработки:

    1. Индикатор батареи
    2. Схема барьера зарядки реализована на Schottky диоде
    3. Антена расположена не совсем удачно и на другом слое от ESP32

    Не туториал!



    По дисплею




    Я применил цветной дисплей на контроллере ST7789 с разрешением 240x240. Он довольно компактный и дешевый. В сети все больше появляется драйверов и портов. Например есть порт для LittlevGL, но на этом дисплее нет тача. Думаю его можно докупить и приклеить. Может у кого-то есть опыт? Поделитесь

    Я разработал на ST7789 одну плату и она «завелась» без каких либо проблем



    LittlevGL esp32


    По заливке программ и debug


    Я использовал USB-TO-UART BRIDGE преобразователь CP2102. Во первых он компактный и во вторых схема подключения очень простая и почти не требуется дополнительных деталей.
    Option 2: A 4.7 μF capacitor can be added if powering other devices from the on-chip regulator.
    Если подключить REGIN и VBUS к питанию USB 5V то потребуется только шунтирующий конденсатор на входе. Хотя думаю может работать и без него. VDD на чипе в этом случае это выход! Я сделал ошибку и подключил его к 3.3V питания схемы и не мог понять почему у меня на питании 4.65V ?!

    По ссылке в документации внизу есть варианты подключения к 3.3V питания. Но думаю совершенно не надо питать CP2102 когда нам не надо заливать или дебажить девайс



    По модулю зарядки батареи


    Резистор на LTC4054 устанавливает ток зарядки:



    По питанию


    Питание осуществляется от батарей 3.7V со стабилизатором HT7833. Выходной ток 500mA. Он имеет малое ~300mV падение напряжения. LD1117-3.3 имеет «немного» больше.

    Замечание про выводы VDD_SDIO. Этот пин выход питания 1.8V или 3.3V в зависимости от того в каком состоянии находится IO12 микроконтроллера при старте. 3.3V GPIO12 is 0 (default)
    VDD_SDIO works as the power supply for the related IO, and also for an external device.

    When VDD_SDIO operates at 1.8 V, it can be generated from ESP32’s internal LDO. The maximum currentthis LDO can offer is 40 mA, and the output voltage range is 1.65 V~2.0 V.

    When the VDD_SDIO outputs 1.8 V, the value of GPIO12 should be set to 1 when the chip boots and it is recommended that users add a2 kΩ ground resistor and a 4.7 mF filter capacitor close to VDD_SDIO.

    When VDD_SDIO operates at 3.3 V, it is driven directly by VDD3P3_RTC through a 6Ωresistor, therefore,there will be some voltage drop from VDD3P3_RTC.

    When the VDD_SDIO outputs 3.3 V, the value of GPIO12 is 0 (default) when the chip boots and it is recommended that users add a 1mF capacitor close to VDD_SDIO

    Это очень удобно если у вас flash 1.8V. Но в моем случае я забил на этот вывод и подключил мою 3V3 flash и PSRAM к общему питанию

    Некоторые модули ESP32 используют VDD_SDIO поэтому на IO12 нельзя ничего вешать из перефирии при старте. Можно например повесить кнопку. В одном из моих решений я повесил на IO12 ногу SPI и модуль не стартовал. Видимо на IO12 попала единица с этого порта SPI, а нужен был 0 или наоборот. Это надо учитывать!

    All together:

    image

    8MB PSRAM


    8MB PSRAM Upgrade Mod
    Support for external RAM
    PSRAM /CE (pin 1) > ESP32 GPIO 16
    PSRAM SO (pin 2) > flash DO
    PSRAM SIO[2] (pin 3) > flash WP
    PSRAM SI (pin 5) > flash DI
    PSRAM SCLK (pin 6) > ESP32 GPIO 17
    PSRAM SIO[3] (pin 7) > flash HOLD
    PSRAM Vcc (pin 8) > ESP32 VCC_SDIO


    PCB antenna


    Я использовал Small Size 2.4 GHz PCB antenna. Она есть в библиотеке Eagle Autodesk и занимает небольшую площадь. Можно наверное применить CERAMIC DIELECTRIC ANTENNA но ее надо покупать, а цена PCB антенны это немного бОльшее занимаемое место. Однако керамическая антенна менее эффективна. Для проверки концепта подойдет любой вариант

    Antenna Selection Quick Guide

    image

    Antenna Design and RF Layout Guidelines

    Немного о согласовании антенны




    В документации ESP32 Hardware Design Guidelines на стр 7 дается рекомендация по реализации RF фильтра:
    The output impedance of the RF pins of ESP32 (QFN 6*6) and ESP32 (QFN 5*5) are (30+j10) Ω and (35+j10) Ω, respectively
    Для расчета воспользуемся Online Smith Chart Tool. Основная идея попасть в центр круга при (30+j10). Однако это расчетные данные и на реальное использование параметров может повлиять толщина дорожек и текстолита, а также расположение относительно других компонентов схемы



    Это не единственная схема согласования антенны. Например согласование на плате esp32-pic выполнено немного иначе:

    esp32-pico-kit-v4_schematic

    Smith Chart and Impedance Matching

    Так же важно расположение антенны и свободная область вокруг нее. Как я написал ранее, в моем случае положение выбрано не оптимально. Но для первой итерации платы и проверки концепта пойдет



    Вторая часть будет посвящена самой плате а третья портированию софта. Возможно все уместится в одну.

    Я немного забегу вперед по порту Doom от компании производителя Espressif Systems. В порте применяется ILI9341 у нас ST7789. Но поскольку инициализация и вывод буфера вынесен в отдельный файл и разбит на отдельные методы, адаптация под мой дисплей не должно вызвать большие сложности.

    • За инициализацию дисплея отвечает ili_init и displayTask
    • За отображения на дисплее отвечает displayTask

    displayTask
    void IRAM_ATTR displayTask(void *arg) {
    	int x, i;
    	int idx=0;
    	int inProgress=0;
    	static uint16_t *dmamem[NO_SIM_TRANS];
    	spi_transaction_t trans[NO_SIM_TRANS];
    	spi_transaction_t *rtrans;
    
        esp_err_t ret;
        spi_bus_config_t buscfg={
            .miso_io_num=-1,
            .mosi_io_num=PIN_NUM_MOSI,
            .sclk_io_num=PIN_NUM_CLK,
            .quadwp_io_num=-1,
            .quadhd_io_num=-1,
            .max_transfer_sz=(MEM_PER_TRANS*2)+16
        };
        spi_device_interface_config_t devcfg={
            .clock_speed_hz=26000000,               //Clock out at 26 MHz. Yes, that's heavily overclocked.
            .mode=0,                                //SPI mode 0
            .spics_io_num=PIN_NUM_CS,               //CS pin
            .queue_size=NO_SIM_TRANS,               //We want to be able to queue this many transfers
            .pre_cb=ili_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
        };
    
    	printf("*** Display task starting.\n");
    
        //Initialize the SPI bus
        ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1);
        assert(ret==ESP_OK);
        //Attach the LCD to the SPI bus
        ret=spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
        assert(ret==ESP_OK);
        //Initialize the LCD
        ili_init(spi);
    
    	//We're going to do a fair few transfers in parallel. Set them all up.
    	for (x=0; x<NO_SIM_TRANS; x++) {
    		dmamem[x]=pvPortMallocCaps(MEM_PER_TRANS*2, MALLOC_CAP_DMA);
    		assert(dmamem[x]);
    		memset(&trans[x], 0, sizeof(spi_transaction_t));
    		trans[x].length=MEM_PER_TRANS*2;
    		trans[x].user=(void*)1;
    		trans[x].tx_buffer=&dmamem[x];
    	}
    	xSemaphoreGive(dispDoneSem);
    
    	while(1) {
    		xSemaphoreTake(dispSem, portMAX_DELAY);
    //		printf("Display task: frame.\n");
    #ifndef DOUBLE_BUFFER
    		uint8_t *myData=(uint8_t*)currFbPtr;
    #endif
    
    		send_header_start(spi, 0, 0, 320, 240);
    		send_header_cleanup(spi);
    		for (x=0; x<320*240; x+=MEM_PER_TRANS) {
    #ifdef DOUBLE_BUFFER
    			for (i=0; i<MEM_PER_TRANS; i+=4) {
    				uint32_t d=currFbPtr[(x+i)/4];
    				dmamem[idx][i+0]=lcdpal[(d>>0)&0xff];
    				dmamem[idx][i+1]=lcdpal[(d>>8)&0xff];
    				dmamem[idx][i+2]=lcdpal[(d>>16)&0xff];
    				dmamem[idx][i+3]=lcdpal[(d>>24)&0xff];
    			}
    #else
    			for (i=0; i<MEM_PER_TRANS; i++) {
    				dmamem[idx][i]=lcdpal[myData[i]];
    			}
    			myData+=MEM_PER_TRANS;
    #endif
    			trans[idx].length=MEM_PER_TRANS*16;
    			trans[idx].user=(void*)1;
    			trans[idx].tx_buffer=dmamem[idx];
    			ret=spi_device_queue_trans(spi, &trans[idx], portMAX_DELAY);
    			assert(ret==ESP_OK);
    
    			idx++;
    			if (idx>=NO_SIM_TRANS) idx=0;
    
    			if (inProgress==NO_SIM_TRANS-1) {
    				ret=spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY);
    				assert(ret==ESP_OK);
    			} else {
    				inProgress++;
    			}
    		}
    #ifndef DOUBLE_BUFFER
    		xSemaphoreGive(dispDoneSem);
    #endif
    		while(inProgress) {
    			ret=spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY);
    			assert(ret==ESP_OK);
    			inProgress--;
    		}
    	}
    }
    


    Video Esp32-Doom quick demo



    Заказ на плату отправлен на фабрику Jlcpcb.

    Челендж запущен!
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 22

      –8
      Русский язык для Вас не родной или вы им очень редко пользуетесь?
      Встречаются выражения, которые понять тяжело.
        0
        Покажите место в тексте, я поправлю
          –1
          Просто текст так составлен, как будто его писали на другом языке, а потом переводили автоматическим переводчиком: термины, аналоги которых давно уже имеются в русском языке написаны на английском, цитаты из технической спецификации (насколько я понимаю они взяты именно оттуда) вполне можно было перевести на великий и могучий, иногда странно (для меня, во всяком случае) построены фразы.

          Я встречал не раз сообщения от иностранцев на русскоязычных форумах, которые выглядели подобным образом.

          Демка с думом вообще взята чужая от 2017 года. Неужели нельзя было записать на своём устройстве, раз всё работает? Или устройство только в процессе создания и ещё не известно заработает ли оно?
            0
            Я редко пользуюсь Русскоязычной тех документацией. Возможно это накладывает отпечаток

            Демка вообще взята от 2017 года (неужели нельзя было записать на своём устройстве, раз всё работает).

            Doom пока не запускал на моем ESP32 устройстве
              +3
              термины, аналоги которых давно уже имеются в русском языке написаны на английском

              Термины латиницей проще гуглить. Даже если информация есть на русском, то на английском всё равно будет больше, подробнее и понятнее. Кроме того некоторые термины вообще не существуют в русском языке, либо существуют лишь как заимствования.


              цитаты из технической спецификации вполне можно было перевести

              Цитаты лучше приводить как есть, но сопровождать комментариями.


              Вы конечно можете возразить, дескать, не все знают английский. Да, не все. Зато все знают, где гуглотранслейт.

                0
                Термины латиницей проще гуглить.
                Чтобы найти информацию на английском — может быть.
                Кроме того некоторые термины вообще не существуют в русском языке, либо существуют лишь как заимствования.
                Довольно большая часть словаря у всех современных языков является заимствованием (из латыни, греческого, англйского, французского, немецкого, голландского и т.д.).
                Так что не показатель (у автора вообще встречается не раз транслит с английского, когда есть слово на русском).
                все знают, где гуглотранслейт.
                Часто бывает, что гуглоперевод менее понятен, чем оригинал на английском.
            +1
            Но Карл!

            Если нашли опечатку в посте, выделите ее и нажмите Ctrl+Enter, чтобы сообщить автору.
              0
              Вы про диод?
                0
                Я в курсе
                Уже сообщал (правда, по одному случаю, ещё до моего первого комментария здесь; безрезультатно, кстати).
                Хотя там мелкой корректуры много получится.
              –7
              лучше бы вдохнул новую жизнь в старые китайские планшеты на Rockchip RK3066 с MALI400…
              туда бы вместо 4 ведроида линукс и нормальный загрузчик и чтобы на встроенной памяти, а не с microSD карточки.
              реально бы многие спасибо за такое скажут и стряхнут пыль с старых, но всё ещё на что-то способных планшетов.
                +1
                Тут как бы немного другая категория девайса. «Родная» OS для ESP32 это RTOS
                0

                А Вы планируете потом выложить в общий доступ (github) комплект файлов для заказа плат (включая исходники разводки), схему и пр. для самостоятельной сборки?


                В принципе, такие готовые решения продаются, но мне, например, в них всегда чего то по мелочи не хватает. А разводить плату с 0 и собирать все шишки с ошибками разводки — не греет (программы писать больше нравится).
                Я свои наработки всегда выкладываю..

                  0
                  Гербер файл?
                  Надо сделать хотя бы одну итерацию. Посмотреть как запустится
                  А вы какими устройства разрабатывали?
                    +1

                    Да вот недавно опубликовал. https://habr.com/ru/post/493412/
                    Инструмент для анализа WiFi сетей.


                    Как раз экран + кнопки. Если была бы возможность компактней сделать штучку. Т.е. были бы открытые исходники разводки платы (в чем разводите, кстати?), что бы по мелочи свое добавить (мне лично нужно + простой 433mHz приемопередатчик с амплитудной модуляцией). Если собирать не из готовых модулей, то размер можно существенно уменьшить. Просто эстетически лучше.


                    Разводить я умею и платы паять, но удовольствия от этого не получаю. Не мое: )

                      0
                      Я начал разрабатывать борду на STM32.
                      github.com/app-z/STM32AudioLCDMinimal

                      Какой чип 433mHz вы имеете ввиду?
                      скинте линк на спеку

                      (в чем разводите, кстати?)

                      Autodesk Eagle
                        0

                        Я рассматривал http://www.ti.com/product/CC1110-CC1111
                        Он конечно несколько избыточен для того что мне надо (достали шлагбаумы в дворовых проездах)
                        Но когда теперь с этим карантином придет модуль на "пощупать"… даже не знаю.
                        Но его лучше, наверно, сразу в виде готового модуля брать. 500 руб и размер платы 25x25

                  +2

                  А это нормально, что ты в цикле displayTask забираешь и не отдаешь семафор dispSem?

                    +1
                    Это не я :)
                    Хорошее замечание! Я не полностью привел код. Там есть еще одна функция
                    void spi_lcd_send(uint16_t *scr) {
                    #ifdef DOUBLE_BUFFER
                            memcpy(currFbPtr, scr, 320*240);
                            //Theoretically, also should double-buffer the lcdpal array... ahwell.
                    #else
                            currFbPtr=scr;
                    #endif
                            xSemaphoreGive(dispSem);
                    }
                    
                    0
                    Обьясните плиз неразумному, зачем тут антенна?
                      0
                      Как зачем? По сети играть ж)
                      0
                      Спасибо за онлайн калькулятор диаграммы смита!
                      Очень удобный ресурс оказался.
                        0
                        Да. Но он только расчетные данные предоставляет. Как настраивать без анализатора? Может есть какой-то способ например на rigol 1054z настроить? У него полоса 100MHz

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое