prenticedavid / TFT_SPI_kbv

Library for ILI9225, ILI9341, HX8347D, ILI9163, ST7735 in SPI mode
14 stars 4 forks source link

How do you use the readGRAM function? #1

Closed benlucy closed 3 years ago

benlucy commented 4 years ago

I'm quite new to this. What I want to do would be impossible without your work, so thank you.

Looking at the header file ST7735_kbv.h there is a readGRAM function:

int16_t readGRAM(int16_t x, int16_t y, uint16_t *block, int16_t w, int16_t h);

My understanding of arduino syntax says that the function accepts these parameters: (x, y, *block, w, h) and returns an int16_t value.

I don't understand: a) What is *block. I understand it's a pointer, but I'm not sure what I'm supposed to be passing to the function here. b) The returned value. It makes sense that readGRAM would return 3 bytes per pixel (for rgb values), but it looks like it returns one int16_t value.

What I would like to do (in pseudocode) is:

#include ST7735_kbv.h

void setup()
{
byte array[480]   //160 pixels * 3 bytes = 480 bytes for a row of pixels
y=1;
}

void loop()
{
array = readGRAM(1, y, ???, 128, 1);
moveStepperMotor(array);
y=y++;
}
prenticedavid commented 4 years ago

I am not sure if this library is in working order.

You can read GRAM on a ST7735 if you have regular 3.3V GPIO pin connected to SDA. e.g. Zero, Due, STM32, ... I use Uno clones with switchable 3.3V GPIO.

If you want to see how to use readGRAM() look at MCUFRIEND_kbv examples.

int16_t  readGRAM(int16_t x, int16_t y, uint16_t *block, int16_t w, int16_t h);

You specify a rectangle in pixel coordinates and it will read colors into an uint16_t array in SRAM. Obviously, you can't read a very big rectangle. e.g. a 20 x 10 rectangle needs an array: uint16_t block[200];

If you want to Software Scroll an area, you can do it one raster at a time. e.g. 240x1 is only 480 bytes of SRAM.

David.

benlucy commented 4 years ago

Hi again,

I wasn’t able to get the library to work. I’ve gone away and read a textbook about C/Arduino, which has helped a bit, but there are still many bits of your code that I still don’t understand.

I think I’m a long way off so I’m ready to give up. My plan B for the project s to use your MCUfriend library and see if I can adapt the OV7670 camera-to-screen library I was using, so that it works with those screens.

However, I thought it’s worth checking with you that there isn’t a quick and easy way to do it. My objective is to read a row of 160 pixels, and be able to choose which row. I get the impression that if I get your AVRfreaks code working 100%, I might be able to write my own readGRAM function for a row of pixels.

It might be the case that my screen is not an S7735R or an ILI9163C? Using your code from the AVRfreaks forums:

ID = readwrite8(0x04, 24, 1);
Serial.println(ID);     //this prints ‘0’ in the serial monitor, not ‘0x7C89F0uL’ as expected.

The screen is this: https://www.ebay.co.uk/itm/112607724521 The screen works fine with displaying some demo graphics, so I’ve definitely got all the pins right. I am using a 5v Arduino nano with resistors to convert to 3.3V logic.

Things I have tried:

void loop() {
  tft.fillScreen(ST77XX_BLUE);
  delay(1000);
  showreg(0x2E, 24, 8);
  delay(1000);
}

However this would not loop – the screen turns blue, then the screen turns permanently white and the serial monitor just outputs ‘0x00’ every second.

I’d greatly appreciate any thoughts. Thanks, Ben

prenticedavid commented 4 years ago

Your display is readable with 3.3V GPIO. Your display looks like a ST7735 controller. Run the readreg sketch.

The TFT_SPI code has not been touched for some time. I suspect that the low level code is no longer working.

I currently use ST7789_kbv library for SPI displays. Currently it only supports readGRAM() for ILI9341.

Reading GRAM or registers on a single SDA pin is painful with most MCUs. In practice few projects ever read GRAM. Which Arduino board are you using?

What do you really want to do? I suspect that you read the Camera and write to the screen.

David.

benlucy commented 4 years ago

Thanks for the reply - made some good progress.

Ran the readreg sketch from the ST7789_kbv library - it's an ST7735S.

