Hi, Can anybody give me an example how to retrieve minutes and hours from a PCF8583 and add them to previously retrieved minutes and hours, and store them in a 24LC512?
Thank you.
add minutes and hours into a memory
Re: add minutes and hours into a memory
A quick start would be to check out the RTC example and Eeprom examples that mE provides. Post some code and we can help with that. Is this for a class project?
Re: add minutes and hours into a memory
Thanks for reply.
The project is for monitoring the hours and minutes an engine was on (for a diesel generator).
This is the whole code:
I know this is far from what I want, but I started like this.
With this code as it is now I can read the time and date and write them into the memory, but when I read them back I get 0 (zero) for tens of hours and for tens of minutes.
I think this is the way to go:
when starting the engine read the time and keep it into a variable -a-
when engine is stopped, read again the time and put it into another variable -b-
then b-a = c (time that engine was on this time)
then d = c + d (global time engine was on)
As you see from the code, if analog reading is >13V it will add the time into the memory (when engine is on, the alternator produces more than 13.4V. so this is the way I am monitoring if the engine is on or off)
Any suggestions?
Thank you.
The project is for monitoring the hours and minutes an engine was on (for a diesel generator).
This is the whole code:
Code: Select all
//Declarations------------------------------------------------------------------
char usecs, seconds, minutes, hours, day, month, year; // Global date/time variables
//--------------------------------------------------------------end-declarations
// Glcd module connections
char GLCD_DataPort at PORTD;
sbit GLCD_CS1 at LATB7_bit; // for writing to output pin always use latch (PIC18 family)
sbit GLCD_CS2 at LATB6_bit;
sbit GLCD_RS at LATB2_bit;
sbit GLCD_RW at LATB3_bit;
sbit GLCD_EN at LATB4_bit;
sbit GLCD_RST at LATB5_bit; // for writing to output pin always use latch (PIC18 family)
sbit GLCD_CS1_Direction at TRISB7_bit;
sbit GLCD_CS2_Direction at TRISB6_bit;
sbit GLCD_RS_Direction at TRISB2_bit;
sbit GLCD_RW_Direction at TRISB3_bit;
sbit GLCD_EN_Direction at TRISB4_bit;
sbit GLCD_RST_Direction at TRISB5_bit;
// End Glcd module connections
const char *Msg_0 = "Welcome" ; // Message 0 for GLCD
const char *Msg_1 = "Olivia" ; // Message 1 for LCD
const char *Msg_2 = "Time:" ; // Message 2 for LCD
const char *Msg_3 = "Date:" ; // Message 3 for LCD
const char *Msg_4 = "Total time engine on:" ; // Message 4 for LCD
const char *Msg_5 = "Bat:" ; // Message 9 for LCD Battery level
char texts[20] ; // copy constants from ROM to RAM
unsigned char ch, ch_0, ch_1; // ADC
unsigned int adc_rd; //
long tlong; //
char aaa, aab, aac,aad,aae,aaf,aag,aah,aai, aga, agb, agc, agd ;
///////////////////////////////////////////////////////////////////////////////////////////////////
void strConstCpy(char *dest, const char *source) { // --- Copying strings from ROM to RAM //
while(*source) //
*dest++ = *source++ ; //
//
*dest = 0 ; //
}//////////////////////////////////////////////////////////////////////////////////////////////////
void Beep() {
PortA.F5 = 1 ;
Delay_ms(100) ;
PortA.F5 = 0 ;
}
void Read_Time() { // Reads time and date information from RTC (PCF8583)
I2C1_Start(); // Issue start signal
I2C1_Wr(0xA0); // Address PCF8583, see PCF8583 datasheet
I2C1_Wr(1); // Start from address 1 ; was 2
I2C1_Repeated_Start(); // Issue repeated start signal
I2C1_Wr(0xA1); // Address PCF8583 for reading R/W=1
usecs = I2C1_Rd(1); // Read useconds byte
seconds = I2C1_Rd(1); // Read seconds byte
minutes = I2C1_Rd(1); // Read minutes byte
hours = I2C1_Rd(1); // Read hours byte
day = I2C1_Rd(1); // Read year/day byte
month = I2C1_Rd(0); // Read weekday/month byte
I2C1_Stop(); // Issue stop signal
}
void Transform_Time() { //-------------------- Formats date and time
usecs = ((usecs & 0xF0) >> 4)*10 + (usecs & 0x0F); // Transform useconds
seconds = ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F); // Transform seconds
minutes = ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F); // Transform months
hours = ((hours & 0xF0) >> 4)*10 + (hours & 0x0F); // Transform hours
year = (day & 0xC0) >> 6; // Transform year
day = ((day & 0x30) >> 4)*10 + (day & 0x0F); // Transform day
month = ((month & 0x10) >> 4)*10 + (month & 0x0F); // Transform month
aga = (hours / 10) ;
agb = (hours % 10) ;
agc = (minutes / 10) ;
agd = (minutes % 10) ;
}
void Display_Time() { //-------------------- Output values to LCD
Glcd_Set_Font(font5x7, 5, 7, 32); // Change font
Glcd_Write_Char((hours / 10) + 48, 33, 2, 1);
Glcd_Write_Char((hours % 10) + 48, 39, 2, 1);
Glcd_Write_Char((minutes / 10) + 48, 50, 2, 1);
Glcd_Write_Char((minutes % 10) + 48, 56, 2, 1);
Glcd_Write_Char((seconds / 10) + 48, 67, 2, 1);
Glcd_Write_Char((seconds % 10) + 48, 73, 2, 1);
Glcd_Write_Char((usecs / 10) + 48, 84, 2, 1);
Glcd_Write_Char((usecs % 10) + 48, 90, 2, 1);
Glcd_Write_Char((day / 10) + 48, 33, 4, 1); // Print tens digit of day variable
Glcd_Write_Char((day % 10) + 48, 39, 4, 1); // Print oness digit of day variable
Glcd_Write_Char((month / 10) + 48, 51, 4, 1);
Glcd_Write_Char((month % 10) + 48, 57, 4, 1);
year += 10; // Print year vaiable + 10 (start from year 2010)
Glcd_Write_Char((year/ 10) + 48, 81, 4, 1);
Glcd_Write_Char((year% 10) + 48, 87, 4, 1);
}
void Set_Time() {
I2C1_Init(100000); // Initialize full master mode
I2C1_Start(); // Issue start signal
I2C1_Wr(0xA0); // Address PCF8583, see PCF8583 datasheet
I2C1_Wr(0); // Start from address 0 (configuration memory location)
I2C1_Wr(0x80); // Write 0x80 to configuration memory location (pause counter...)
I2C1_Wr(0); // Write 0 to cents memory location
I2C1_Wr(0x45); // Write 0 to seconds memory location
I2C1_Wr(0x15); // Write 0x30 to minutes memory location
I2C1_Wr(0x15); // Write 0x12 to hours memory location
I2C1_Wr(0x02); // Write 0x24 to year/date memory location
I2C1_Wr(0x06); // Write 0x08 to weekday/month memory location
I2C1_Stop(); // Issue stop signal
I2C1_Start(); // Issue start signal
I2C1_Wr(0xA0); // Address PCF8530
I2C1_Wr(0); // Start from address 0
I2C1_Wr(0); // Write 0 to configuration memory location (enable counting)
I2C1_Stop(); // Issue stop signal
Delay_ms(2000);
}
void Show_Display_1() {
Beep() ;
Glcd_Fill(0x00) ; // Clear GLCD
Glcd_Set_Font(font5x7, 5, 7, 32); // Change font
strConstCpy(texts,Msg_2) ;
Glcd_Write_Text(texts, 0, 2, 1) ; //Time:
strConstCpy(texts,Msg_3) ;
Glcd_Write_Text(texts, 0, 4, 1) ; //Date:
strConstCpy(texts,Msg_4) ;
Glcd_Write_Text(texts, 0, 6, 1) ; //Total time engine on:
strConstCpy(texts,Msg_5) ;
Glcd_Write_Text(texts, 0, 0, 1) ; //Bat:
Glcd_Write_Char(':', 45, 2, 1);
Glcd_Write_Char(':', 62, 2, 1);
Glcd_Write_Char(':', 79, 2, 1);
Glcd_Write_Char('/', 45, 4, 1);
Glcd_Write_Text("/20", 63, 4, 1);
}
void Welcome() {
Beep() ;
Glcd_Fill(0x00) ; // Clear GLCD
Glcd_Set_Font(Character8x7, 8, 7, 32);// Change font
strConstCpy(texts,Msg_0) ;
Glcd_Write_Text(texts, 32, 2, 1) ;
strConstCpy(texts,Msg_1) ;
Glcd_Write_Text(texts, 36, 4, 1) ;
Delay_ms(2500) ;
Glcd_Fill(0x00) ; // Clear GLCD
Show_Display_1() ;
}
void Read_ADC() { //-----------Read ADC PortA.0-----------------------
ADCON0.ADON = 1 ; //Turn ON the AD module
adc_rd = ADC_read(0); // get ADC value from 2nd channel
tlong = (long)adc_rd * 5000; // covert adc reading to milivolts
tlong = tlong / 1023; // 0..1023 -> 0-5000mV
ch_0 = tlong / 1000; // extract volts digit
Glcd_Write_Char(48+ch_0, 27, 0, 1); // write ASCII digit at 2nd row, 5th column
ch_1 = (tlong / 100) % 10; // extract 0.1 volts digit
Glcd_Write_Char(48+ch_1, 33, 0, 1); // write ASCII digit at cursor point
Glcd_Write_Char('.', 39, 0, 1);
ch = (tlong / 10) % 10; // extract 0.01 volts digit
Glcd_Write_Char(48+ch, 43, 0, 1); // write ASCII digit at cursor point
ch = tlong % 10; // extract 0.001 volts digit
Glcd_Write_Char(48+ch, 49, 0, 1); // write ASCII digit at cursor point
Glcd_Write_Char('V', 55, 0, 1);
if(ch_0 >= 1) {
if(ch_1 > 3) {
I2C1_Start(); // issue I2C start signal
I2C1_Wr(0b10100010); // send byte via I2C (device address + W)
I2C1_Wr(0x00); // send byte (address of EEPROM location)
I2C1_Wr(0x0B);
// I2C1_Wr(hours) ;
// I2C1_Wr(minutes) ;
I2C1_Wr(48) ;
I2C1_Wr(48) ;
I2C1_Wr(48) ;
I2C1_Wr(48) ;
I2C1_Wr(aga) ;
I2C1_Wr(agb) ;
I2C1_Wr(agc) ;
I2C1_Wr(agd) ;
I2C1_Stop(); // issue I2C stop signal
Delay_ms(100);
// I2C1_Repeated_Start(); // issue I2C signal repeated start
I2C1_Start(); // issue I2C start signal
I2C1_Wr(0b10100010); // send byte via I2C (device address + Write)
// I2C1_Wr(2); // send byte (data address)
I2C1_Wr(0x00); // send byte (address of EEPROM location)
I2C1_Wr(0x0B);
I2C1_Repeated_Start(); // issue I2C signal repeated start
I2C1_Wr(0b10100011); // send byte (device address + Read)
aaa = I2C1_Rd(1); // Read the data (yes acknowledge)
aab = I2C1_Rd(1); // Read the data (yes acknowledge)
aac = I2C1_Rd(1); // Read the data (yes acknowledge)
aad = I2C1_Rd(1); // Read the data (yes acknowledge)
aae = I2C1_Rd(1); // Read the data (yes acknowledge)
aaf = I2C1_Rd(1); // Read the data (yes acknowledge)
aag = I2C1_Rd(1); // Read the data (yes acknowledge)
aah = I2C1_Rd(0); // Read the data (no acknowledge)
I2C1_Stop(); // issue I2C stop signal
Glcd_Write_Char(aaa ,32,7,1);
Glcd_Write_Char(aab ,38,7,1);
Glcd_Write_Char(aac ,44,7,1);
Glcd_Write_Char(aad ,50,7,1);
Glcd_Write_Char((aae / 10) + 48,56,7,1);
Glcd_Write_Char((aaf % 10) + 48,62,7,1);
Glcd_Write_Char(58,67,7,1);
Glcd_Write_Char((aag / 10) + 48,72,7,1);
Glcd_Write_Char((aah % 10) + 48,78,7,1);
}
}
ADCON0.ADON = 0 ; //Turn OFF the AD module
Delay_ms(1);
}
void main() {
PORTA = 0 ; //all pins are low
TRISA = 0b00011111 ; //pin0 is input for AD, pin4 input
LATA = 0 ;
PORTB = 0b00000000 ; //pin1 is high for RTC init, rest of pins are low
TRISB = 0; //all pins are output
LATB = 0 ;
PORTC = 0b10111000 ; //pins3&4 are high for I2C, rest of pins are low
TRISC = 0b10100000 ; //pin5&7 are input
LATC = 0 ;
PORTD = 0b00000000 ; //all pins are low
TRISD = 0b00011111 ; //all pins are output
LATD = 0 ;
PORTE = 0 ; //all pins are low
TRISE = 0b111 ; //all pins are input
LATE = 0 ;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ADCON0 = 0b00000010 ; // controls the operation of the A/D module //
ADCON1 = 0b00011100 ; // configures the functions of the port pins; AN0 only //
ADCON2 = 0b10010100 ; // configures the A/D clock source, acquisition time and justification
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CMCON |= 7; //0b00000111 // Disable comparators
Glcd_Init(); // Initialize GLCD
Glcd_Fill(0x00); // Clear GLCD
I2C1_Init(100000); // Initialize Soft I2C communication
Delay_ms(400);
Welcome() ;
Show_Display_1() ;
while(1) { // Endless loop
Read_Time(); // Read time from RTC(PCF8583)
Transform_Time(); // Format date and time
Display_Time(); // Prepare and display on LCD
// Delay_ms(1000); // Wait 1 second
Read_ADC() ; // Read AN0
}
}
With this code as it is now I can read the time and date and write them into the memory, but when I read them back I get 0 (zero) for tens of hours and for tens of minutes.
I think this is the way to go:
when starting the engine read the time and keep it into a variable -a-
when engine is stopped, read again the time and put it into another variable -b-
then b-a = c (time that engine was on this time)
then d = c + d (global time engine was on)
As you see from the code, if analog reading is >13V it will add the time into the memory (when engine is on, the alternator produces more than 13.4V. so this is the way I am monitoring if the engine is on or off)
Any suggestions?
Thank you.
-
- Posts: 619
- Joined: 05 Jul 2008 06:05
- Location: Thailand
Re: add minutes and hours into a memory
Yes, don't use an RTCC for this application! You're going to run into all sorts of bother with the maths especially if the generator is running across midnight on New Years Eve.Any suggestions?
Maxim make chips exactly for this purpose, such as the DS1682 (http://datasheets.maxim-ic.com/en/ds/DS1682.pdf), which can record up to 34 years of usage on its own EEPROM - it's all done internally and automatically so you won't have to worry about any of the code for the accumulator. And it also has it's own temperature stabilised oscillator which means it will be much more accurate than an external 32kHz xtal.
Re: add minutes and hours into a memory
Thanks Sobrietytest
I didn't know about such chips.
I'll use it.
Thanks again.
I didn't know about such chips.
I'll use it.
Thanks again.
Re: add minutes and hours into a memory
Hi,
I've got the chip (DS1682+) in the circuit up and running.
Only...
it seems to increment every 26 countings
and it does not increment at a second interval.
The datasheet is too cryptic for me to understand.
Can anybody help?
this is the code:
So, as soon as the event pin goes high, I can see the numbers going up
(aaa % 10) goes from 0 (zero) to 9, then again 0-9, then 0-5, then (aae / 10) is incremented and aaa goes again to 0-9, 0-9, 0-5
(aae / 10) goes from 0 (zero) to I (capital i)
????
what am I doing wrong?
Regards
I've got the chip (DS1682+) in the circuit up and running.
Only...
it seems to increment every 26 countings
and it does not increment at a second interval.
The datasheet is too cryptic for me to understand.
Can anybody help?
this is the code:
Code: Select all
void Read_Rec() { // read recordings
I2C1_Start(); // issue I2C start signal
I2C1_Wr(0b11010110); // send DS1682 device address + Write
I2C1_Wr(0x05); // address of Elapsed Time Counter ETC location
I2C1_Repeated_Start(); // issue I2C signal repeated start
I2C1_Wr(0b11010111); // send DS1682 device address + Read
aaa = I2C1_Rd(1); // Read the data (yes acknowledge)
aab = I2C1_Rd(1); // Read the data (yes acknowledge)
aac = I2C1_Rd(1); // Read the data (yes acknowledge)
aad = I2C1_Rd(1); // Read the data (yes acknowledge)
aae = I2C1_Rd(0); // Read the data (no acknowledge)
I2C1_Stop(); // issue I2C stop signal
aaa = ((aaa & 0xF0) >> 4)*10 + (aaa & 0x0F);
aab = ((aab & 0xF0) >> 4)*10 + (aab & 0x0F);
aac = ((aac & 0xF0) >> 4)*10 + (aac & 0x0F);
aad = ((aad & 0xF0) >> 4)*10 + (aad & 0x0F);
aae = ((aae & 0xF0) >> 4)*10 + (aae & 0x0F);
Glcd_Write_Char((aad / 10) + 48, 12,7,1);
Glcd_Write_Char((aad % 10) + 48, 18,7,1);
Glcd_Write_Char((aac / 10) + 48, 24,7,1);
Glcd_Write_Char((aac % 10) + 48, 30,7,1);
Glcd_Write_Char((aab / 10) + 48, 36,7,1);
Glcd_Write_Char((aab % 10) + 48, 42,7,1);
Glcd_Write_Char((aaa / 10) + 48, 49,7,1);
Glcd_Write_Char((aaa % 10) + 48, 55,7,1);
Glcd_Write_Char((aae / 10) + 48, 102,7,1); // event counter
Glcd_Write_Char((aae % 10) + 48, 108,7,1); // event counter
}
(aaa % 10) goes from 0 (zero) to 9, then again 0-9, then 0-5, then (aae / 10) is incremented and aaa goes again to 0-9, 0-9, 0-5
(aae / 10) goes from 0 (zero) to I (capital i)
????
what am I doing wrong?
Regards
- ranko.rankovic
- Posts: 433
- Joined: 11 Jun 2010 09:22
Re: add minutes and hours into a memory
Hello Olivia,
Please consider our examples for RTC and EEPROM that come within our software bundle. They can be found in folder where compiler is installed (\Examples\Extra Boards\). They may lead you to solution.
Best regards
Please consider our examples for RTC and EEPROM that come within our software bundle. They can be found in folder where compiler is installed (\Examples\Extra Boards\). They may lead you to solution.
Best regards
Ranko Rankovic
mikroElektronika [Support Department]
mikroElektronika [Support Department]
Re: add minutes and hours into a memory
Thanks for trying ranko
This is exactly what I have done.
I copied your example for RTC, and just changed the seconds, minutes, hours to my aaa,aab,aac....and of course the chip address
The problem is that in your example the RTC chip increments every second (that's why the code works);
But in my application the DS1682 chip increments in quarter of a second (and that's why my code does not work).
What should I add/modify so it will work correctly?
Regards.
This is exactly what I have done.
I copied your example for RTC, and just changed the seconds, minutes, hours to my aaa,aab,aac....and of course the chip address
The problem is that in your example the RTC chip increments every second (that's why the code works);
But in my application the DS1682 chip increments in quarter of a second (and that's why my code does not work).
What should I add/modify so it will work correctly?
Regards.
Re: add minutes and hours into a memory
Sorry, maybe I did not explain corectly what I want and what the problem is:
So I want to record the total time an engine was runing for.
Not just the last run, but the total run over the years.
So let's say it is running for 2 hours daily for 20 years that would give a total of 14600 hours.
You see, a diesel generator doesn't do any miles, like a car, so you wouldn't know when it's been 6000 miles so you change the oil and the filters.
Recording the time will tell you when it needs a new oil and filters.
Now the problem is that this chip (DS1682) increments every quarter of a second.
So, I got the reading from the chip, I divide it by 4 and still it looses about 6 or 7 secons every minute.
It supposed to be more accurate than an external 32k crystal.
And probably is.
I just need to see how to do it.
The previous aproach was wrong, as this chip does not give the output in BCD format as an RTC chip.
So I found that doing:
gives a better result.
Now I can see the readings going up from 0 to 255, then next bit aab is incremented, and aaa starts again from 0
And if I do:
I can see it going up from 0 to 59, like real seconds in a RTC chip.
But it is not acurate. It looses about 7 seconds every minute. Even if I don't divide it by 4.2667 it looses the same seconds.
Is there a way to close a thread?
Because I opened another one about the same problem, and I would like to close this one, carry on on the other.
Regards.
So I want to record the total time an engine was runing for.
Not just the last run, but the total run over the years.
So let's say it is running for 2 hours daily for 20 years that would give a total of 14600 hours.
You see, a diesel generator doesn't do any miles, like a car, so you wouldn't know when it's been 6000 miles so you change the oil and the filters.
Recording the time will tell you when it needs a new oil and filters.
Now the problem is that this chip (DS1682) increments every quarter of a second.
So, I got the reading from the chip, I divide it by 4 and still it looses about 6 or 7 secons every minute.
It supposed to be more accurate than an external 32k crystal.
And probably is.
I just need to see how to do it.
The previous aproach was wrong, as this chip does not give the output in BCD format as an RTC chip.
So I found that doing:
Code: Select all
aaa = I2C1_Rd(1); // Read the data (yes acknowledge)
ByteToStr(aaa, txt) ;
Glcd_Write_Text(txt, 49,7,1);
Now I can see the readings going up from 0 to 255, then next bit aab is incremented, and aaa starts again from 0
And if I do:
Code: Select all
aaa /=4.2667 ;
ByteToStr(aaa, txt) ;
Glcd_Write_Text(txt, 49,7,1);
But it is not acurate. It looses about 7 seconds every minute. Even if I don't divide it by 4.2667 it looses the same seconds.
Is there a way to close a thread?
Because I opened another one about the same problem, and I would like to close this one, carry on on the other.
Regards.