Menu
JAQForum Ver 19.10.27

Forum Index : Microcontroller and PC projects : Scrolling Graph on ILI9341 to slow on armmite, picomite and upython

   Page 1 of 2    
Posted: 07:10pm
04 Jan 2022
Copy link to clipboard
Vampire05
Regular Member

Hi guys,
I am trying to build some kind of oscilloscope. For this I measure values with the ADC and want to draw them on a scrolling graph. I have tried with the Armmite F4 (with 7 inch ssd display), Picomite and micropython rp2040 (with 2.8 inch ili9341 display). Everywhere the same result: it scrolls too slow. On the picomite and the armmite i also tried blit. i.e. the whole screen except the last pixel shifted to the left. This is also too slow. how can i implement a fast scrolling graph?

If you put a lot of effort it seems to work:
https://www.hackster.io/news/driving-an-ili9341-display-with-a-raspberry-pi-pico-8dd4ded042e1
is it also possible with less effort in mmbasic?


attached is the code for micropython:


from ili934xnew import ILI9341, color565
from machine import Pin, SPI
from micropython import const
import os
import time
from machine import ADC, Pin
import array


SCR_WIDTH = const(320)
SCR_HEIGHT = const(240)
SCR_ROT = const(2)
CENTER_Y = int(SCR_WIDTH/2)
CENTER_X = int(SCR_HEIGHT/2)

print(os.uname())
TFT_CLK_PIN = const(6)
TFT_MOSI_PIN = const(7)
TFT_MISO_PIN = const(4)

TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(15)

spi = SPI(
   0,
   baudrate=40000000,
   miso=Pin(TFT_MISO_PIN),
   mosi=Pin(TFT_MOSI_PIN),
   sck=Pin(TFT_CLK_PIN))
print(spi)

display = ILI9341(
   spi,
   cs=Pin(TFT_CS_PIN),
   dc=Pin(TFT_DC_PIN),
   rst=Pin(TFT_RST_PIN),
   w=SCR_WIDTH,
   h=SCR_HEIGHT,
   r=SCR_ROT)

adc = ADC(Pin(26))     # create ADC object on ADC pin
buf = array.array('i', (120 for _ in range(320)))

def shift_to_buf(buf, x):
   for i in range(1,320):
           buf[i-1] = buf[i]
   buf[319] = x
   return buf

def draw_buf(buf):
   display.erase()
   for i in range(0, 319):
       display.pixel(buf[i], i, color565(255, 255, 255))

while(1):
   ad = int((adc.read_u16() * 240)/65535)
   buf = shift_to_buf(buf, ad)
   draw_buf(buf)


 
Posted: 07:13pm
04 Jan 2022
Copy link to clipboard
thwill
Guru


When you advance the display have you tried just redrawing the current trace black (to erase it) and then drawing the new trace ? My understanding is that should involve the minimum (almost) amount of data being sent to the display on each update.

Best wishes,

Tom
Edited 2022-01-05 05:21 by thwill
 
Posted: 07:27pm
04 Jan 2022
Copy link to clipboard
Mixtel90
Guru


Don't attempt to keep redrawing the screen. That involves shifting a huge amount of data and will give an obvious flicker. Also, SPI displays are always slower than parallel ones.
 
Posted: 07:29pm
04 Jan 2022
Copy link to clipboard
thwill
Guru


Alternatively divide the display width into, for example, 10 strips and maintain the bounding rectangle of the trace within each strip, then when you blit don't blit the whole display one pixel to left but just the bounding rectangles.

Note I haven't personally tried either of these approaches, they just seem viable at my current level of understanding as to how the SPI displays operate.

Best wishes,

Tom
 
Posted: 07:42pm
04 Jan 2022
Copy link to clipboard
Mixtel90
Guru


I'm wondering if it would be an idea to have an array the width of the screen. Then use PIXEL to plot as you go along. Read the existing pixel position from the array, delete it, plot the new pixel position, update that array cell, inc the array pointer and loop round for the next value. I've never tried this.
 
Posted: 07:45pm
04 Jan 2022
Copy link to clipboard
Vampire05
Regular Member

i have tested in micropython:

for i in range(0, 319):
      display.pixel(buf[i], i, color565(255, 255, 255))


drawing 320 pixel costs over 400 milliseconds.  


yesterday i have tested to blit smaller areas in mmbasic. its faster, but in the worst case i have to redraw the whole display. -> blit more smaller areas is slow too!

i need a clever idea how to scroll with the minimum effort.
 
Posted: 07:59pm
04 Jan 2022
Copy link to clipboard
Mixtel90
Guru


it's not possible AFAIK. Not unless there is some sort of command in the LCD controller to handle hardware scrolling.

You simply can't write to the display any faster than it's controller is designed to handle. That starts with the max speed of your interface. That's why a parallel interface will always win hands down.

You have to reduce the amount of data sent to the screen to an absolute minimum.
Edited 2022-01-05 06:00 by Mixtel90
 
Posted: 08:07pm
04 Jan 2022
Copy link to clipboard
thwill
Guru


  Mixtel90 said  I'm wondering if it would be an idea to have an array the width of the screen. Then use PIXEL to plot as you go along. Read the existing pixel position from the array, delete it, plot the new pixel position, update that array cell, inc the array pointer and loop round for the next value. I've never tried this.


Great minds Mick, I've just been considering the same idea whilst putting the kids to bed.

