ESP32上的DOOM Watch。第1部分

在尝试使用现成的ESP32模块进行开发后,我想做一些小巧而原生的事情。我决定做一只手表。起初,我想到了ESP32-PICO-D4由于该程序只有4Mb闪存,因此我决定制作一个完整版本,最大扩展为16Mb闪存和8Mb SRAM。无论什么时钟,您都可以运行第一个Doom。总的来说,这就是全部填充!



尚未完成或需要改进的地方:

  1. 电池指示灯
  2. 在肖特基二极管上实现的充电势垒电路
  3. 天线不在ESP32的另一层上

不是教程!



通过显示




我在ST7789控制器上应用了分辨率为240x240的彩色显示器。它非常紧凑且便宜。网络上出现越来越多的驱动程序和端口。例如,有一个LittlevGL的端口,但此显示器上没有独轮车。我认为可以购买和粘贴。也许有人有经验?分享:

我在ST7789上开发了一块板,并且启动时没有任何问题。



LittlevGL esp32


通过填充程序和调试


我使用了CP2102 USB-TO-UART BRIDGE转换器。首先,它非常紧凑,其次,连接图非常简单,几乎不需要其他任何部件。
选项2:如果通过片上稳压器为其他器件供电,则可以添加4.7 F电容器。
如果将REGIN和VBUS连接到USB 5V电源,则仅在输入端需要一个并联电容器。尽管我认为没有它也可以工作。在这种情况下,芯片上的VDD是出路!我犯了一个错误,将其连接到3.3V电源电路,但无法理解为什么我的电源上有4.65V?

以下文档中的链接具有用于连接3.3V电源的选项。但是我认为,当我们不需要上载或调试设备时,绝对不需要为CP2102供电



模数电池充电


LTC4054上的电阻器设置充电电流:



营养


由带有稳定器HT7833的3.7V电池供电。输出电流500mA。它的电压降很小〜300mV。 LD1117-3.3还有“一点”。

关于VDD_SDIO的结论的注释。此引脚电源输出为1.8V或3.3V,具体取决于启动时 IO12微控制器的状态。 3.3V GPIO12为0(默认)
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

如果您有闪光灯1.8V,这将非常方便。但就我而言,我获得了这个结论,并将3V3闪存和PSRAM连接到了通用电源,

某些ESP32模块使用了VDD_SDIO,因此启动时我无法将任何东西挂在IO12的外围设备上。例如,您可以挂一个按钮。在我的一种解决方案中,我在IO12上挂了一个SPI引脚,模块没有启动。显然,IO12从此SPI端口获得了一个单元,但我需要0,反之亦然。必须考虑到这一点!

全部一起:

图片

8MB PSRAM


8MB PSRAM升级Mod
支持外部RAM
PSRAM / CE(引脚1)> ESP32 GPIO 16
PSRAM SO(引脚2)>闪存DO
PSRAM SIO [2](引脚3)>闪存WP
PSRAM SI(引脚5)>闪存DI
PSRAM SCLK(引脚6)> ESP32 GPIO 17
PSRAM SIO [3](引脚7)>闪存保持
PSRAM Vcc(引脚8)> ESP32 VCC_SDIO


PCB天线


我使用了2.4 GHz小尺寸PCB天线它位于Eagle Autodesk库中,占地很小。您可能可以使用陶瓷介电天线,但您需要购买它,而且PCB天线的价格要高一些。但是,陶瓷天线效果较差。任何选件《

天线选择快速指南》《天线设计和RF布局指南》都适用于检查概念。

图片



关于天线匹配的一些知识




ESP32硬件设计指南第7页上提供用于实现RF滤波器的指导方针:
ESP32(QFN 6 * 6)和ESP32(QFN 5 * 5)的RF引脚的输出阻抗分别为(30 + j10)Ω和(35 + j10)Ω。
要进行计算,请使用Online Smith Chart Tool。主要思想是在(30 + j10)处到达圆心。但是,这是计算得出的数据,参数的实际使用可能会受到走线和PCB的厚度以及相对于电路其他组件的位置的影响,



这不是唯一的天线匹配电路。例如,在esp32-pic板上的匹配有些不同:

esp32-pico-kit-v4_schematic

Smith图表和阻抗匹配

天线位置及其周围的自由区域也很重要。如我先前所写,就我而言,职位不是最佳选择。但是,对于电路板的第一次迭代和概念验证,



第二部分将专门讨论电路板本身以及软件的第三次移植。也许一切都合而为一。

我将在Espressif Systems Doom端口上继续介绍该端口使用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快速演示



电路板的订单已发送到Jlcpcb工厂。

发起挑战!

All Articles