Hello
I have an Arduino Nano RP2040 sending data via SPI to a screen (Waveshare 1.5inch OLED Display Module 128x128). I want the screen to be refreshed as quickly as possible. Here is the code that I use to monitor the speed of display :
And here is what I get : Time elapsed : 84530 (so about 0.1 s)
From what I have read, the _F in the construction line says that the whole buffer is stored in the Arduino RAM and then sent to the screen at once. If I understand correctly, we have 128x128 pixels, and by default it seems to be either ON or OFF, no grey level, so it takes about 2ko of RAM. If the buffer takes in the data for every pixel, it would mean that it is sent at a rate of roughly 20ko/s. Btw, it that is the case, could we instead send only the data for the pixel we want to "invert" or turn on?
I bet that the screen is the one slowing down here, since the Arduino clock is orders of magnitude faster than that. Also, playing with the frequency ( u8g2.setBusClock(); ) barely helps.
I don't know how to use modes _1 and _2 (instead of _F): they are faster but I see no pixel being turned on!
How fast can you go with a 128x128 screen wired to an Arduino? Could you suggest a piece of code, or another library, or even another screen?
Data Transfer:
It is true, that only 2kbytes are required, however the SSD1327 is a 16-graylevel display without monochrome mode, so u8g2 has to transfer 4 bit per pixel (2kb * 4 = 8kb)
How to use modes _1 and _2:
With modes _1 and _2 you can't use sendBuffer(), instead you need to use the "picture loop", see here: u8g2reference · olikraus/u8g2 Wiki · GitHub
Modes _1 and _2 will not be faster. The idea instead is to trade speed vs RAM consumption. In other words modes _1 and _2 will be even slower.
Speed:
The bit conversion from 1 bit to 4 bit and also the larger data amount will eat up most of the computing power of the Arduino. Compared to this "setBusClock()" will just increse the pure transfer speed, which will not help soo much.
Partially Update:
I think UpdateDisplayArea u8g2reference · olikraus/u8g2 Wiki · GitHub might help here. But it is a little bit tricky to use, because the coordinates / position arguments are different.
Thanks for your answer. Actually it might not be helpful in my case, since there could be several areas on the screen that would need to be updated; it would be a lot of work for a little gain of time (and I need quite a lot of it!)
In my project I get measurements from analog input pins (dozens per second) and I want to update the screen in between. It doesn't matter if I can't refresh after each and every reading, but the time where the Arduino is busy sending information to the screen should be very short, so it can go back to the readings (does it make sense?)
Apparently the RP2040 is dualcore. So maybe I could use the first core to make the measurements, use the second one to take input from the first one, deal with the screen while core one does its things, and when it is done, take the next input, etc. But I guess this is no longer about screen here
It seems like either multithreading or DMA would allow data transfer between Arduino and screen while the rest of the code is being executed. But I don't know anything about it and I can't find sketches that do that. Do you think the Nano RP2040 is the right Arduino for the job?
Are you sure that the rest of the code is blocked by the display communication? More probably you force the display to do excessive or repeated time consuming things.
Yes, because for the code to run normally, I should not allow much more than 10ms of "interruption", and here I am close to 100ms. I hoped (not knowing anything about communication with screens) that I could dramatically decrease it, but apparently not. That's why I am now looking at DMA or dual core to run things in parallel. Or any other method!
I am not familiar with that processor and will take a SWAG. In many years past we used used dual-ported RAM for efficient data handling in the main loop, not in the Interrupt Service Routine (ISR).
Key Points to Consider: 1. Updating Displays in an ISR:
◦ Updating a display directly within an ISR is generally discouraged because ISRs should execute as quickly as possible to avoid delaying other critical tasks and to prevent the risk of missing other interrupts.
◦ If the display update requires significant processing or access to shared resources (e.g., a display buffer), it can cause timing issues or introduce race conditions. 2. Moving Display Updates to the Main Loop:
◦ Instead of updating the display in the ISR, set a flag or use a buffer to indicate that an update is needed. The main loop can then check this flag and perform the actual display update.
◦ This approach keeps the ISR short and responsive, while the main loop can handle more complex tasks like refreshing the display without interrupting other processes. 3. Dual-Ported RAM (DPRAM) for Display Buffers:
◦ Dual-ported RAM allows simultaneous access from two separate systems, such as a microcontroller and a display driver, making it ideal for situations where you need fast and concurrent read/write access.
◦ Using DPRAM for display buffers can be advantageous if you have a system where the display driver needs to access data independently from the main processor. This can be beneficial for high-speed applications or systems with stringent real-time requirements. 4. Using Dynamic RAM (DRAM) in Embedded Systems:
◦ DRAM is less expensive and offers more storage capacity than static RAM (SRAM), but it is generally slower due to the need for refresh cycles.
◦ For display updates, DRAM can be sufficient if the refresh rate is low enough not to impact performance. However, SRAM or DPRAM is preferred for high-speed applications because of their lower access latency. 5. Raspberry Pi and Memory Access:
◦ On the Raspberry Pi, shared memory between the CPU and GPU (graphics processing unit) can act similarly to dual-ported RAM for display purposes. The GPU can handle the display updates while the CPU performs other tasks.
◦ Using shared memory or frame buffers in the Pi's architecture can be an efficient way to manage display data without impacting the main processing loop significantly.
Recommendations:
• Use a flag-based approach to signal display updates from the ISR to the main loop.
• Consider dual-ported RAM if you have stringent timing requirements and need independent access to the display data.
• Utilize shared memory or efficient memory management techniques for the Raspberry Pi to optimize display performance.
This way, you ensure that the system remains responsive, and display updates are handled efficiently.
Sorry, I should have detailed more. What the code already does :
It makes a series of analog input readings, and when it is done : it updates variables that can be used to draw shapes, numbers, etc. on the screen, and right after, or after max 10ms of laziness, goes back to its next reading session, and so on.
What the screen shoud do : refresh as often as possible, with the latest information available. It won't get all the updates because they come too often but that's fine.
So the measurement is leading the game, the screen only shows up when it finished refreshing, to fetch the latest data and immediately disappears to refresh again.
I don't know what you meant by interrupts (use the screen or the measurements as the trigger)? But I agree not to use them anyway = )
About DPRAM and DRAM : I don't know about them, I guess some advanced programmer could get something out of them but I can barely use the basic functions of an Arduino
Raspberry Pi : It sounds more user friendly. I could have a look, but I would still prefer to stay in the Arduino environment. I have already moved from Uno to the different Nanos : Every, 33Iot, ESP32, and after I understood that RAM was critical to use a screen, RP2040. And even though they are all Arduino's, I had to change the resistor values, play around with some parameters in my code, etc. All that to say that changing from an Arduino to another one can already take a bit of work, so to a whole new platform like Raspberry... I would really appreciate if I could avoid it. But let's see how it goes.
Dynamic RAM (DRAM) is a type of volatile memory, meaning it loses its data when power is turned off. Additionally, DRAM requires periodic refreshing to retain its data. This refresh process involves reading the contents of its memory cells at regular intervals to prevent data loss. You can find a more detailed explanation here.