There is also an optimisation to consider if the new and old pixel positions are the same, in which case there is no need to erase and redraw.

Best wishes,

Tom
 
Posted: 08:09pm
04 Jan 2022
Copy link to clipboard
Vampire05
Regular Member

Ok, you are right!



one interesting thing is:


for i=1 to 320
   pixel i, 120
next i


draw 320 pixels in picomite clock(125khz) costs only 26 ms

with clockspeed of 250khz it is 13 ms
Edited 2022-01-05 06:10 by Vampire05
 
Posted: 08:24pm
04 Jan 2022
Copy link to clipboard
Mixtel90
Guru


Obviously processing will take some time, but processing is faster than accessing the display sometimes.

Also you could do it like a digital storage scope. Capture your data into an array first without even thinking of displaying it. Then scale all the values in the array to make them fit the screen. Once you have a time window's worth then display a part or all of that array in your own good time. This doesn't give continual display of the input, only a triggered display, but you can scan along the array to look at different parts of it.
 
Posted: 08:37pm
04 Jan 2022
Copy link to clipboard
Vampire05
Regular Member

Yes, that is a nice idea. It is the best idea for fast signals  

for slow signals and tracking over longer timeperiod it is okay, when the display refresh rate is slow!

by the way: the cls command is very expensive too: over 60 ms !!!
 
Posted: 08:52pm
04 Jan 2022
Copy link to clipboard
thwill
Guru


  Vampire05 said  by the way: the cls command is very expensive too: over 60 ms !!!


I think it is because it has to work by serially writing the current background colour to every pixel on the screen one at a time, so infact it is one of the slowest commands you can issue.

Best wishes,

Tom
 
Posted: 08:58pm
04 Jan 2022
Copy link to clipboard
twofingers
Guru


  Vampire05 said  Hi guys,
I am trying to build some kind of oscilloscope.

Hi, I'm not sure if it helps. I did something similar for the MM2.
Peter did it even better ...

Regards
Michael
 
Posted: 10:09pm
04 Jan 2022
Copy link to clipboard
Vampire05
Regular Member

Wow, this is so cool  
Yes, it helps!

Thank you guys
 
Posted: 03:35am
05 Jan 2022
Copy link to clipboard
zeitfest
Guru

It is feasible to split the tasks, ie into data acquisition and then display. I got reasonable results using my own interpreter mx170 doing A/D and then sending display data to a cheapie arduino. But hardly worth the effort !

vitrino
 
Posted: 02:51pm
05 Jan 2022
Copy link to clipboard
Vampire05
Regular Member

It is a nice idea to have an "universal plotting display" which only plots data! On the other side you can have multiple "data acquisition / processing units". When the communication protocol is smart enough, than it is a super flexible setup!
Edited 2022-01-06 00:52 by Vampire05
 
Posted: 03:00pm
05 Jan 2022
Copy link to clipboard
matherp
Guru

All displays support some sort of firmware based scrolling. The MM+ and now PicoMite uses this in console mode on the SSD1963 display which is why scrolling up and down in the editor is so fast. This does involve quite a lot of code in the firmware as line 0 may no longer be at the top of the screen

The ILI9341 is actually a 240x320 display and only supports H/W scrolling vertically which is why in landscape mode it is so slow if used as a console device.

It would be possible to create a new Basic command that sends to any display any arbitrary display specific command. In this way you could send the command to scroll a ILI9341 display sideways by one pixel (in landscape mode only) it would then be up to the Basic code to track where the screen map is located and more importantly return it to something sensible on program exit (including trapping Ctrl-C).

Any interest?
 
Posted: 04:28pm
05 Jan 2022
Copy link to clipboard
matherp
Guru

This fast enough?

Poke display &H37,0,0
Load image "tiger-480"
Do
 For i=0 To 479
 Poke display &H37,(i And &Hff00)>>8,i And &Hff
 Pause 1
 Next i
Loop


POKE DISPLAY will be in the next release. Too fast to see without the pause

Coming in V5.07.03RC9

  Quote  POKE DISPLAY command [,data1] [,data2] [,datan]
This command sends commands and associated data to the display controller for a connected display.
This allows the programmer to change parameters of how the display is configured
e.g. POKE DISPLAY &H28 will turn off an SSD1963 display and POKE DISPLAY &H29 will turn it back on again.
It is up to the Basic programmer to read and understand the datasheet for the display in use to make use of the command
Works for all displays except ST7790 and GDEH029A1

Edited 2022-01-06 03:39 by matherp
 
Posted: 05:45pm
05 Jan 2022
Copy link to clipboard
hitsware2
Guru


Here ' s mine .......

Dim y(127)
ADC open 50000,1 ' adjust horizontal
Do
CLS
ADC start y()
For x%=0 To 127
Pixel x%,100*y(x%)-133 ' adjust vertical
Next x%
Pause 200
Loop


 
Posted: 09:42pm
05 Jan 2022
Copy link to clipboard
Vampire05
Regular Member

@matherp: Cool    i will try it with V5.07.03RC9

My workaround: I have now a switch for fast/slow signals. if the switch is set to fast signals, the buffer is first filled and only then drawn as with a DSO. With slow signals aquire/pixel/aquire/pixel/... loop
With a extra potentiometer i can change the pause time


Here is a video: https://www.youtube.com/watch?v=W9ZKUD0ppd8

Ignore my german comments :-)
 
   Page 1 of 2    
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025