Problem displaying time via SPI

Hi all, first post so hope this is the appropriate area.

I am new to C programming would like to build an environment controller. Initially I have bought an Arduino Micro to get started.

The setup I am having trouble with at the moment is a sparkfun DT1307 RTC module and a 16x2 LCD fitted with an Adafruit backpack that only works in SPI mode I'm afraid (Adafruit are sending a replacement) I have had the LCD correctly displaying the temperature with a TMP36 but cannot get the RTC up and running.

I noticed the RTClib include is black in the IDE but it is installed in the user libraries only.

The LCD is wired for SPI as In this Adafruit tutorial: Arduino SPI Use | I2C/SPI LCD Backpack | Adafruit Learning System

The DT1307 is wired as in this bildr tutorial: http://bildr.org/2011/03/ds1307-arduino/

The code below compiles, uploads, the LCD then blinks and turns off completely -

#include <LiquidCrystal.h>
#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 RTC;
LiquidCrystal lcd(3, 2, 4);

void setup() {
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();  
  lcd.begin(16, 2);
  lcd.print("LCD Started..");
  //lcd.noAutoscroll();

  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  
  delay(2000);
}

void loop() {
  DateTime now = RTC.now();    
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Testing..");
  lcd.setCursor(0,1);
  lcd.print(now.month(), DEC);
  lcd.print("/");
  lcd.print(now.day(), DEC);
  lcd.print("/");  
  lcd.print(now.year(), DEC);
  lcd.print(" ");
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  lcd.print(now.minute(), DEC);
  delay(1000);
}

This is the working code that displays the TMP36 correctly - I would like to integrate this with a working RTC code.

// An example of displaying temperature on LCD.
// Temp sensor is TMP36.
// TMP36 --- Arduino --- LCD.
// by MHLAB
// 5/2012
// 
// References
// http://arduino.cc/en/Tutorial/LiquidCrystal
// http://www.ladyada.net/learn/sensors/tmp36.html

#include <LiquidCrystal.h>
#include <Wire.h>

#define aref_voltage 3.30 // To set the aref to ~3.3v

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


// Connect via SPI. Data pin is #3, Clock is #2 and Latch is #4
LiquidCrystal lcd(3, 2, 4);

// Variables to control the reading time interval and to average the reading:
int index = 0; // the index of the current reading
int readings = 0; // the readings from the analog input
unsigned long total = 0; // the sum of total readings
float average = 0.0; // the average of readings
float temp1 = 0.0; // temp oC of sensor 1

unsigned long time1 = 0; // Timing 1
unsigned long time2 = 0; // Timing 2

// constants won't change
const int numReadings = 1000; // sampling numbers for analog readings
const unsigned long timeInterval = 1000; // Setting for the interval of the output

// Pin numbers asignment TMP36 sensors
int inputPin1 = A1; // Read voltage of sensor tmp36

void setup()
{
  analogReference(EXTERNAL); // To set the aref to something other than 5v
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD starting at [0,0]
    lcd.setCursor(1, 0);      // Move cursor to our second line

  lcd.print("TEMP:");
}

void loop() {
  // Get the time by millis()
  time1 = millis();

  // reading average ADC of sensor 1
  average = averageTempAd(inputPin1);
  // convert ADC and convert it to Celsius
  temp1 = temperatureSensorTMP35(average); 

  // Print out to LCD
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(7, 0);
  // print the number of seconds since reset:
  lcd.print(temp1);
  lcd.print(char(223));
  lcd.print("C");
  //lcd.print("/");

  // Print out to LCD (oF)
  // set the cursor to column 8, line 1
  //lcd.setCursor(8, 1);
  //lcd.print(temp1*9/5+32.0);
  //lcd.print(char(223));
  //lcd.print("F");

  // Controll the data output timing: Using millis()
  while(time1 + timeInterval > millis()){
    // do nothing
  }
}

