SD and 16x2 LCD do not work together.

Hi,

I am trying to log and display temperatures. I have a Duemilanove on a breadboard
with this SD card module http://www.ebay.de/itm/Neu-SD-Memory-Card-Module-Slot-Socket-SPI-Reader-For-Arduino-ARM-MCU-3-3V-5V-/261073492935?pt=Wissenschaftliche_Geräte&hash=item3cc9315bc7
and this display http://www.ebay.de/itm/5pcs-New-5v-1602-LCD-Display-Module-Blue-for-Arduino-2560-UNO-R3-ARV-STM32-ARM-/280928964351?pt=Bauteile&hash=item4168abceff

Now, the logging works. Always. The LCD, however, stops working as soon as as SD.begin is called and holds the last text displayed. Without line 59-67, the display works fine again (but of course, the logging does not). So, the wireing seems to be ok. I don't know where to start searching the problem ...

Code can be seen at TempLogger - Pastebin.com

I click your code link and I get:

Your request has been blocked by XXX Information Security

XXX blocks Web sites which contain inappropriate content, those that contain malicious code, and those that provide services that may be unsafe to the XXX network and or its resources.

Where XXX is my company.

Post your code, or, if it is too large, make a sample that just illustrates the problem. It should not take more than 9500 characters to illustrate the problem.

Strange. I mean, it's pastebin. Pretty standard ...

// -----------------------------------------------------------------

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <SD.h>
 
// Data wire is plugged into pin 7 on the Arduino
#define ONE_WIRE_BUS 7
 
// Setup a oneWire instance to communicate with any OneWire devices 
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
 
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
float temperature = 0.0;

// -----------------------------------------------------------------

#include <LiquidCrystal.h>

// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

int backLight = 13;    // pin 13 will control the backlight

// -----------------------------------------------------------------

//SD card
const int sdPin = 9;
File logFile;

// -----------------------------------------------------------------

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control");
  // Start up the library
  sensors.begin();
  
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(16,2);              // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
  lcd.print("Dallas Temperature IC Control");    // change this text to whatever you like. keep it clean.
  lcd.setCursor(0,1);           // set cursor to column 0, row 1
  lcd.print("DS18B20");
  delay(1000);
  
  if(!SD.begin(sdPin)) {
    Serial.println("Failed to initialize SD card");
//    lcd.setCursor(0,0); 
//    lcd.println("Init SD failed  ");
  } else {
    Serial.println("SD initialized.");
//    lcd.setCursor(0,0); 
//    lcd.println("Init SD success ");
  }
  delay(1000);
}
 
 
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print(" Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  temperature = sensors.getTempCByIndex(0);

  Serial.print("Temperature for Device 1 is: ");
  Serial.println(temperature); // Why "byIndex"? 
    // You can have more than one IC on the same bus. 
    // 0 refers to the first IC on the wire
  lcd.setCursor(0,0);
  lcd.print(temperature);
  lcd.print("*C         ");
  lcd.setCursor(0,1);
  lcd.print(millis()/1000);
  lcd.print(" sec                 ");
  
  logFile = SD.open("cookLog.txt", FILE_WRITE);
  logFile.print(millis());
  logFile.print("\t");
  logFile.println(temperature);
  logFile.close();
}
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

Pins 11, 12, and 13 are the SPI pins. Those are generally the pins that are used to connect SD card readers.

How is your SD card reader connected to the Arduino?

Oh dammit. I put the µC and the display together some time ago and now I just assumed it also works with SPI - so I just wired everything like two SPI devices.
Obviously, it does not. So, that explains alot.

Thanks!

ElCaron, I think I'm experiencing the same problem as you, though I'm not sure what you mean by two different SPI interfaces. Could you elaborate a bit, perhaps posting your end-result pinout?

I'm using an ethernet shield, 20x4 LCD, and Arduino Mega. The LCD utilizes pins (7,8,9,10,11,12) and the SDCS at pin 4. I can run each component separately, though when combined together (specifically when I add the line 'lcd.setCursor(0,0)'), I fail to write anything to the SD.

ElCaron, I think this is just a matter of clashing pins. The lines of code that point to this are

// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

Where you don't assign pin 13, despite the comment.

I have had to do much the same thing. My SD is built in and selects with pin 4. I thus had no choice but re-wire the lcd pin 4 to A2 via an intermediate shield. You may have the same problem. Similarly, there could be problems with pin 10, which I understand the SD requires to be high, or it cannot write. Fortunately, my LCD is not interested in that.

Here is some code, the relevant bits of which may be of interest. BTW note that Arduino does not datestamp the CSVs, and you may need to go on to incorporate a clock!

