Custom pins numbers for SD card’s SPI bus: how to setup CS, MOSI, SCK, MISO?

Good day !
Mega2560wifi motherboard, 320 x 480 ILI9488 display, XPT2046 touch control, SD card datalogger.
As indicated in the link, the touch control and the sd card do not work together.
XPT2046 touch freezes if I initialize the SD card.

hardware pin assignment:(fix pins special board:3,95" lcd module for mega2560)
LCDWIKI_KBV my_lcd(ILI9488, 40, 38, 39, 43, 41); model,cs,cd,wr,rd,reset
LCDWIKI_TOUCH my_touch(53, 52, 50, 51, 44); //tcs,tclk,tdout,tdin,tirq
SD cs_pin 48
How can I make it work?
I pasted the sd lib from the previous example, it didn't get any better.

How to set to use a software spi for the SD card?

Please post a link to the actual display that you have bought. e.g. Ebay sale page.

Then we can give you accurate replies.

image

http://www.lcdwiki.com/3.95inch_Arduino_Display-Mega2560
My use Lib version : 3.95inch_Arduino_Mega2560_8BIT_V1.1

Thanks for the link. If you want to use MCUFRIEND_kbv library you need to configure as a "SPECIAL" e.g.

USE_SPECIAL
USE_MEGA_8BIT_PORTC_SHIELD
tft.begin(0x9488)

The SD Card will work fine with #define SD_CS 48
The Touch will work fine with #define TP_CS 53

Note that both SD and Touch are connected to the hardware SPI pins on a MEGA2560.
Which means that you use XPT2046_Touchscreen.h and regular SD.h

I am not familiar with the badly spelled library(s) from LCDWIKI.
They probably work. But I would not put money on it.

David.

I would like to use the MCUFRIEND_kbv library.
Please give me more precise instructions.
error: 'USE_SPECIAL' was not declared in this scope
#include <XPT2046_Touchscreen.h> The example doesn't work either!
:rage:

Read the how_to file e.g. on my PC it is
C:\Users\David Prentice\Documents\Arduino\libraries\Mcufriend_kbv\extras\mcufriend_how_to.txt

17. If you do not have a standard Uno Shield, you can add a SPECIAL to the mcufriend_special.h
    Edit mcufriend_shield.h:  #define USE_SPECIAL
    Edit mcufriend_special.h: e.g. #define USE_MEGA_16BIT_SHIELD
    If your "special" is write-only,  the library can not read the ID.  It always returns 0xD3D3

in your case you would enable USE_SPECIAL in
C:\Users\David Prentice\Documents\Arduino\libraries\Mcufriend_kbv\utility\mcufriend_shield.h
and enable USE_MEGA_8BIT_PORTC_SHIELD in
C:\Users\David Prentice\Documents\Arduino\libraries\Mcufriend_kbv\utility\mcufriend_special.h

and edit setup() in every sketch

The library is intended for Uno Shields from mcufriend.com. That is why I called it MCUFRIEND_kbv.
Yes, it is fiddly when you want to use SPECIAL wiring. But at least your Mega2560 Shield plugs straight into your MEGA2560 Arduino.

David.

All right.
The display works well.
It wasn't difficult to use the modifications.
Once again, the mcufriend library does not disappoint.
Congratulations.
I will continue the tests for using the touch and the sd card. Do you have any tips for the touch library?

Read a recent thread from cowboydaniel. It took a long time for him to get his screen working. https://forum.arduino.cc/t/3-95-tft-lcd-for-mega-2560-not-working/988124

There are example sketches at #41, #42, #66, #67, #90.

David.

SD.begin(48); unfortunately it doesn't work.
So far, with all the tested examples, either touch or sd works.
Not together!


//#include "Wire.h"
//#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <EEPROM.h>
#include "PCF8574.h"
#include <DS3231.h>
#include <Watchdog.h>
#include <XPT2046_Touchscreen.h>
#include "Adafruit_GFX.h"// Hardware-specific library
#include <MCUFRIEND_kbv.h>

#define CS_PIN  53
#define TIRQ_PIN  44
#define SD_CS 48

#define LCD_CS 40 // Chip Select goes to Analog 3
#define LCD_CD 41 // Command/Data goes to Analog 2
#define LCD_WR 37 // LCD Write goes to Analog 1
#define LCD_RD 38 // LCD Read goes to Analog 0
#define LCD_RESET 39 // Can alternately just connect to Arduino's reset pin

#define BLACK       0x0000      /*   0,   0,   0 */
#define NAVY        0x000F      /*   0,   0, 128 */
#define DARKGREEN   0x03E0      /*   0, 128,   0 */
#define DARKCYAN    0x03EF      /*   0, 128, 128 */
#define MAROON      0x7800      /* 128,   0,   0 */
#define PURPLE      0x780F      /* 128,   0, 128 */
#define OLIVE       0x7BE0      /* 128, 128,   0 */
#define LIGHTGREY   0xC618      /* 192, 192, 192 */
#define DARKGREY    0x7BEF      /* 128, 128, 128 */
#define BLUE        0x001F      /*   0,   0, 255 */
#define GREEN       0x07E0      /*   0, 255,   0 */
#define CYAN        0x07FF      /*   0, 255, 255 */
#define RED         0xF800      /* 255,   0,   0 */
#define MAGENTA     0xF81F      /* 255,   0, 255 */
#define YELLOW      0xFFE0      /* 255, 255,   0 */
#define WHITE       0xFFFF      /* 255, 255, 255 */
#define ORANGE      0xFDA0      /* 255, 180,   0 */
#define GREENYELLOW 0xB7E0      /* 180, 255,   0 */
#define PINK        0xFC9F

MCUFRIEND_kbv tft;
XPT2046_Touchscreen ts(CS_PIN, 255);
Watchdog watchdog;
DS3231 Clock;
PCF8574 PCF_01(0x20);
PCF8574 PCF_02(0x21);
PCF8574 PCF_03(0x22);




void setup() {
  watchdog.enable(Watchdog::TIMEOUT_4S);//Possible timeout durations are 15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1s, 2s, 4s, and 8s.

  Serial.begin(19200); //Start serial communication
  ts.begin();
  tft.reset();
  tft.begin(0x9488);
  ts.setRotation(1);
  tft.setRotation(1);

  // Wire.begin();
  PCF_01.begin();
  PCF_02.begin();
  PCF_03.begin();
  analogReference(INTERNAL2V56); // DEFAULT  INTERNAL1V1on Arduino UNO
  pinMode(klima1_hiba_pin, INPUT);
  pinMode(klima2_hiba_pin, INPUT);

  tft.fillScreen(BLACK);
  tft.drawRoundRect(5, 5, 470, 310, 8, LIGHTGREY);
  tft.drawRoundRect(10, 10, 460, 300, 7, DARKGREY);
  watchdog.reset();

  // tft.setTextColor(WHITE, BLACK);

  if (!SD.begin(SD_CS)) {
    tft.setTextColor(RED);
    tft.setTextSize(3);
    tft.setCursor(30, 130);
    tft.println(" SD card not detected!!" );
    tft.setCursor(30, 170);
    tft.println("        RESTART        ");//,

    while (1);
  }

  tft.setTextColor(BLUE);
  tft.setTextSize(4);

  tft.setCursor(20, 55);
  tft.println(" Szerencs vezerlo");
  tft.setCursor(24, 95);
  tft.println(" OPITHERM masina");//,

  tft.drawTriangle(30, 280, 40, 260, 50, 280, GREEN );

  delay(1000);
  watchdog.reset();
 

}

It's a simple test though.
What is a common mistake?

Go on. Please follow my standard advice :

  1. post link to hardware display. YES
  2. run example code. quote example by name. NO

I am fed up with repeating myself.

If an example fails, quote example name. Describe failure.
I would expect the #41, #66, #67, #90 examples from cowboydaniel thread to work.

I expect you to say which ones worked and which ones failed.

David.

@kefeur
You have the exact same screen I do. You are asking the same person for help that I did.
Please do exactly what he says, then you can be helped.

One issue I have noticed with the SD card slot on this screen.
Sometimes it randomly stops working in the middle of the code.
The way to fix this is to eject the card and then re-insert it and reset the board. You can try that, as it may not be code issues at all, but hardware issues.

How is your screen connected? Is is connected directly, or are you using jumpers?

Also, how large is your SD card? I found that the larger the card, the more trouble it gave me, so I settled with having to create partitions in my 16GB card. It doesn't work reliably over 4GB, so try making a single 4GB partition as a test. If you have a windows machine, you can use diskpart, but please follow some instructions as you can destroy your pc if you aren't careful!!

Let me know how that goes for you.

@kefeur
Try this code WITHOUT CHANGING A SINGLE LINE, and tell me what happens. You will have to upload a 100 x 100 bmp onto your SD card for testing purposes.

#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h> // Hardware-specific library
#include <MCUFRIEND_kbv.h>

MCUFRIEND_kbv tft;

#include <XPT2046_Touchscreen.h>           // Hardware SPI library
const int TS_LANDSCAPE = 1; //XPT2046_TouchScreen.h
const int TS_LEFT = 261, TS_RT = 3770, TS_TOP = 3869, TS_BOT = 296;
#define XPT_CS  53      // MEGA2560 SHIELD 
#define XPT_IRQ 255     // XPT2046 library does not like IRQ
XPT2046_Touchscreen ts(XPT_CS, XPT_IRQ);

int pixel_x, pixel_y;     //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
  bool pressed = ts.touched();
  if (pressed) {
    TS_Point p = ts.getPoint();
    if (TS_LANDSCAPE) mapxy(p.y, p.x);
    else mapxy(p.x, p.y);
  }
  return pressed;
}

