Pages: [1]   Go Down
Author Topic: Failed SD Initialisation Makes SPI Slow Speed  (Read 1157 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
God Member
*****
Karma: 17
Posts: 568
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This involves both an SD Card and TFT but it's the card that seems to cause an issue so I thought this was the best place to ask.

I've got a 128x160 7735R driven colour TFT display, compatible with the AdaFruit 7735 and I'm using that library. I'm also using the SD library for the onboard SD card slot.

The Adafruit library supports a 'soft SPI' mode and a hardware SPI. With both the TFT and SD connected as hardware SPI everything works fine if the SD Card initialises properly, i.e. a card in the slot. However, if there is no card in the slot then SD initialisation fails, as expected, but the subsequent test of the TFT is in slow speed, as if it's on soft SPI mode.

I'm suspecting that the SD library is somehow leaving the SPI bus set at a slower speed, after low speed initialisation attempt. SInce TFT is already initialised at that point (I'm outputting to the screen already), it doesn't seem to look at the SPI speed to see if it's still in the same mode.

I'm sure someone can confirm if I'm on the right track, but then how to resolve this? I've not included the functions as the text was too large for a post, but it's just the standard, unmodified, functions from the test script and they all work fine if there is a card in the slot, or no SD Card included in the sketch.

Code:
/***************************************************
  This is an example sketch for the Adafruit 1.8" SPI display.
  This library works with the Adafruit 1.8" TFT Breakout w/SD card
  ----> http://www.adafruit.com/products/358
  as well as Adafruit raw 1.8" TFT display
  ----> http://www.adafruit.com/products/618
 
  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

// You can use any (4 or) 5 pins
//#define tftSCL 7 // serial clock when driving tft non-spi
//#define tftSDA 6 // serial data when driving tft non spi
#define tftCS 10 // CS pin for tft
#define tftDC 8 // DC/AO pin for tft
#define tftRST 7 // reset for tft;  or can be connected to Arduino reset

#define sdCS 4 // CS pin for SD card
#define BUFFPIXEL 20 // how many pixels to buffer when reading in bitmaps from SD card

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <SD.h>

// Option 1: use any pins but a little slower
// Adafruit_ST7735 tft = Adafruit_ST7735(tftCS, tftDC, tftSDA, tftSCL, tftRST);

// Option 2: must use the hardware SPI pins - much faster and can share  SD and other devices
Adafruit_ST7735 tft = Adafruit_ST7735(tftCS, tftDC, tftRST);

float p = 3.1415926;

void setup(void) {
  Serial.begin(115200);
  Serial.println(F("Hello!"));

  // Our supplier changed the 1.8" display slightly after Jan 10, 2012
  // so that the alignment of the TFT had to be shifted by a few pixels
  // this just means the init code is slightly different. Check the
  // color of the tab to see which init code to try. If the display is
  // cut off or has extra 'random' pixels on the top & left, try the
  // other option!

  // If your TFT's plastic wrap has a Red Tab, use the following:
  tft.initR(INITR_REDTAB);   // initialize a ST7735R chip, red tab
  // If your TFT's plastic wrap has a Green Tab, use the following:
  //tft.initR(INITR_GREENTAB); // initialize a ST7735R chip, green tab
 
  tft.setTextWrap(false);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST7735_RED);
  tft.setTextSize(1);
  tft.println(F("Welcome"));
  tft.setTextColor(ST7735_YELLOW);
  tft.setTextSize(1);
  tft.println(F("This is the 128x160"));
  tft.println(F("Test Screen"));
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(1);
  tft.println(F("Enjoy!"));
  tft.setTextColor(ST7735_BLUE);
  tft.setTextSize(1);
  tft.println(F("Mick"));

  tft.setTextSize(1);
  tft.println();
 
  Serial.print(F("Initializing SD card..."));
  tft.println(F("Initializing SD card..."));
  if (!SD.begin(sdCS)) {
    Serial.println(F("Failed!"));
    tft.println(F("Failed!"));
    pinMode(sdCS, OUTPUT);
    digitalWrite(sdCS, HIGH);
    //return;
  }
  Serial.println(F("OK!"));
  tft.println(F("OK!"));
 
 
  int sec = 5;
 
  while(sec != -1)
  {
    tft.print(sec);
    tft.println(F("..."));
    sec -= 1;
    delay(1000);
  }
 
  tft.println(F("GO!!!!!!"));
  delay(2000);
 
  //bmpDraw("parrot.bmp", 0, 0);
  //delay(4000);

  uint16_t time = millis();
  tft.fillScreen(ST7735_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);
  delay(500);

  // large block of text
  tft.fillScreen(ST7735_BLACK);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST7735_WHITE);
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(4000);

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, ST7735_GREEN);
  delay(500);

  // line draw test
  testlines(ST7735_YELLOW);
  delay(500);

  // optimized lines
  testfastlines(ST7735_RED, ST7735_BLUE);
  delay(500);

  testdrawrects(ST7735_GREEN);
  delay(500);

  testfillrects(ST7735_YELLOW, ST7735_MAGENTA);
  delay(500);

  tft.fillScreen(ST7735_BLACK);
  testfillcircles(10, ST7735_BLUE);
  testdrawcircles(10, ST7735_WHITE);
  delay(500);

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);

  Serial.println("done");
  delay(1000);
}

void loop()
{
  int i = 0;
 
 
  while(i<3)
  {
    tft.invertDisplay(true);
    delay(500);
    tft.invertDisplay(false);
    delay(500);
    i += 1;
  }
 
   
  //bmpDraw("parrot.bmp", 0, 0);
   
  while(1); // loop here forever; i.e stop main loop
   
}
« Last Edit: January 23, 2013, 03:54:17 pm by tack » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yup, known 'feature' of failed SD card initialization. One option is to change the library or make your own code to check for the fail.
Logged

UK
Offline Offline
God Member
*****
Karma: 17
Posts: 568
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the reply. That was pretty much what I was expecting.

I'll give SDFatLib a try as it looks like that fixes a few issues.
Logged

0
Offline Offline
Edison Member
*
Karma: 64
Posts: 1639
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The problem is with the TFT library.  Any library for a device on the SPI bus must set the the speed and mode before each access.  Often devices that share the SPI bus have very different needs so a library can not assume its SPI settings will be preserved between accesses to the SPI bus.

SdFat sets the mode and speed before each SPI access.  SD cards require a very slow speed for initialization so a failure during initialization will result in a slow SPI speed.  The next device will be slow and may even use the wrong SPI mode unless it initializes the bus before each access.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the problem has solution.
You need to edit line 325 in Sd2Card.cpp adding:
  setSckRate(sckRateID);// Esto agregue
previus the return command.
This put the serial clock at previus value.
Sorry for my very bad english...
Logged

0
Offline Offline
Edison Member
*
Karma: 64
Posts: 1639
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
the problem has solution.
You need to edit line 325 in Sd2Card.cpp adding:
  setSckRate(sckRateID);// Esto agregue

This is not a good solution.  There is no guarantee this will be the correct SPI mode and speed for another library.

The best solution is for each library that uses the SPI bus to have a function that selects its device.  This function should set the correct SPI mode, speed, bit order, and then set chip select low for its device.  This is the only possible way to avoid problems when sharing the SPI bus between a number of devices. 
Logged

Pages: [1]   Go Up
Jump to: