Go Down

Topic: I'm Confused DS1307 & LCD (Read 4 times) previous topic - next topic

G_Man

I just received a DS1307 break-out board  from Sparkfun and decided to try it out.  So I downloaded Sjunnesson's library from the playground.  I hooked everything up and ran the example code.  That worked fine.  

I then decided to send the output to an LCD instead of the serial port.  So I mounted up a 16x2 LCD.  To test my hook up, I loaded up the LCD "Hello World" example and ran it.  It functioned fine.  

So then I sort of collided the two sketches like this:

Code: [Select]
#include <LiquidCrystal.h>
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int Hr=0;
int Mn=0;
int Sc=0;
int DD=0;
int MM=0;
int YY=0;

void setup() {
 lcd.begin(16, 2);
}

void loop() {

 Hr=RTC.get(DS1307_HR,true);
 Mn=RTC.get(DS1307_MIN,false);
 Sc=RTC.get(DS1307_SEC,false);
 DD=RTC.get(DS1307_DATE,false);
 MM=RTC.get(DS1307_MTH,false);
 YY=RTC.get(DS1307_YR,false);

 lcd.clear();
 lcd.print(MM);
 lcd.setCursor(2, 0);
 lcd.print("-");
 lcd.setCursor(3, 0);
 lcd.print(DD);
 lcd.setCursor(5, 0);
 lcd.print("-");
 lcd.setCursor(7, 0);
 lcd.print(YY);

 lcd.setCursor(0, 1);
 lcd.print(Hr);
 lcd.setCursor(2, 1);
 lcd.print(":");
 lcd.setCursor(3, 1);
 lcd.print(Mn);
 lcd.setCursor(5, 1);
 lcd.print(":");
 lcd.setCursor(6, 1);
 lcd.print(Sc);

 delay(1000);

}


When I run that, I get odd results.  Either the ":" and "-" characters do not show up and the time does not update or nothing shows at all.  So I altered the code to this:
Code: [Select]
#include <LiquidCrystal.h>
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int Hr=0;
int Mn=0;
int Sc=0;
int DD=0;
int MM=0;
int YY=0;

void setup() {
 lcd.begin(16, 2);
}

void loop() {

 Hr=RTC.get(DS1307_HR,true);
 Mn=RTC.get(DS1307_MIN,false);
 Sc=RTC.get(DS1307_SEC,false);
 DD=RTC.get(DS1307_DATE,false);
 MM=RTC.get(DS1307_MTH,false);
 YY=RTC.get(DS1307_YR,false);

 lcd.clear();
 lcd.print("Time:");
//  lcd.print(MM);
//  lcd.setCursor(2, 0);
//  lcd.print("-");
//  lcd.setCursor(3, 0);
//  lcd.print(DD);
//  lcd.setCursor(5, 0);
//  lcd.print("-");
//  lcd.setCursor(7, 0);
//  lcd.print(YY);

 lcd.setCursor(0, 1);
 lcd.print(Hr);
 lcd.setCursor(2, 1);
 lcd.print(":");
 lcd.setCursor(3, 1);
 lcd.print(Mn);
 lcd.setCursor(5, 1);
 lcd.print(":");
 lcd.setCursor(6, 1);
 lcd.print(Sc);

 delay(1000);

}


... and it functions as one would anticipate (after cycling the power).  The word "Time" shows up on the first line of the LCD and the time that updates every second on the second line.  What the heck am I missing?

PaulS

Does it work any better if you explicitly convert the numbers to strings before calling lcd.print?

Code: [Select]
char buffer[6];
sprintf(buffer, "%d", Hr);
lcd.print(buffer);

G_Man

#2
Nov 16, 2009, 06:13 pm Last Edit: Nov 17, 2009, 03:42 am by ggutshal Reason: 1
I'll try that once I get home.

G_Man

Well I tried it.  It didn't work.  A bar of blocks was displayed on the first line of the LCD and nothing else.  After trying it, I couldn't get anything to display from the real time clock.  Even using the code that worked before.  The LCD "Hello World" app however still works.  Now I'm really confused.  The DS1307 example code also still works.

Any other suggestions?

G_Man

No one has any other ideas?

mircho

It would benefit anyone trying to help you if you post the "new" code you say you used without success

G_Man

Right, sorry:

Code: [Select]

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

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

int Hr=0;
int Mn=0;
int Sc=0;
int DD=0;
int MM=0;
int YY=0;
char buffer[6];

void setup() {
 lcd.begin(16, 2);
}

void loop() {

 Hr=RTC.get(DS1307_HR,true);
 Mn=RTC.get(DS1307_MIN,false);
 Sc=RTC.get(DS1307_SEC,false);
 DD=RTC.get(DS1307_DATE,false);
 MM=RTC.get(DS1307_MTH,false);
 YY=RTC.get(DS1307_YR,false);

 lcd.clear();

 sprintf(buffer, "%d", Sc);
 lcd.print(buffer);  

 delay(1000);

}

ahdavidson

Some things to check, as I look at your code:

  • (Without having looked at the DS1307 library) Do you need any initialization calls to use the RTC.get() functions? I don't see anything in your setup () function.
  • Have you tried, in your loop () function, using Serial.println calls along with lcd.print in order to verify that you are getting good data and converting them to strings properly?
  • (Again without looking at libraries) Why do you have WProgram.h and Wire.h included in your program? Does DS1307 need them?
  • The fact that you say the LCD and RTC tests work independently of each other makes me suspect interference between them.
  • The boolean parameter passed to RTC.get seems to be for a refresh option. Why do you have some true and some false?

Hopefully, these questions might lead someplace useful in your investigation.

.andy
.andy

G_Man

I am suspecting some kind of interference between the libraries as well.  The behavior is just too random and unpredictable and I'm too green to find it.

Quote

   * (Without having looked at the DS1307 library) Do you need any initialization calls to use the RTC.get() functions? I don't see anything in your setup () function.


There was none in the DS1307 example code.

Quote

   * Have you tried, in your loop () function, using Serial.println calls along with lcd.print in order to verify that you are getting good data and converting them to strings properly?


The example code uses serial.Print to send out the data gleaned from the DS1307.  I hadn't tried sending it both to the LCD & serial simultaneously.

Quote

   * (Again without looking at libraries) Why do you have WProgram.h and Wire.h included in your program? Does DS1307 need them?


I presume that it does because they were in the DS1307 example code.

Quote

   * The fact that you say the LCD and RTC tests work independently of each other makes me suspect interference between them.


My thoughts exactly, but where and how?

Quote

   * The boolean parameter passed to RTC.get seems to be for a refresh option. Why do you have some true and some false?


Because you don't want to update the data you're reading prior to reading all of it.  Imagine reading the time directly at 59 minutes, 59.9999 seconds.  You get the proper hour, but suddenly the minute value reads "00" because you've updated and it rolled and you're data is now erroneously an hour old.

ahdavidson

More questions:

How is the RTC chip getting initialized? By that I mean, are you sure that it has valid time data in it and the battery powering it is good?

Are you getting the actual time from your computer and then loading that into the RTC ?

There are some RTC.set() functions in the library that you can use to load values into the clock chip, and there are RTC.start() and RTC.stop() calls to control it. The example I saw did use these.

Your latest test program only attempts to show the seconds; I assume that was just to test?

I don't know how the libraries might interact with each other and I don't know exactly which ones you have downloaded and are using, etc.

If I were trying to debug this, I would reduce it to the simplest case I could formulate, and try to get that working, then add in more stuff.

A simple case might be to push known values into the RTC (stop, set, set, set...) without starting it, and then verify you can get those values back and see them via serial and lcd output. Then put the values in and start the clock (stop, set, set, set... start) and see that you are getting updates. Do this without the sprintf buffer first.

Then once you know you are getting good data, add in the sprintf formatting and continue the verification.

I think you have too many floating unknowns right now and you need to reduce the problem to narrower test cases.

If I had one of those modules, I would happily play with it, as I plan to develop an RTC app soon myself.

.andy
.andy

mircho

Two things to propose:
- try outputing a constant integer, instead of the seconds.
- try updating the LCD more slowly. put a delay_microsecodns in the loop, delay for half a second and output something.

G_Man

#11
Nov 18, 2009, 07:59 am Last Edit: Nov 18, 2009, 08:16 am by ggutshal Reason: 1
OK, I've taken your advice.  I altered the code to this:

Code: [Select]

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

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

int Hr=0;
int Mn=0;
int Sc=0;
int DD=0;
int MM=0;
int YY=0;
char buffer[6];

void setup() {
 lcd.begin(16, 2);
}