void mapxy(int x, int y)                //maps ADC to pixel_x, pixel_y
{
  int aspect = tft.getRotation();     //LANDSCAPE
  int tft_width = tft.width();
  int tft_height = tft.height();
  switch (aspect & 3) {
    case 0:      //PORTRAIT
      pixel_x = map(x, TS_LEFT, TS_RT, 0, tft_width);
      pixel_y = map(y, TS_TOP, TS_BOT, 0, tft_height);
      break;
    case 1:      //LANDSCAPE
      pixel_x = map(y, TS_TOP, TS_BOT, 0, tft_width);
      pixel_y = map(x, TS_RT, TS_LEFT, 0, tft_height);
      break;
    case 2:      //PORTRAIT REV
      pixel_x = map(x, TS_RT, TS_LEFT, 0, tft_width);
      pixel_y = map(y, TS_BOT, TS_TOP, 0, tft_height);
      break;
    case 3:      //LANDSCAPE REV
      pixel_x = map(y, TS_BOT, TS_TOP, 0, tft_width);
      pixel_y = map(x, TS_LEFT, TS_RT, 0, tft_height);
      break;
  }
}

#define USE_TOUCH    0x2046

#define SD_CS 48
#define NAMEMATCH ""
#define PALETTEDEPTH   8     // support 256-colour Palette