// Average temp function
float averageTempAd(int pinNumber){
  int aveADC;
  while (index < numReadings){
    readings = analogRead(pinNumber);
    // add the reading to the total:
    total= total + readings; 
    // advance to the next position in the array: 
    index = index + 1;
  }

  // Average AD number of temp
  aveADC = total / numReadings;

  // ...reset, wrap around to the beginning:
  index = 0; 
  total = 0;

  return aveADC;
}

// --- Convert to digit number to Temp oC ---
// TMP35 Temperature sensor calculation
// rawADC (10bit = 1024) to Temp (oC)
// Schematic:
// [Arduino] -- {TMP35}
// [Vcc (5 or 3.3v)] -- {Pin#1}
// [A1] -- {Pin#2} 
// [Ground] -- {Pin#3}
// converting from 10 mv per degree wit 500 mV offset
// to degrees ((volatge - 500mV) times 100)
 
float temperatureSensorTMP35(float rawADC) {
  float Temp; // Dual-Purpose variable to save space
  Temp = rawADC*aref_voltage/1024.0; // convert from Digital to voltage.
  Temp = (Temp - 0.5) * 100.0 ; // convert to oC
  return Temp; 
}

Check the connections of the DS1307 module again. Have you tried the module without the display, just sending the time values to the serial interface?

Check the voltage you have between the GND pin and the 5V pin when the sketch is running. What do you get?

Thanks for the reply pylon.

I get no voltage when the sketch is running but 5V when the arduino is reset. The connections are correct.

Nothing displays on serial monitor when I run the example DS1307 sketch in the RTC libray. In fact I have yet to see anything get sent to the monitor.

I get no voltage when the sketch is running but 5V when the arduino is reset. The connections are correct.

In this case you produced a short circuit somewhere. Check the wiring. If you don't find the reason make a picture of the whole setup and post it here.

Thanks again for the help pylon mate, much appreciated.

I will try and get a fritzing up later but you might be right in that there was a short connection somewhere. In the mean time I have been trying different methods and code to see if I can get a result and this one below I have hacked slightly from Henning Karlson gives this display:

TIME: 27:85:85
TEMP: get temp

xxx

I cannot see how those strange time values are there and my newb eyes fail to see how to set the time and date.

During this sketch the DS1307 reads 4.4v across 5v & gnd and 0v across SQW and gnd. I am using approx 12k pullup resistors with this one. Sorry no scope.

// DS1307_LCD (C)2010 Henning Karlsen

// DS1302:  SDA pin   -> Arduino Digital 4
//          SCL pin   -> Arduino Digital 5
//
// LCD:     DB7       -> Arduino Digital 2
//          DB6       -> Arduino Digital 3
//          DB5       -> Arduino Digital 4
//          DB4       -> Arduino Digital 5
//          E         -> Arduino Digital 11
//          RS        -> Arduino Digital 12

#include <LiquidCrystal.h>
#include <DS1307.h>
#include <Wire.h>

// Init the DS1307
DS1307 rtc(4, 5);

// Init the LCD

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


// Connect via SPI. Data pin is #3, Clock is #2 and Latch is #4
//LiquidCrystal lcd(3, 2, 4);

// Variables to control the reading time interval and to average the reading:
int index = 0; // the index of the current reading
int readings = 0; // the readings from the analog input
unsigned long total = 0; // the sum of total readings
float average = 0.0; // the average of readings
float temp1 = 0.0; // temp oC of sensor 1

unsigned long time1 = 0; // Timing 1
unsigned long time2 = 0; // Timing 2

// constants won't change
const int numReadings = 1000; // sampling numbers for analog readings
const unsigned long timeInterval = 1000; // Setting for the interval of the output

// Pin numbers asignment TMP36 sensors
int inputPin1 = A1; // Read voltage of sensor tmp36