/*
Reading two DS18B20s pins 14&15
display to monitor
display to LCD with pin D04 moved to pin 16 (A2)
Code uses Arduino LCD, sheepdog temp reader, SD stuff from Mellis & Igoe
*/

#define tture1 14//no ; here
#define tture2 15//no ; here

// include the library codes:
#include <LiquidCrystal.h>
#include <SD.h>

File myFile;

// initialize the library with the numbers of MY interface pins
LiquidCrystal lcd(8,9,16,5,6,7);

int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

void setup() {
    //For each tture sensor: Do a pinMode and a digitalWrite
    pinMode(tture1, INPUT);
    pinMode(tture2, INPUT);

    digitalWrite(tture1, LOW);//Disable internal pull-up.
    digitalWrite(tture2, LOW);

    Serial.begin(9600);
    delay(300);//Wait for newly restarted system to stabilize
    Serial.print("Temperature measurement, two sensors:\n\n");

  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
 
  
  Serial.print("Initializing SD card...");
 
   pinMode(10, OUTPUT);
   
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  lcd.clear();
  // Print a message to the LCD.
  lcd.print("SD card OK");    
  delay(2000);
   lcd.clear();
  lcd.print("temp   in   out");      
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);//+++++++++++++++++++ OPEN
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing! Did you forget the date?");
    myFile.close();//++++++++++++++++++++++++++++++++++++++++++++ CLOSE

    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
}

void loop(){

// set the LCD cursor to column 4, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(4, 1);
  readTture(tture1);//N.B.: Values passed back in globals
  printTture();//N.B.: Takes values from globals. Also...
     //no newline part of printTture;

  delay(120);// Delay... must not be too short.
  
  // set LCD cursor for second temp
  lcd.setCursor(11, 1);
  readTture(tture2);//Now read and report 2nd tture.
  printTture();
  delay(200);// Delay... must not be too short.
  Serial.print("\n");//Start new line
  
       myFile = SD.open("test.txt", FILE_WRITE);//+++++++++++++++++++++++++OPEN
       myFile.println();
    myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE
  delay(880); 
}

//Everything below here... just copy it into your program "as is".
//You are only likely to need to use readTture(pin) and printTture()
//   directly. Others are subordinate to those.
//These routine access the following global variables...
//   int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse
{
     digitalWrite(Pin, LOW);
     pinMode(Pin, OUTPUT); // bring low for 500 us
     delayMicroseconds(500);
     pinMode(Pin, INPUT);
     delayMicroseconds(500);
}
//end OneWireReset

void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
   byte n;

   for(n=8; n!=0; n--)
   {
      if ((d & 0x01) == 1)  // test least sig bit
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(5);
         pinMode(Pin, INPUT);
         delayMicroseconds(60);
      }
      else
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(60);
         pinMode(Pin, INPUT);
      }
      d=d>>1; // now the next bit is in the least sig bit position.
   }
}//end OneWireOutByte

byte OneWireInByte(int Pin) // read byte, least sig byte first
{
    byte d, n, b;

    for (n=0; n<8; n++)
    {
        digitalWrite(Pin, LOW);
        pinMode(Pin, OUTPUT);
        delayMicroseconds(5);
        pinMode(Pin, INPUT);
        delayMicroseconds(5);
        b = digitalRead(Pin);
        delayMicroseconds(50);
        d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
    }
    return(d);
}//end OneWireInByte

void readTture(byte Pin){
//Pass WHICH pin you want to read in "Pin"
//Returns values in... (See global declarations)
  OneWireReset(Pin);
  OneWireOutByte(Pin, 0xcc);
  OneWireOutByte(Pin, 0x44); // perform temperature conversion, strong pullup for one sec

  OneWireReset(Pin);
  OneWireOutByte(Pin, 0xcc);
  OneWireOutByte(Pin, 0xbe);

  LowByte = OneWireInByte(Pin);
  HighByte = OneWireInByte(Pin);
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
};//end readTture

void printTture(){//Uses values from global variables.
//See global declarations.
//N.B.: No new line inside printTture
      myFile = SD.open("test.txt", FILE_WRITE); //+++++++++++++OPEN
if (SignBit) // If it's negative
    {
     Serial.print("-");
     lcd.print("-");

     myFile.print("-");
    };
  Serial.print(Whole);
  Serial.print(".");
  lcd.print(Whole);
  lcd.print(".");
  myFile.print(Whole);
  myFile.print(".");
  if (Fract < 10)
    {
     Serial.print("0");
     lcd.print("0");
     myFile.print("0");
    };
  Serial.print(Fract);
  lcd.print(Fract);
  myFile.print(Fract);
    Serial.print("       ");
    myFile.print("  ,    ");
  myFile.close();//++++++++++++++++++++++++ CLOSE
};//end printTture