ESP32 (non-blinky question)

P. Short

Super Moderator
Staff member
I've been working on a project using the ESP8266 in which I was trying to read data into the RAM at a 2MByte/s rate. I noticed that there are slight hiccups when the WiFi is enabled and connected, which I attributed to the processor handling some WiFi low-level housekeeping tasks, so I'm thinking of switching to use an ESP32 board instead of the Wemos D1 Mini.

So, how would I ensure that all of the WiFi processing is handled by one of the cores so that my application can run continuously on the other core transferring data to ESP RAM at 2MByte/sec (accepting that receiving short command packets from the WiFi or sending responses would interrupt the bulk data flow)? I'm using the Arduino IDE at the moment, and am a bit reluctant to switch development environments given how difficult it is to separate outdated or irrelevant information from useful, accurate information over the internet.
 
Unfortunately that article doesn't discuss the relationship between the cores and WiFi handling...are the WiFi functions pinned to one core or another, is it something that the programmer is supposed to manage, or is it some form of magic?
 
The IDE writes to Core 1 unless code is written to do otherwise . Wifi is on core 0
While this is correct, the issue is not this simple. Loop does run on C1. ESPasync and most other services run on C0 which means that some of the ide code actually executes on C0. So not all code created by the user executes on C1. Next, ISRs run on the CPU on which the ISR was bound (at runtime) unless otherwise specified in the setup operation. Same for tasks. It sounds like you are polling your data transfer. To do that, you create a task on C1 that runs at a higher priority than "loop". The task should be putting itself to sleep to allow loop to run. A better solution is to use DMA to move the data into a buffer and then trigger an interrupt when the DMA needs a refresh.
 
While this is correct, the issue is not this simple. Loop does run on C1. ESPasync and most other services run on C0 which means that some of the ide code actually executes on C0. So not all code created by the user executes on C1. Next, ISRs run on the CPU on which the ISR was bound (at runtime) unless otherwise specified in the setup operation. Same for tasks. It sounds like you are polling your data transfer. To do that, you create a task on C1 that runs at a higher priority than "loop". The task should be putting itself to sleep to allow loop to run. A better solution is to use DMA to move the data into a buffer and then trigger an interrupt when the DMA needs a refresh.

The maximum SPI data rate in the data source is 15 Mbps, while 16 Mps would be needed if I were to try to use the ESP32 DMA/with/SPI mode. Not having read the ESP32 specs in detail, I don't know if there are any other useful ways to send data to the ESP in such a way that it's DMA could be utilized.
 
DMA can be attached to the UARTS, SPI, RMT, I2C interfaces. You are saying that the data source generates a data stream at 15Mbps that needs to be captured by the ESP. What does the ESP do with that data?

A SPI interface is a great fit if the data source is ok with being polled. Using the UART may be a better choice if the data is asynchronous.
 
The data source 'wants' to send data at a 16 Mbps rate, i.e. two bytes per uS. That is too fast for the SPI port on the sending device, which is limited to 15 Mbps. That rate is much too high for i2c (the fastest i2c data rate is 3.4 Mpbs, if I recall right) and too fast for serial data transfer over a uart (generally limited under 5 Mbps). I don't know what RMT is, I'll have to look it up after I get back from lunch.

The ESP buffers the incoming data in a huge circular buffer, and would transmit it via udp/pv4/Wifi to an application on a PC to graphically display it on the screen. I can make it work with the Wemo D1 mini, just not quite as nice.
 
I would have to take a look, but a single circular buffer means the DMA would only need two blocks in the chain and the chain would be circular. You get an interrupt at the end of each block and then refresh the status in the DMA control header. You would get zero delays that way. Not sure how you align your data or deal with the SPI overhead but this sounds like something the ESP32 should handle.
 
Question for Martin: I'm under the impression that you have decided on an ESP32 board that plugs into the ESPixelStick V3 in the same pin locations that would be used for a Wemos D1 Mini. Which ESP module would you recommend?

Most likely by accident I ordered these boards from Amazon last November. Are they ones that I should be using (in general), or are they ones that I should plan to replace with something better? Those boards seem to be usable in the same sockets as the Wemos D1 Mini.
 
I've gone to the effort of modifying the code to test performance with an ESP32 (dual-core) both with the Arduino IDE and with the Espressif IDF package, with indifferent results. In either case interrupt latency times and the gpio transfer rates are both worse than with the ESP8266. I'll need to look into this more, or find a way to live the WiFi issues with the ESP8266 (not that there is any guarantee that those problems would disappear with the ESP32).
 
I'd have to figure out how to use github. In any case, I'm out of town (Rochester) at the moment, but I've come across some things that I can try in the meantime.
 
Thanks, Martin. I've discovered a method of increasing GPIO speed - use REG_WRITE instead of some of the alternative ways of controlling the GPIO pins. So I'll carry on.
 
Back
Top