void setup()
{
  analogReference(EXTERNAL); // To set the aref to something other than 5v
  //
  // Set the clock to run-mode
  rtc.halt(false);
  //pin 9 as pwm output for contrast
   pinMode(9, OUTPUT);  
  analogWrite(9, 0);   
  // Setup LCD to 16x4 characters
  lcd.begin(16, 4);

  // The following lines can be commented out to use the values already stored in the DS1307
  rtc.setDOW(SUNDAY);        // Set Day-of-Week to SUNDAY
  rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
  rtc.setDate(3, 10, 2010);   // Set the date to October 3th, 2010

  // Set SQW/Out rate to 1Hz, and enable SQW
  rtc.setSQWRate(SQW_RATE_1);
  rtc.enableSQW(true);
}

void loop()
{
  lcd.setCursor(0,0);
  lcd.print("TIME:");
  // Display time on the upper line
  lcd.setCursor(6, 0);
  lcd.print(rtc.getTimeStr());
  
  
  lcd.setCursor(0,1);
  lcd.print("TEMP:");
  // Display date in the lower right corner
  lcd.setCursor(6, 1);
  //lcd.print(rtc.getDateStr());
  lcd.print("get temp");



  // Display abbreviated Day-of-Week in the lower left corner
  lcd.setCursor(2, 3);
  lcd.print(rtc.getDOWStr(FORMAT_SHORT));
  
  // Wait one second before repeating :)
  delay (1000);
}

During this sketch the DS1307 reads 4.4v across 5v & gnd and 0v across SQW and gnd. I am using approx 12k pullup resistors with this one. Sorry no scope.

You don't need a scope for this. 4.4V is not enough for the DS1307. If the voltage drops to much (I think to remember it was 4.7V) it goes into a state where it doesn't answer to I2C requests anymore. If it drops more, it changes to the backup battery for current. So you have to make sure your power supply has enough power to drive your setup without droping the voltage. An USB connection often isn't a stable enough power source to read a DS1307.

Your time in binary decimal written as hex digits: 27:7F:7F
You get this if the line produces only logical ones, which is the case if a I2C device doesn't answer (bus is pulled up), although I would have expected the value 37 for the hour. As you didn't specify which of the many DS1307 libraries you use I have to guess how this result actually was created.

That is interesting pylon, I shall build a regulated 5v supply and try this out.

I think the DS1307 library is the one supplied in Hennings zip.

I believe that If I can get a square wave output from the DS1307 I can measure with a meter. Checking the datasheet it involves a pull-up resistor on the SQW output.

I think the DS1307 library is the one supplied in Hennings zip.

Link?

I believe that If I can get a square wave output from the DS1307 I can measure with a meter. Checking the datasheet it involves a pull-up resistor on the SQW output.

I don't see what you want to measure with a meter on that square wave output. What result do you expect and how should that resolve your problem?

pylon:
Link?

Here: Electronics - Henning Karlsen

pylon:
I don't see what you want to measure with a meter on that square wave output. What result do you expect and how should that resolve your problem?

Im so sorry pylon, I got mixed up in my conversations slightly, the advice given was that I could set the square wave output and measure a voltage reading. This would indicate the chip was at least working.

I have purchased a DS1307 IC and appropriate crystal to breadboard the RTC module just to make sure there is nothing wrong with the PCB. Below is some of Hennings code hacked into the working temp display code and a fritzing / pic of the current setup. I have also rigged up an 5V external breadboard PS, just in case the rtc wasn't getting enough power as suggested. (I have forgot to include the 3v external Ref on the main board in the fritzing)

The line:

// Set the clock to run-mode (error:turns off display)
  //rtc.halt(false);

As soon as I uncomment the rtc.halt command it turns off the display entirely, left commented out the display works and reads temp. I can initialise the RTC at the start but fails when set to run.

// An example of displaying temperature on LCD.
// Temp sensor is TMP36.
// TMP36 --- Arduino --- LCD.
// by MHLAB
// 5/2012
// 
// References
// http://arduino.cc/en/Tutorial/LiquidCrystal
// http://www.ladyada.net/learn/sensors/tmp36.html

#include <LiquidCrystal.h>
#include <Wire.h>
#include <DS1307.h>

