PCF 8583 RTC chip troubles.

On my project to water potted plants, I have moved a step forward, alas two back.

Looking for which RTC to get, I went for the PCF 8583 one.

Found some libraries and included them.

These are the errors:
In file included from PCF8583.cpp:31:
PCF8583.h:70: error: 'byte' has not been declared
PCF8583.h:71: error: 'byte' does not name a type
PCF8583.cpp: In member function 'void PCF8583::get_time()':
PCF8583.cpp:54: error: 'byte' was not declared in this scope
PCF8583.cpp:54: error: expected `;' before 'incoming'
PCF8583.cpp:55: error: 'incoming' was not declared in this scope
PCF8583.cpp: In member function 'void PCF8583::set_time()':
PCF8583.cpp:81: error: 'int_to_bcd' was not declared in this scope
PCF8583.cpp:84: error: 'byte' was not declared in this scope
PCF8583.cpp: At global scope:
PCF8583.cpp:97: error: 'int PCF8583::bcd_to_byte' is not a static member of 'class PCF8583'
PCF8583.cpp:97: error: 'byte' was not declared in this scope
PCF8583.cpp:98: error: expected ',' or ';' before '{' token
PCF8583.cpp:102: error: 'byte' does not name a type

Attached is the sketch.

I had to change parts of the library as well as it had old terms in it like:
WIre.transmit and Wire.receive which had to be changed to the newer terms.

No big, but then some of the other errors are a bit beyond me just now.

I AM working on them as well, but would appreciate a bit of a shove in the right direction.

I am also needing help with the libraries so that a "Day of the week" value is accessible to me and that would have to be done at the .ccp or .h level.

I shall try to contact the person who wrote it and ask/annoy him, but to be fair, I was hoping someone here could/would help.

Thanks.

P.S.

I have found a later version of said libraries but I still get errors.

This is the error:

In file included from read_write_time_alarm.pde:3:
E:\Shepherd's documents\Arduino\libraries\PCF8583/PCF8583.h:81: error: 'byte' has not been declared
E:\Shepherd's documents\Arduino\libraries\PCF8583/PCF8583.h:82: error: 'byte' does not name a type

and the sketch is .....
(see attached)

V7a.zip (5.74 KB)

read_write_time_alarm.pde (2.27 KB)

Now I'm lost and confused.
What is the read_write_time_alarm.pde file ? Is that your sketch ?
What is the V7a.ino file ? Is that the example with the library or your sketch ?

The library is old, but can be updated easily.
The read_write_time_alarm.pde seems to use a different library (there is no init and no hour_A and no alarm).

V7a is my pot plant sketch with the libraries for the 8583 RTC chip.

It has all the files needed.

Because of errors with the "libraries" (.h and .cpp/.ccp files) I downloaded a "new" version which I found.

New. Ha! It too has problems and isn't "supported" but the latest IDE.

So:
V7a.ino is the whole thing on which I am working.

read_write_time_alarm.pde is the supplied sketch with the libraries which also doesn't work.

The first block of "code" is the errors I get when trying to compile the V7a sketch.
I thought BYTE was a standard word/command and so I am perplexed why I am getting the errors I am getting.

The second block of "code" is the errors I am getting when trying to compile the read_write_time_alarm file.

The V7a.zip, is that your projects file ?
I want to bring the PCF8583.cpp and PCF8583.h into your project, that makes it easier to change them.

Can you do the next steps

  • Remove the PCF8583 library from the library folder
  • Copy files form the V7a.zip into a project folder, or create new files with the dropdown menu (right upper corner) and create PCF8583.cpp and PCF8583.h into you project.
  • PCF8583.h, remove the "#include <WProgram.h>" and "#include <../Wire/Wire.h>".
  • PCF8583.cpp, remove the same two includes and replace them with "#include <Arduino.h>" and "#include <Wire.h>.
  • V7a (V7a.ino), remove the "#include <stdio.h>".
  • Solve the remaining errors in the V7a file. I don't know if it is me, but I can't figure out what the code is supposed to do.

G'day.

Sorry for the delay. "Lost" internet connection. (Went over the limit and was "shaped" to dial up speed.)

I tried what you said. Kinda worked.

Here is my latest at your example sketch.

What I would like to do is also get a "day of the week" from the RTC. Reading the documentation of the RTC Chip, it supports this, but your libraries don't have that implemented.

My project is a plant watering system and I need to be able to set a time and day of the week to water them. "Day": Be it one day a week or marked days. But to do this, I need a "day of the week value.

Thanks.

read_write_time.zip (3.09 KB)

The code is not my library, I don't even know the PCF8583. But I know how to read a datasheet.

You can remove the "#include <WProgram.h>" from PCF8583.cpp

Most RTC chips have the day of the week.
According to the datasheet, the PCF8583 has 'weekdays' from 0 to 6.
It is in location 06h together with the month.
You can add 'weekdays' by changing the code at every line that contains the 'month'.
Can you do that ? I should I try ?

You can use the attached zip file. I did not test the code, since I don't have a PCF8583.
I hope you did not change the code in the meanwhile.
If you want to set the day of the week with the serial monitor, uncomment the line that reads the format with day of the week added in it.

read_write_time.zip (3.15 KB)

Thanks.

No the code hasn't been changed since the posting.

I am too stuck on it to try - and other things are happening which are stopping much happening there as well.

Thanks very much for that. Libraries are still beyond me.

Sorry if there was confusion about you writing the code. Somewhere your name came into things and there was a mis-understanding.

If it works I shall apply the changes to my REAL code and get to the next step in my plant watering system which is now becoming a bit of a joke on progress of the code.

I still have quite a long way to go with the mechanical parts which is a real annoyance.

Anyway, I'll stop here and get around to looking at the code.

Bye for now.

Thanks.

Looked at code.

I think I can get my head around that.

Shall go away and try to implement it.

Ok,

Something is not working.

I ran the I2C sketch and it sees the device - RTC - and so I compiled the alarm sketch.

I am getting "weird" times - which is to be expected if the time has not been set - but when I send it the set time command (120101010101; as an example) it keeps sending the same erroneous data.

I've tried with and without the pull up resistors on the I2C bus.

Sorry folks, need a nudge.
:slight_smile:

Ok, learned something:

// provide device address as a full 8 bit address (like the datasheet)
PCF8583::PCF8583(int device_address)

Yes, I am going to look like an idiot, but I know I am, so it is nothing new.

The address is 0x51 (or 81 decimal)

Where/how do I define this?

I can't find device_address anywhere in the code.

Full code a few posts back.

There is some confusion over the I2C address in general.
Some manufacturers use 8-bit unshifted address, some use 7-bit shifted.

The Arduino Wire library uses the 7-bit address (which is actually the shifted address). The 7-bit address is the most used way to interpret an address.

The PCF8583 uses the address for the Wire library, so it needs the 7-bit address.

To avoid all problems, use the i2c scanner, Arduino Playground - I2cScanner
Use the (hexadecimal) address it finds. That is what the Wire library uses.

The PCF8583 code does not use a begin() function. The address is set into the class when the class is created.

The class is created in the *.ino file.
This line: PCF8583 p (0xA0);
creates a PCF8483 class called 'p', and the address 0xA0 is written into the class.

Now that I'm writing this, the address 0xA0 is wrong. That is an 8-bit value, and we need a 7-bit value.

I'm pretty sure that is the one I used to get the 0x51 address.

So, with that, as I sort of asked: Where do I put that in?

QUOTE:
The PCF8583 code does not use a begin() function. The address is set into the class when the class is created.

The class is created in the *.ino file.
This line: PCF8583 p (0xA0);
creates a PCF8483 class called 'p', and the address 0xA0 is written into the class.

Ok, so I change the 0xA0 to 0x51 and all should be ok?

I think I tried that and got the same results of bad data being displayed.

Thanks, shall try it again though.

Shall keep you posted.

Ok this is the part of the code:

int correct_address = 0;
PCF8583 p (0x51);	
void setup(void){

When the sketch is running this is what I get:

02/25/45 07 165:165:165
setting date
02/25/45 07 165:165:165
02/25/45 07 165:165:165
02/25/45 07 165:165:165

when I put in: 13040118201800;

I have the day of the week enabled.

See attached sketch.

read_write_time_V2.zip (3.19 KB)

I'm sorry, I made a mistake.

I read the code once more. In PCF8583.cpp the address is shifted from an 8-bit address to a so called 7-bit address.

PCF8583::PCF8583(int device_address) 
{
  address = device_address >> 1;  // convert to 7 bit so Wire doesn't choke
  Wire.begin();
}

Are you sure that the 0x51 the result of i2c_scanner ?
You can use 0x51 and remove that ">> 1".
Or you can shift it to 8-bit address and use 0xA2.

If 0x51 is shifted to left, it becomes 0xA2.

Thank you thank you thank you.

Got it working.

Now back to the "main" sketch and all that.

Thanks again.

Hmmmm...

Weird.

I had to re-write a lot of the code so it talks to the new RTC and the "delays" are real, not delay() functions.

So the code?

Well, there is a problem.

It doesn't seem to work. The clock is ticking - if the block of code is enabled in the main "loop" part of the code.

But other routines access the RTC and when they do, the time doesn't change.

op_solenoid() calls the RTC to get the time but the time it gets is "stuck" at the same time every call, which kind of defeats the purpose of an RTC.

Yes, it is messy, but I would like someone's input on what is going wrong.

in the "op_solenoid" function there are two blocks of "test code" which are surrounded by
/////////////////
// test code

/////////////////

In "loop" there is a block which prints the time - I can see it ticking over quite well, when "nothing is going on".

Stimulating the input (pin 2) low, it SHOULD start to cycle the 5 outputs.

It gets stuck on the first one because when you see the time/s scroll past, you will notice/see that it isn't ticking.
Yet it was when there was nothing going on.

In op_solenoid there is a lot going on to say.

It gets the "index" from the previous routine and activates that solenoid.
The index gets a value of 'n' seconds for that solenoid to run.
Yes, there are more/other loops happening which are to detect water levels and abort if the pot is full of water or the main reserve is empty.

But it "delays" for those seconds before going to the next solenoid.

It uses p.second - stored as sec_now - to count down that many seconds.
But reading the time the values don't change.

and I am confused why this is happening.

Please. Anyone?

V7c.zip (6.07 KB)

Well, I found the problem.

I was not reading the time in the loop. So that is why it wasn't working.

That problem fixed.

This is the sketch now.

As I am new to Serial.read() and the like, I may need a bit of help.

I included the ability to set the time/date from the other read/write time sketch.

I changed a bit of it so when it sets the time it displays it back, so I know it is set.

Alas it doesn't.

That was done quite easily by just adding a couple of lines from the sketch which display the time anyway.

So in part it looks like:

  if(Serial.available() > 0)
  {
       p.year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48)) + 2000;
       p.month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
       // weekdays, format YYMMwwddhhmmss;
       p.dow = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
       p.date = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
       p.hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
       p.minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
       p.second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  

       if(Serial.read() == ';')
       {
         Serial.println("setting date");
	 p.set_time();

         delay(400);
         p.get_time();
         char time[50];
         sprintf(time, "%02d/%02d/%02d %02d %02d:%02d:%02d",
         p.year, p.month, p.date, p.dow, p.hour, p.minute, p.second);
         Serial.println(time);

       }
  }

That way I can reset the time if ever I want to with this sketch and don't have to re-flash a program to set the RTC.

But I don't know why it isn't accepting the time.

I'm working on it too, but would like any help.

V7d.zip (6.27 KB)

I think that the set_time() function is good.
So the part you posted must be the problem.

If you send a line from the serial monitor, there could be a trailing "Carriage Return" and "Line Feed".

"Carriage Return" = CR = 0x0D = '\r'
"Line Feed" = new line = LF = 0x0A = '\n'

You have to discard those.
You can read the serial data, and if it is not a number, just throw away the read character.
If it is a number, it should be the start of the YYMMwwddhhmmss; string, and you can write the time.

I would like to read the YYMMwwddhhmmss; in a buffer before it is used to set the time.
The code as it it now, reads the serial port without knowing if that character is available.
Perhaps that is something for later. For now I added a delay to be sure that the whole string has been transferred into the buffer of the Serial library.

The code below is an example with the code as it is now.

if( Serial.available() > 0)
{
  int incoming = Serial.read();
  
  // Test if the character is a number.
  if( isdigit( incoming))
  {
    // The string to set the date is being received.
    // Wait some time to be sure that the whole string
    // is received and ready in the buffer of the Serial library.
    delay( 100);

    // The first byte is already read in the 'incoming' variable.
    p.year= (byte) ((incoming - 48) *10 +  (Serial.read() - 48)) + 2000;
    ....
  }
}

Thanks.

The "serial data" is read and the ; at the end is used as the terminator - as said in the code.

But as I see the data is not read into a "buffer".

So if I want to test for things, as I do that, the original data is "corrupted".

As you implied it would be better if it was read into a "buffer" and then I could check it before passing it to the other routine.

But what is also confusing me is that the time set routine works and it says it is setting the time. I added the extra line/s so it prints the time. Again: From the original sketch.

But it doesn't print!

The original sketch is constantly printing the time, so it is academic to print it when set, but as I am not always printing the time repeatedly it is not possible.

That's why I put the extra couple of lines in the sketch:

       if(Serial.read() == ';')
       {
         Serial.println("setting date");
	 p.set_time();

         delay(400);
         p.get_time();
         char time[50];
         sprintf(time, "%02d/%02d/%02d %02d %02d:%02d:%02d",
         p.year, p.month, p.date, p.dow, p.hour, p.minute, p.second);
         Serial.println(time);

       }

So it sees the ; it sets the time (p.set_time() ) then it delays 400ms, reads the time and prints it.

So why isn't it happening?

I shall read your other code and attempt to implement it. Still learning.

Looking at your code:

if( Serial.available() > 0)
{
  int incoming = Serial.read();
  
  // Test if the character is a number.
  if( isdigit( incoming))
  {
    // The string to set the date is being received.
    // Wait some time to be sure that the whole string
    // is received and ready in the buffer of the Serial library.
    delay( 100);

    // The first byte is already read in the 'incoming' variable.
    p.year= (byte) ((incoming - 48) *10 +  (Serial.read() - 48)) + 2000;
    ....
  }
}

"incoming" is an integer.

The data being sent in ends with a ; so will "int" work?

And how would it work if I sent it a line of code like:

time;

to make it send/print the time.

I am looking at the example sketches but at this point the are still beyond me understanding.

Oh, silly me!

I didn't think to look at the second sketch "read write time with alarm"

Actually I was starting to think along those lines anyway, with a PRE Header!

That way the first char switches what is done.

Shall try and post results.

Drats!

That has opened up a whole other can of worms.

V7d.ino: In function 'void loop()':
V7d:139: error: 'class PCF8583' has no member named 'hour_A'
V7d:140: error: 'class PCF8583' has no member named 'minute_A'
V7d:141: error: 'class PCF8583' has no member named 'second_A'
V7d:144: error: 'class PCF8583' has no member named 'set_daily_alarm'
V7d:163: error: 'class PCF8583' has no member named 'get_alarm'
V7d:165: error: 'class PCF8583' has no member named 'hour_A'
V7d:165: error: 'class PCF8583' has no member named 'minute_A'
V7d:165: error: 'class PCF8583' has no member named 'second_A'

Looking in the sketch, I can't find them and as I had not been working on that one, the libraries are "back to square one" with their errors.