void loop() {

 Hr=1;
 Mn=2;
 Sc+=1;
 DD=3;
 MM=4;
 YY=2009;

 lcd.clear();
 lcd.print(MM);
 lcd.setCursor(2, 0);
 lcd.print("-");
 lcd.setCursor(3, 0);
 lcd.print(DD);
 lcd.setCursor(5, 0);
 lcd.print("-");
 lcd.setCursor(7, 0);
 lcd.print(YY);

 lcd.setCursor(0, 1);
 lcd.print(Hr);
 lcd.setCursor(2, 1);
 lcd.print(":");
 lcd.setCursor(3, 1);
 lcd.print(Mn);
 lcd.setCursor(5, 1);
 lcd.print(":");
 lcd.setCursor(6, 1);
 lcd.print(Sc);

 delay(1000);

}


It does not work.  If however I comment out the "#include <DS1307.h>" line, it functions as one would anticipate.  That pretty much localizes it.  Does anyone have an idea how to fix it?

mircho

How did you connect the LCD and the RTC? Can you post a schematic or at least a simple drawing? It might be a lines signal problem.

G_Man

Ok, I've been playing some more with the code.  I followed the other DS1307 link on the playground and adapted the code I found there. The following functions just fine:

Code: [Select]

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address

// Global Variables
int second, minute, hour, dayOfWeek, dayOfMonth, month, year;

void setup() {
 Wire.begin();
 Serial.begin(57600);
}

void loop() {

   getDateDs1307();
 
   Serial.print(month);
   Serial.print("/");
   Serial.print(dayOfMonth);
   Serial.print("/");
   Serial.print(year);
   Serial.println();

   Serial.print(hour);
   Serial.print(":");
   Serial.print(minute);
   Serial.print(":");
   Serial.print(second);
   Serial.println();

   delay(500);
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
 return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
 return ( (val/16*10) + (val%16) );
}

// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
 // Reset the register pointer
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.send(0x00);
 Wire.endTransmission();

 Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

 // A few of these need masks because certain bits are control bits
 second     = bcdToDec(Wire.receive() & 0x7f);
 minute     = bcdToDec(Wire.receive());
 hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
 dayOfWeek  = bcdToDec(Wire.receive());
 dayOfMonth = bcdToDec(Wire.receive());
 month      = bcdToDec(Wire.receive());
 year       = bcdToDec(Wire.receive());

}


However as soon as I add the LCD library and declare an instance, things head south.

Code: [Select]

#include "Wire.h"
#include <LiquidCrystal.h>
#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address

// Global Variables
int second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
 Wire.begin();
 lcd.begin(16, 2);
}

void loop() {
   getDateDs1307();

   lcd.clear();
   lcd.print(month);
   lcd.setCursor(2,0);
   lcd.print("/");
   lcd.setCursor(3,0);
   lcd.print(dayOfMonth);
   lcd.setCursor(5,0);
   lcd.print("/");
   lcd.setCursor(6,0);
   lcd.print(year);

   lcd.setCursor(0, 1);
   lcd.print(hour);
   lcd.setCursor(2,1);
   lcd.print(":");
   lcd.setCursor(3,1);
   lcd.print(minute);
   lcd.setCursor(5,1);
   lcd.print(":");
   lcd.setCursor(6,1);
   lcd.print(second);

   delay(500);
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
 return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
 return ( (val/16*10) + (val%16) );
}

// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
 // Reset the register pointer
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.send(0x00);
 Wire.endTransmission();

 Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

 // A few of these need masks because certain bits are control bits
 second     = bcdToDec(Wire.receive() & 0x7f);
 minute     = bcdToDec(Wire.receive());
 hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
 dayOfWeek  = bcdToDec(Wire.receive());
 dayOfMonth = bcdToDec(Wire.receive());
 month      = bcdToDec(Wire.receive());
 year       = bcdToDec(Wire.receive());
}


If I leave the Serial.print statements in the code and comment out everything BUT the instantiation of the LCD instance ("LiquidCrystal lcd(12, 11, 5, 4, 3, 2);") then the code ceases to function.

Here is the schematic you've asked for:


mircho

OK, now you've shuffled some things around and you can repeat the same tests.
Does the LCD driver work by itself (as in the previous occasion). If so - does adding the DS1307 driver make things worse?
Because now you show the opposite behavior than before - the clock working, and adding the LCD "sends things south".
The connections seem OK to me.
I would check if the drivers in their initialization parts make some strange assumptions and initialize other ports and pins than the ones they need. Also if some strange and long delays are used.

Go Up