char namebuf[32] = "/";

int pathlen;

#define BMPIMAGEOFFSET 54

#define BUFFPIXEL      20

uint16_t read16(File& f) {
  uint16_t result;         // read little-endian
  f.read((uint8_t*)&result, sizeof(result));
  return result;
}

uint32_t read32(File& f) {
  uint32_t result;
  f.read((uint8_t*)&result, sizeof(result));
  return result;
}

uint8_t showBMP(char *nm, int x, int y)
{
  File bmpFile;
  int bmpWidth, bmpHeight;    // W+H in pixels
  uint8_t bmpDepth;           // Bit depth (currently must be 24, 16, 8, 4, 1)
  uint32_t bmpImageoffset;    // Start of image data in file
  uint32_t rowSize;           // Not always = bmpWidth; may have padding
  uint8_t sdbuffer[3 * BUFFPIXEL];    // pixel in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
  uint8_t bitmask, bitshift;
  boolean flip = true;        // BMP is stored bottom-to-top
  int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
  uint32_t pos;               // seek position
  boolean is565 = false;      //

  uint16_t bmpID;
  uint16_t n;                 // blocks read
  uint8_t ret;

  if ((x >= tft.width()) || (y >= tft.height()))
    return 1;               // off screen

  bmpFile = SD.open(nm);      // Parse BMP header
  bmpID = read16(bmpFile);    // BMP signature
  (void) read32(bmpFile);     // Read & ignore file size
  (void) read32(bmpFile);     // Read & ignore creator bytes
  bmpImageoffset = read32(bmpFile);       // Start of image data
  (void) read32(bmpFile);     // Read & ignore DIB header size
  bmpWidth = read32(bmpFile);
  bmpHeight = read32(bmpFile);
  n = read16(bmpFile);        // # planes -- must be '1'
  bmpDepth = read16(bmpFile); // bits per pixel
  pos = read32(bmpFile);      // format
  if (bmpID != 0x4D42) ret = 2; // bad ID
  else if (n != 1) ret = 3;   // too many planes
  else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
  else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
  else {
    bool first = true;
    is565 = (pos == 3);               // ?already in 16-bit format
    // BMP rows are padded (if needed) to 4-byte boundary
    rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
    if (bmpHeight < 0) {              // If negative, image is in top-down order.
      bmpHeight = -bmpHeight;
      flip = false;
    }

    w = bmpWidth;
    h = bmpHeight;
    if ((x + w) >= tft.width())       // Crop area to be loaded
      w = tft.width() - x;
    if ((y + h) >= tft.height())      //
      h = tft.height() - y;

    if (bmpDepth <= PALETTEDEPTH) {   // these modes have separate palette
      //bmpFile.seek(BMPIMAGEOFFSET); //palette is always @ 54
      bmpFile.seek(bmpImageoffset - (4 << bmpDepth)); //54 for regular, diff for colorsimportant
      bitmask = 0xFF;
      if (bmpDepth < 8)
        bitmask >>= bmpDepth;
      bitshift = 8 - bmpDepth;
      n = 1 << bmpDepth;
      lcdbufsiz -= n;
      palette = lcdbuffer + lcdbufsiz;
      for (col = 0; col < n; col++) {
        pos = read32(bmpFile);    //map palette to 5-6-5
        palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
      }
    }

    // Set TFT address window to clipped image bounds
    tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
    for (row = 0; row < h; row++) { // For each scanline...
      // Seek to start of scan line.  It might seem labor-
      // intensive to be doing this on every line, but this
      // method covers a lot of gritty details like cropping
      // and scanline padding.  Also, the seek only takes
      // place if the file position actually needs to change
      // (avoids a lot of cluster math in SD library).
      uint8_t r, g, b, *sdptr;
      int lcdidx, lcdleft;
      if (flip)   // Bitmap is stored bottom-to-top order (normal BMP)
        pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
      else        // Bitmap is stored top-to-bottom
        pos = bmpImageoffset + row * rowSize;
      if (bmpFile.position() != pos) { // Need seek?
        bmpFile.seek(pos);
        buffidx = sizeof(sdbuffer); // Force buffer reload
      }

      for (col = 0; col < w; ) {  //pixels in row
        lcdleft = w - col;
        if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
        for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
          uint16_t color;
          // Time to read more pixel data?
          if (buffidx >= sizeof(sdbuffer)) { // Indeed
            bmpFile.read(sdbuffer, sizeof(sdbuffer));
            buffidx = 0; // Set index to beginning
            r = 0;
          }
          switch (bmpDepth) {          // Convert pixel from BMP to TFT format
            case 24:
              b = sdbuffer[buffidx++];
              g = sdbuffer[buffidx++];
              r = sdbuffer[buffidx++];
              color = tft.color565(r, g, b);
              break;
            case 16:
              b = sdbuffer[buffidx++];
              r = sdbuffer[buffidx++];
              if (is565)
                color = (r << 8) | (b);
              else
                color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
              break;
            case 1:
            case 4:
            case 8:
              if (r == 0)
                b = sdbuffer[buffidx++], r = 8;
              color = palette[(b >> bitshift) & bitmask];
              r -= bmpDepth;
              b <<= bmpDepth;
              break;
          }
          lcdbuffer[lcdidx] = color;

        }
        tft.pushColors(lcdbuffer, lcdidx, first);
        first = false;
        col += lcdidx;
      }           // end cols
    }               // end rows
    tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
    ret = 0;        // good render
  }
  bmpFile.close();
  return (ret);
}

