Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 06:17 22 Jan 2022 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

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

     Page 1 of 2    
Author Message
Vampire05
Regular Member

Joined: 06/12/2020
Location: Germany
Posts: 75
Posted: 07:10pm 04 Jan 2022
Copy link to clipboard 
Print this post

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)


 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 2077
Posted: 07:13pm 04 Jan 2022
Copy link to clipboard 
Print this post

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
CMM2 Welcome Tape, Creaky old text adventures
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 1482
Posted: 07:27pm 04 Jan 2022
Copy link to clipboard 
Print this post

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.
-- Mick

Zilog Inside! nascom.info for Nascom & Gemini
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 2077
Posted: 07:29pm 04 Jan 2022
Copy link to clipboard 
Print this post

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
CMM2 Welcome Tape, Creaky old text adventures
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 1482
Posted: 07:42pm 04 Jan 2022
Copy link to clipboard 
Print this post

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.
-- Mick

Zilog Inside! nascom.info for Nascom & Gemini
 
Vampire05
Regular Member

Joined: 06/12/2020
Location: Germany
Posts: 75
Posted: 07:45pm 04 Jan 2022
Copy link to clipboard 
Print this post

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.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 1482
Posted: 07:59pm 04 Jan 2022
Copy link to clipboard 
Print this post

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
-- Mick

Zilog Inside! nascom.info for Nascom & Gemini
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 2077
Posted: 08:07pm 04 Jan 2022
Copy link to clipboard 
Print this post

  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
CMM2 Welcome Tape, Creaky old text adventures
 
Vampire05
Regular Member

Joined: 06/12/2020
Location: Germany
Posts: 75
Posted: 08:09pm 04 Jan 2022
Copy link to clipboard 
Print this post

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
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 1482
Posted: 08:24pm 04 Jan 2022
Copy link to clipboard 
Print this post

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.
-- Mick

Zilog Inside! nascom.info for Nascom & Gemini
 
Vampire05
Regular Member

Joined: 06/12/2020
Location: Germany
Posts: 75
Posted: 08:37pm 04 Jan 2022
Copy link to clipboard 
Print this post

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 !!!
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 2077
Posted: 08:52pm 04 Jan 2022
Copy link to clipboard 
Print this post

  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
CMM2 Welcome Tape, Creaky old text adventures
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 964
Posted: 08:58pm 04 Jan 2022
Copy link to clipboard 
Print this post

  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
 
Vampire05
Regular Member

Joined: 06/12/2020
Location: Germany
Posts: 75
Posted: 10:09pm 04 Jan 2022
Copy link to clipboard 
Print this post

Wow, this is so cool  
Yes, it helps!

Thank you guys
 
zeitfest
Senior Member

Joined: 31/07/2019
Location: Australia
Posts: 219
Posted: 03:35am 05 Jan 2022
Copy link to clipboard 
Print this post

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
 
Vampire05
Regular Member

Joined: 06/12/2020
Location: Germany
Posts: 75
Posted: 02:51pm 05 Jan 2022
Copy link to clipboard 
Print this post

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
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 5688
Posted: 03:00pm 05 Jan 2022
Copy link to clipboard 
Print this post

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?
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 5688
Posted: 04:28pm 05 Jan 2022
Copy link to clipboard 
Print this post

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
 
hitsware2

Guru

Joined: 03/08/2019
Location: United States
Posts: 441
Posted: 05:45pm 05 Jan 2022
Copy link to clipboard 
Print this post

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



http://www.hitswares.com/
 
Vampire05
Regular Member

Joined: 06/12/2020
Location: Germany
Posts: 75
Posted: 09:42pm 05 Jan 2022
Copy link to clipboard 
Print this post

@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    
Print this page
© JAQ Software 2022