// Init the DS1307
DS1307 rtc(4, 5);

#define aref_voltage 3.30 // To set the aref to ~3.3v

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


// Connect via SPI. Data pin is #3, Clock is #2 and Latch is #4
LiquidCrystal lcd(3, 2, 4);


// Variables to control the reading time interval and to average the reading:
int index = 0; // the index of the current reading
int readings = 0; // the readings from the analog input
unsigned long total = 0; // the sum of total readings
float average = 0.0; // the average of readings
float temp1 = 0.0; // temp oC of sensor 1

unsigned long time1 = 0; // Timing 1
unsigned long time2 = 0; // Timing 2

// constants won't change
const int numReadings = 1000; // sampling numbers for analog readings
const unsigned long timeInterval = 1000; // Setting for the interval of the output

// Pin numbers asignment TMP36 sensors
int inputPin1 = A1; // Read voltage of sensor tmp36

void setup()
{
  analogReference(EXTERNAL); // To set the aref to something other than 5v
  // set up the LCD's number of columns and rows: 
  
   // Set the clock to run-mode (error:turns off display)
  //rtc.halt(false);
  
  lcd.begin(16, 2);
  // Print a message to the LCD starting at [0,0]
    lcd.setCursor(1, 0);      // Move cursor to our second line

  lcd.print("TEMP:");
  
  
  // The following lines can be commented out to use the values already stored in the DS1307
  //rtc.setDOW(SUNDAY);        // Set Day-of-Week to SUNDAY
  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
  //rtc.setDate(3, 10, 2010);   // Set the date to October 3th, 2010

  // Set SQW/Out rate to 1Hz, and enable SQW
  //rtc.setSQWRate(SQW_RATE_1);
  //rtc.enableSQW(true);
}

void loop() {
  // Get the time by millis()
  time1 = millis();

  // reading average ADC of sensor 1
  average = averageTempAd(inputPin1);
  // convert ADC and convert it to Celsius
  temp1 = temperatureSensorTMP35(average); 

  // Print out to LCD
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(7, 0);
  // print the number of seconds since reset:
  lcd.print(temp1);
  lcd.print(char(223));
  lcd.print("C");
  //lcd.print("/");

  // Print out to LCD (oF)
  // set the cursor to column 8, line 1
  lcd.setCursor(1, 1);
  lcd.print("TIME:");
  
  //Display time on second line
  lcd.setCursor(7, 1);
  //lcd.print(rtc.getTimeStr());
  lcd.print("get time");

  // Controll the data output timing: Using millis()
  while(time1 + timeInterval > millis()){
    // do nothing
  }
}

// Average temp function
float averageTempAd(int pinNumber){
  int aveADC;
  while (index < numReadings){
    readings = analogRead(pinNumber);
    // add the reading to the total:
    total= total + readings; 
    // advance to the next position in the array: 
    index = index + 1;
  }

  // Average AD number of temp
  aveADC = total / numReadings;

  // ...reset, wrap around to the beginning:
  index = 0; 
  total = 0;

  return aveADC;
}

// --- Convert to digit number to Temp oC ---
// TMP35 Temperature sensor calculation
// rawADC (10bit = 1024) to Temp (oC)
// Schematic:
// [Arduino] -- {TMP35}
// [Vcc (5 or 3.3v)] -- {Pin#1}
// [A1] -- {Pin#2} 
// [Ground] -- {Pin#3}
// converting from 10 mv per degree wit 500 mV offset
// to degrees ((volatge - 500mV) times 100)
 
float temperatureSensorTMP35(float rawADC) {
  float Temp; // Dual-Purpose variable to save space
  Temp = rawADC*aref_voltage/1024.0; // convert from Digital to voltage.
  Temp = (Temp - 0.5) * 100.0 ; // convert to oC
  return Temp; 
}

You forgot to connect the grounds (of the external power supply and the Arduino, which gets it's power from the USB connection). Without a common ground you won't get a communication up between the components.