#define BLACK       0x0000      /*   0,   0,   0 */
#define NAVY        0x000F      /*   0,   0, 128 */
#define DARKGREEN   0x03E0      /*   0, 128,   0 */
#define DARKCYAN    0x03EF      /*   0, 128, 128 */
#define MAROON      0x7800      /* 128,   0,   0 */
#define PURPLE      0x780F      /* 128,   0, 128 */
#define OLIVE       0x7BE0      /* 128, 128,   0 */
#define LIGHTGREY   0xC618      /* 192, 192, 192 */
#define DARKGREY    0x7BEF      /* 128, 128, 128 */
#define BLUE        0x001F      /*   0,   0, 255 */
#define GREEN       0x07E0      /*   0, 255,   0 */
#define CYAN        0x07FF      /*   0, 255, 255 */
#define RED         0xF800      /* 255,   0,   0 */
#define MAGENTA     0xF81F      /* 255,   0, 255 */
#define YELLOW      0xFFE0      /* 255, 255,   0 */
#define WHITE       0xFFFF      /* 255, 255, 255 */
#define ORANGE      0xFDA0      /* 255, 180,   0 */
#define GREENYELLOW 0xB7E0      /* 180, 255,   0 */
#define PINK        0xFC9F

Adafruit_GFX_Button on_btn, off_btn;