The readreg sketch made me suspicious of my 'wiring defines' for the AVRfreaks code. I revisited it and now it is reading values other than 0x00 or 0xFF.

However, I am a little unsure about the MISO pin: a) The TFT module doesn't have an appropriate pin. b) It looks like MISO is not used for anything in the program. Deleting the one line setting MISO to INPUT_PULLUP in the AVRfreaks code has no effect.

I'm using a 5V nano with resistors to convert to 3.3V.

What I really want to do is:

  1. Use a camera to display a live image to the screen. The library for that is up and running successfully (https://github.com/indrekluuk/LiveOV7670). (This is the reason I'm trying to use this screen).
  2. Press a button to freeze the image on the screen.
  3. Read a row of pixels from the screen into an array (and convert to greyscale).
  4. Have a mechanical gantry 'draw' the row of pixels similar to this project: http://inventorartist.com/facere-bot/
  5. Repeat steps 3&4 for the rest of the pixels.

Therefore the speed of reading GRAM isn't very important. If the AVRfreaks code is giving me a legitimate value (which I haven't managed to test yet), then I just need to be able to 'aim' at a pixel before I read the 0x2E register and I'm good to go.

prenticedavid commented 4 years ago

I do not like 5V GPIO for anything. STM32 BluePill or ESP32 modules are 3.3V and cheap.

I am impressed with the OV7670 video. I have ordered a OV7670 from a UK Ebay shop. I have never played with a camera.

When the OV7670 arrives (Saturday) I will have an incentive to revisit the ST7735 project. Reading pixels from a stationary screen image is straightforward. Likewise grayscale. And storing on SD card.

Have you made the "mechanical gantry" ? Does it work ?

David.

benlucy commented 4 years ago

Excellent, I was sort of hoping the project would pique your interest. I've been itching to get building but I wanted to prove out yours and indrek's libraries first. I'm confident on the mechanical side but uncomfortable with the code, so if the libraries weren't fairly easy to get working then the project wouldn't be a goer. My previous project (inverted pendulum) used stepper motors so I'm not worried about getting the gantry running.

The camera/screen is great. I've only used Uno/Nano/ProMini so I just followed his youtube video to the letter and it worked first time. I might try out another board if there are no compatibility issues just to eliminate all the resistors . He also uses a WAVGAT Nano which has ~2x the clock speed and gets a much faster frame-rate, but for grayscale mode with the Arduino Nano the frame-rate delay is barely perceptible.

benlucy commented 4 years ago

Hello again, hope you’re well.

I recklessly went ahead and built the machine, despite not having the code sorted.

Could you help with reading GRAM? You said it is trivial to select a row of the screen and then read those pixels into an array (as per the application description in a previous post), but I haven’t come close to figuring it out. Is it possible that you can add some lines to your code on the AVR freaks forum so that it reads a whole row, and will read the next row once prompted? (The code you wrote here works on the nano although I haven't tested it on the mega: https://www.avrfreaks.net/forum/st7735-graphics-chip-read-frame-buffer-memory-over-spi?page=all).

I don’t know how big an ask that is. If you’re busy then some hints on how to do it would be great. I’m going to use an Arduino Mega because it’s compatible with the ‘live OV7670 camera’ code.

There’s no rush – I still have plenty to do (need to get the PCB made, write the code for interpreting the pixels into movement commands, and experiment with how the brush behaves).

Thanks, Ben

drawing machine

tjl1444 commented 3 years ago

Hi Ben,

I was just browsing the net trying to find out if SetAddressWindow() works on GRAM read operations as well as GRAM write operations, and I stumbled upon your post. I don't know if you still need help with the code, but I have provided some help below.

The code below reads a row of pixels from the GRAM starting at pixels (5,5) and stores them into an array of rgb values.

uint16_t rgbArray[100] = {0};

int16_t col = 5;
int16_t row = 5;
int16_t width = 10;
int16_t height = 1;

readGRAM(col, row, rgbArray, width, height);

Then if you want to go to new a row, just change the row variable and call the readGRAM function again.

benlucy commented 3 years ago

Hi, thanks for that tj. I never got this library compiling/working though and I so I couldn't check if that worked. I paid a freelancer to sort it out in the end - they started from David's original proof of concept code & now it's sorted.