void setup() {
  Serial.begin(19200); //Start serial communication
  ts.begin();
  tft.reset();
  tft.begin(0x9488);
  ts.setRotation(1);
  tft.setRotation(1);

  tft.fillScreen(BLACK);
  tft.drawRoundRect(5, 5, 470, 310, 8, LIGHTGREY);
  tft.drawRoundRect(10, 10, 460, 300, 7, DARKGREY);

  // tft.setTextColor(WHITE, BLACK);

  if (!SD.begin(SD_CS)) {
    tft.setTextColor(RED);
    tft.setTextSize(3);
    tft.setCursor(30, 130);
    tft.println(" SD card not detected!!" );
    tft.setCursor(30, 170);
    tft.println("        RESTART        ");//,

    while (1);
  }

  tft.setTextColor(BLUE);
  tft.setTextSize(4);

  tft.setCursor(20, 55);
  tft.println(" Szerencs vezerlo");
  tft.setCursor(24, 95);
  tft.println(" OPITHERM masina");//,

  tft.drawTriangle(30, 280, 40, 260, 50, 280, GREEN );
  delay(5000);
  tft.fillScreen(BLACK);
  on_btn.initButton(&tft,  440, 280, 80, 80, LIGHTGREY, CYAN, BLACK, "ON", 2);
  off_btn.initButton(&tft,  440, 200, 80, 80, LIGHTGREY, CYAN, BLACK, "OFF", 2);
}

uint8_t ret;

bool down;

void loop() {
  down = Touch_getXY();
  on_btn.press(down && on_btn.contains(pixel_x, pixel_y));
  off_btn.press(down && off_btn.contains(pixel_x, pixel_y));
  on_btn.drawButton(false);
  off_btn.drawButton(false);
  if (on_btn.justReleased()) {
    on_btn.drawButton(true);
    off_btn.drawButton();
  }
  if (off_btn.justReleased()) {
    off_btn.drawButton(true);
    on_btn.drawButton();
  }
  if (on_btn.justPressed())
  {
    tft.fillScreen(BLACK);
    ret = showBMP("/01.bmp", 0, 0);
    on_btn.drawButton(true);
    off_btn.drawButton(false);
  }
  if (off_btn.justPressed())
  {
    tft.fillScreen(BLACK);
    off_btn.drawButton(true);
    on_btn.drawButton(false);
  }
}

Does the touch work?
Does the SD card work?
Do they both work?

David !
Ok .Test code:
#41-> no code!????


#66 draw-pen test : it works
#67 on-off button test : it works
#90 calculator : it works
The screen is connected directly to the motherboard.
Thank you.

None of them work because the screen says: "SD card not detected!!" displayed.

I use a small sd card, 128Mb, it works well with other datalogger programs that only use sd.(no touch, no display, The shield is connected directly to the motherboard with its own connector. .)

1 Like

My apologies. I should have said #42.
i.e. edit showBMP_kbv_Uno.ino

Seriously. I can only help if you provide accurate information.

David.

I beg your pardon. I was impatient.
A#42 works, bmp is displayed.
I'm doing exactly what you asked...

1 Like

Is your SD card connected? If it is, eject the SD card and reinsert it without turning the power off to your board.