SimpleIDE Code Examples For The DS1302 Module (New Sample Posted 04/05/2020)

Hello Everyone
My initial intent was to create a library for the DS1302, but after coming to the conclusion that is not what I wanted or needed, I simply created two projects, one for writing to the DS1302 and one for reading from the DS1302. I additionally came to the conclusion that the DS1302 has too much time drift for my requirements. However, since I had the DS1302 on hand and since I needed additional logical code for my project, I figured I would work on these two sections and post it when I thought it was a little worthy.
@Ken - I did not create a library for you, but I am fairly certain that the attached code samples will be of great use to many of your customers, and your minions should be able to create a decent library, using the examples provided here.
These code examples were built using a PropBOE Without drawing this out with a lengthy discussion, the main thing that needs to be done, is altering the Propeller I/O pin constants at the top of each C file.
I am going to post the code and also attach zipped project files.
EDIT: Please note that the following variables can be removed from the top of the main() function of the Read_The_DS1302.c file.
My initial intent was to create a library for the DS1302, but after coming to the conclusion that is not what I wanted or needed, I simply created two projects, one for writing to the DS1302 and one for reading from the DS1302. I additionally came to the conclusion that the DS1302 has too much time drift for my requirements. However, since I had the DS1302 on hand and since I needed additional logical code for my project, I figured I would work on these two sections and post it when I thought it was a little worthy.
@Ken - I did not create a library for you, but I am fairly certain that the attached code samples will be of great use to many of your customers, and your minions should be able to create a decent library, using the examples provided here.
These code examples were built using a PropBOE Without drawing this out with a lengthy discussion, the main thing that needs to be done, is altering the Propeller I/O pin constants at the top of each C file.
I am going to post the code and also attach zipped project files.
// Set_The_DS1302.c
#include "simpletools.h"
//////////////////////////////////////////////////////////////////
// OVERVIEW
// This code is intended to set your DS1302 time and date according
// the time it is complied and run on your PC, and should be run
// seperately from your other firmware. Please note that DS1302
// has time drift issues.
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #1
// Before running this code, set your PC time clock to the highest
// accuracy that you can possibly achieve.
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #2 - One time setting
// Define the I/0 pin going from your Propeller chip to the DS1302
// CE pin.
#define DS1302_CE 0
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #3 - One time setting
// Define the I/0 pin going from your Propeller chip to the DS1302
// SCLK pin.
#define DS1302_SCLK 1
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #4 - One time setting
// Define the I/0 pin going from your Propeller chip to the DS1302
// I/O pin.
#define DS1302_IO 2
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #5 - Adjust as necessary
// Adjust for the difference between compile time and runtime.
// This is the number of seconds between the compilation time and
// the amount of time that it takes to write the date and time to
// the DS1302 registers.
#define OFFSET_SECONDS 4
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #6 - Run with terminal
// If your DS1302 is inaccurate compared to your PC's time clock,
// then repeat Step #5 and Step #6 until the DS1302 time and your
// PC's time clock are synchronized.
//////////////////////////////////////////////////////////////////
int second;
int minute;
int hour;
int weekday;
int month;
int date;
int year;
int second_bcd;
int minute_bcd;
int hour_bcd;
int weekday_bcd;
int month_bcd;
int date_bcd;
int year_bcd;
// Reset and enable the DS1302
void Reset()
{
low(DS1302_SCLK);
low(DS1302_CE);
high(DS1302_CE);
}
// Convert integer to binary coded decimal
int DecimalToBCD(int Decimal)
{
return (((Decimal / 10) << 4) | (Decimal % 10));
}
// Get the weekday... 0 = Sunday, 1 = Monday, etc.
int GetTheWeekday()
{
int Weekday;
int Month;
int Date;
int Year;
Month = month;
Date = date;
Year = year;
Weekday = ((Date += (Month < 3 ? Year-- :(Year - 2))),
(23 * Month / 9 + Date + 4 + Year / 4 - Year / 100 + Year / 400)) % 7;
return Weekday;
}
// Write all clock and calender registers in burst mode
void Set_DS1302_Time()
{
Reset();
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, 0xBE);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, second_bcd);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, minute_bcd);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, hour_bcd);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, date_bcd);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, month_bcd);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, weekday_bcd);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, year_bcd);
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, 0);
Reset();
}
// Read all clock and calender registers in burst mode
void Get_DS1302_Time()
{
Reset();
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, (int)0xBF);
second = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
minute = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
hour = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
date = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
month = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
weekday = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
year = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
Reset();
}
int main()
{
const char *pCharacterPointer;
char chMonth[4];
char chDate[3];
char chYear[5];
char chWeekday[2];
char chHour[3];
char chMinute[3];
char chSecond[3];
int previous_second;
if(strstr(__DATE__, "Jan") != NULL)
{
month = 1;
}
else if(strstr(__DATE__, "Feb") != NULL)
{
month = 2;
}
else if(strstr(__DATE__, "Mar") != NULL)
{
month = 3;
}
else if(strstr(__DATE__, "Apr") != NULL)
{
month = 4;
}
else if(strstr(__DATE__, "May") != NULL)
{
month = 5;
}
else if(strstr(__DATE__, "Jun") != NULL)
{
month = 6;
}
else if(strstr(__DATE__, "Jul") != NULL)
{
month = 7;
}
else if(strstr(__DATE__, "Aug") != NULL)
{
month = 8;
}
else if(strstr(__DATE__, "Sep") != NULL)
{
month = 9;
}
else if(strstr(__DATE__, "Oct") != NULL)
{
month = 10;
}
else if(strstr(__DATE__, "Nov") != NULL)
{
month = 11;
}
else if(strstr(__DATE__, "Dec") != NULL)
{
month = 12;
}
pCharacterPointer = strstr(__DATE__, " ");
if(pCharacterPointer != NULL)
{
pCharacterPointer += 2;
strncpy(chDate, pCharacterPointer, 1);
chDate[1] = '\0';
pCharacterPointer += 2;
}
else
{
pCharacterPointer = strstr(__DATE__, " ");
if(pCharacterPointer != NULL)
{
pCharacterPointer += 1;
strncpy(chDate, pCharacterPointer, 2);
chDate[2] = '\0';
pCharacterPointer += 3;
}
}
sprint(chMonth, "%d", month);
strncpy(chYear, pCharacterPointer, 4);
chYear[4] = '\0';
strncpy(chHour, __TIME__, 2);
chHour[2] = '\0';
pCharacterPointer = strstr(__TIME__, ":");
pCharacterPointer += 1;
strncpy(chMinute, pCharacterPointer, 2);
chMinute[2] = '\0';
pCharacterPointer += 3;
strncpy(chSecond, pCharacterPointer, 2);
chSecond[2] = '\0';
month = atoi(chMonth);
date = atoi(chDate);
year = atoi(chYear);
hour = atoi(chHour);
minute = atoi(chMinute);
second = atoi(chSecond);
weekday = GetTheWeekday();
sprint(chWeekday, "%d", weekday);
second = second + OFFSET_SECONDS;
year = year - 2000;
weekday = weekday + 1;
print("Compile Date: ");
print("%s/", chMonth);
print("%s/", chDate);
print("%s\n", chYear);
print("Compile Time: ");
print("%s:", chHour);
print("%s:", chMinute);
print("%s\n\n", chSecond);
second_bcd = DecimalToBCD(second);
minute_bcd = DecimalToBCD(minute);
hour_bcd = DecimalToBCD(hour);
weekday_bcd = DecimalToBCD(weekday);
month_bcd = DecimalToBCD(month);
date_bcd = DecimalToBCD(date);
year_bcd = DecimalToBCD(year);
Set_DS1302_Time();
previous_second = 0;
while(1)
{
Get_DS1302_Time();
if(second != previous_second)
{
print("DS1302 Time: ");
if(weekday == 1)
{
print("Sunday");
}
else if(weekday == 2)
{
print("Monday");
}
else if(weekday == 3)
{
print("Tuesday");
}
else if(weekday == 4)
{
print("Wednesday");
}
else if(weekday == 5)
{
print("Thursday");
}
else if(weekday == 6)
{
print("Friday");
}
else if(weekday == 7)
{
print("Saturday");
}
print(" ");
putHexLen(month,2);
print("/");
putHexLen(date,2);
print("/");
putHexLen(year,2);
print(" ");
putHexLen(hour,2);
print(":");
putHexLen(minute,2);
print(":");
putHexLen(second,2);
print("\n");
}
previous_second = second;
}
}
// Read_The_DS1302.c
#include "simpletools.h"
#include <time.h>
//////////////////////////////////////////////////////////////////
// OVERVIEW
// This code is intended to read the time and date of your DS1302.
// Please note that DS1302 has time drift issues.
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #1 - One time setting
// Define the I/0 pin going from your Propeller chip to the DS1302
// CE pin.
#define DS1302_CE 0
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #2 - One time setting
// Define the I/0 pin going from your Propeller chip to the DS1302
// SCLK pin.
#define DS1302_SCLK 1
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Step #3 - One time setting
// Define the I/0 pin going from your Propeller chip to the DS1302
// I/O pin.
#define DS1302_IO 2
//////////////////////////////////////////////////////////////////
int second;
int minute;
int hour;
int weekday;
int month;
int date;
int year;
int second_bcd;
int minute_bcd;
int hour_bcd;
int weekday_bcd;
int month_bcd;
int date_bcd;
int year_bcd;
// Reset and enable the DS1302
void Reset()
{
low(DS1302_SCLK);
low(DS1302_CE);
high(DS1302_CE);
}
int BCDToDecimal(int BCD)
{
return (((BCD >> 4) * 10) + (BCD & 0xF));
}
// Get the weekday... 0 = Sunday, 1 = Monday, etc.
int GetTheWeekday()
{
int Weekday;
int Month;
int Date;
int Year;
Month = month;
Date = date;
Year = year;
Weekday = ((Date += (Month < 3 ? Year-- :(Year - 2))),
(23 * Month / 9 + Date + 4 + Year / 4 - Year / 100 + Year / 400)) % 7;
return Weekday;
}
// Read all clock and calender registers in burst mode
void Get_DS1302_Time()
{
Reset();
shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, (int)0xBF);
second = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
minute = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
hour = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
date = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
month = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
weekday = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
year = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8);
Reset();
}
int main()
{
const char *pCharacterPointer;
char chMonth[4];
char chDate[3];
char chYear[5];
char chWeekday[2];
char chHour[3];
char chMinute[3];
char chSecond[3];
int previous_second;
previous_second = 0;
while(1)
{
Get_DS1302_Time();
if(second != previous_second)
{
print("DS1302 Time: ");
if(weekday == 1)
{
print("Sunday");
}
else if(weekday == 2)
{
print("Monday");
}
else if(weekday == 3)
{
print("Tuesday");
}
else if(weekday == 4)
{
print("Wednesday");
}
else if(weekday == 5)
{
print("Thursday");
}
else if(weekday == 6)
{
print("Friday");
}
else if(weekday == 7)
{
print("Saturday");
}
print(" ");
putHexLen(month, 2);
print("/");
putHexLen(date, 2);
print("/");
putHexLen(year, 2);
print(" ");
putHexLen(hour, 2);
print(":");
putHexLen(minute, 2);
print(":");
putHexLen(second, 2);
print(" ");
print("\n");
int converted_second = BCDToDecimal(second);
int converted_minute = BCDToDecimal(minute);
int converted_hour = BCDToDecimal(hour);
int converted_date = BCDToDecimal(date);
int converted_month = BCDToDecimal(month) - 1;
int converted_year = BCDToDecimal(year) + 2000 - 1900;
struct tm current = { converted_second, converted_minute, converted_hour,
converted_date, converted_month, converted_year };
time_t current_time = mktime(¤t);
printf("Unix time for current time: %ld\n", current_time);
struct tm previous = { 0, 0, 20, 29, 2, 120 };
time_t previous_time = mktime(&previous);
printf("Unix time for 20:00:00 03/29/2020: %ld\n", previous_time);
printf("Seconds of difference: %.f\n", difftime(current_time, previous_time));
// Create file or folder name
///////////////////////////////////////////////////////////
char file_folder_name[80];
strftime(file_folder_name, sizeof(file_folder_name),
"%Y%m%dT%H%M%S", ¤t);
print("File or folder name: %s", file_folder_name);
///////////////////////////////////////////////////////////
print("\n\n");
}
previous_second = second;
}
}
EDIT: Please note that the following variables can be removed from the top of the main() function of the Read_The_DS1302.c file.
const char *pCharacterPointer;
char chMonth[4];
char chDate[3];
char chYear[5];
char chWeekday[2];
char chHour[3];
char chMinute[3];
char chSecond[3];
Comments
EDIT: I will be providing one more example, which I will be working on today and perhaps tomorrow. This upcoming example will be made by altering the Read_The_DS1302.c file. In this upcoming example, I will be creating a folder and file on an SD card, named from values obtained from the DS1302 module, and then I will be writing UNIX timestamps to the file, with some other information attached. I don't really know how long it will take me, but I guess it shouldn't take that long.
/////////////////////////////////////////////////////////// // Create folder name // For my purposes, one folder per month is sufficient,so // the folders will be named according to the current year // and month. /////////////////////////////////////////////////////////// char folder_name[80]; strftime(folder_name, sizeof(folder_name), "%Y%m", ¤t); print("Folder name: %s\n", folder_name); /////////////////////////////////////////////////////////// // Create file name // For my purposes, files will be created and written to // according to a beginning trigger event and an ending // trigger event. The beginning trigger event will create // and open the file for witing, and the ending trigger // event will close the file. This file will be stored in // a folder named according to the current year and month, // in which the file was created. While the file is open // for writing, I will be writing UNIX timestamps to the file // based on other trigger events. For the purpose of this // example, I will be using two pushbuttons to signal // trigger events. The first button press of the first // button will create a folder, based on year and month, if // it does not already exist. Afterwards it will create and // and open a file, within the previously mentioned folder, // for writing. With each button press of the second button, // a UNIX timestamp will be added to the open file. A second // button press of the first button will indicate that the // logging procedure has been completed, and the file will be // closed, with no further writing to this specific file. // Additionally, it is worth noting that this file will be // created and named according to the current date and time // of the DS1302. /////////////////////////////////////////////////////////// char file_name[80]; strftime(file_name, sizeof(file_name), "%Y%m%dT%H%M%S", ¤t); print("File name: %s\n", file_name); ///////////////////////////////////////////////////////////
I was almost finished coding the last sample, when I stumbled across this roadblock
I will need a minute or two to think about rearranging the intended naming of the file system.
I think the folders named after the year and month is okay.
I think the previously mentioned folder will now have subfolders created according to the day of the month (1~31).
I further think that I will now name the files located in these subfolders with the format of "HHMMSS.TXT".
I also think that plan will work. Undoubtedly it will be a bit more painful to reach a desired file, but I have to get around the 8.3 format one way or another
In other words, let's say a file is created March 31, 2020 at 20:43:36. The file path would be:
Once again, this makes it a bit more complicated to get at the log files, but I believe in the long run, it is a bit more organized.
200331/204336.TXT
so
YYMMDD/hhmmss.TXT
just saying, good for 100 80 years.
EDIT
sorry I am dumb today, with 8 chars you can do
YYYYMMDD for the Directory.
/EDIT
Mike
Flat structures are bad for humans, say you should not have more then 7 menu entries/buttons/whatever because the usual human can remember 7 things and click out of memory, with more then seven he has to READ all of it again.
Think of the development of menus and sub menus. Keep the number short.
On the other hand for computers flat structures are way more easy.
And for log files this is anyways something you will later on parse with some program for extraction of the problematic ones.
Enjoy!
Mike
Where was this suggestion before I started rewriting the relevant code
This is my latest and last example. To run this example, you will need a DS1302 RTC module, a board that has an SD card holder, an SD card, and two pushbuttons wired up to your board, to set off trigger events. For my testing, I used a PropBOE, activity board or something similar can also be used.
This sample creates timestamps in files on the SD card, according to trigger events.
Anyhow, once again, I don't feel much like talking about it, but I would suggest running the "Set_The_DS1302" example prior to running this one, to help ensure you get good timestamps.
Here is the code, but I am also attaching a zipped project file below:
// DS1302_Timestamps.c #include "simpletools.h" #include <time.h> #include <stdbool.h> ////////////////////////////////////////////////////////////////// // OVERVIEW // This code is intended to read the time and date of your DS1302 // and write timestamps to a file based upon pushbutton trigger // events. Please note that DS1302 has time drift issues. ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #1 - One time setting // Define the I/0 pin going from your Propeller chip to the DS1302 // CE pin. #define DS1302_CE 0 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #2 - One time setting // Define the I/0 pin going from your Propeller chip to the DS1302 // SCLK pin. #define DS1302_SCLK 1 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #3 - One time setting // Define the I/0 pin going from your Propeller chip to the DS1302 // I/O pin. #define DS1302_IO 2 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #4 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD DO (Data Out) #define SD_DO 22 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #5 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD CLK (Clock) #define SD_CLK 23 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #6 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD DI (Data In) #define SD_DI 24 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #7 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD CS (Chip Select) #define SD_CS 25 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #8 - One time setting // Define the I/0 pin going from your Propeller chip to a pushbutton, // which will trigger the creation of a folder if it does not exist // and it will create a file for data logging (timestamps). #define PB_FOLDER_FILE 13 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #9 - One time setting // Define the I/0 pin going from your Propeller chip to a pushbutton, // which will trigger the writing of a timestamp to an open file. #define PB_TIMESTAMP 4 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #10 - Run with the terminal and push some buttons :) ////////////////////////////////////////////////////////////////// int second; int minute; int hour; int weekday; int month; int date; int year; int second_bcd; int minute_bcd; int hour_bcd; int weekday_bcd; int month_bcd; int date_bcd; int year_bcd; int converted_second; int converted_minute; int converted_hour; int converted_date; int converted_month; int converted_year; struct tm current; time_t current_time; // Reset and enable the DS1302 void Reset() { low(DS1302_SCLK); low(DS1302_CE); high(DS1302_CE); } int BCDToDecimal(int BCD) { return (((BCD >> 4) * 10) + (BCD & 0xF)); } // Read all clock and calender registers in burst mode void Get_DS1302_Time() { Reset(); shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, (int)0xBF); second = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); minute = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); hour = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); date = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); month = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); weekday = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); year = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); Reset(); converted_second = BCDToDecimal(second); converted_minute = BCDToDecimal(minute); converted_hour = BCDToDecimal(hour); converted_date = BCDToDecimal(date); converted_month = BCDToDecimal(month) - 1; converted_year = BCDToDecimal(year) + 2000 - 1900; current.tm_sec = converted_second; current.tm_min = converted_minute; current.tm_hour = converted_hour; current.tm_mday = converted_date; current.tm_mon = converted_month; current.tm_year = converted_year; current_time = mktime(¤t); } int main() { char folder_name[9]; char file_name[11]; char file_path[20]; char timestamp[15]; bool bLogging; FILE* file_pointer; bLogging = false; sd_mount(SD_DO, SD_CLK, SD_DI, SD_CS); print("Press your buttons to create folders, files, and timestamps\n\n"); while(1) { if(bLogging == false) { if(input(PB_FOLDER_FILE) == 1) { Get_DS1302_Time(); strftime(folder_name, sizeof(folder_name), "%Y%m%d", ¤t); strftime(file_name, sizeof(file_name), "%H%M%S", ¤t); // Add the desired extension to complete the file name strcat(file_name, ".txt"); if(mkdir(folder_name, 0) == 0) { print("Folder Created: %s\n", folder_name); } else { print("Folder Must Already Exist: %s\n", folder_name); } // Creating the file path strcpy(file_path, folder_name); strcat(file_path, "\\"); strcat(file_path, file_name); print("File Path: %s\n", file_path); sprint(timestamp, "%d", current_time); strcat(timestamp, "\r\n"); file_pointer = fopen(file_path, "w"); if(file_pointer != NULL) { print("File Opened: %s\n", file_name); fwrite(timestamp, sizeof(char), strlen(timestamp), file_pointer); printf("Timestamp Written: %d\n", current_time); memset(timestamp, 0, sizeof(timestamp)); } bLogging = true; pause(200); } } else { if(input(PB_FOLDER_FILE) == 1) { fclose(file_pointer); bLogging = false; print("File Closed: %s\n\n", file_name); memset(folder_name, 0, sizeof(folder_name)); memset(file_name, 0, sizeof(file_name)); memset(file_path, 0, sizeof(file_path)); pause(200); } else if(input(PB_TIMESTAMP) == 1) { Get_DS1302_Time(); sprint(timestamp, "%d", current_time); strcat(timestamp, "\r\n"); fwrite(timestamp, sizeof(char), strlen(timestamp), file_pointer); printf("Timestamp Written: %d\n", current_time); memset(timestamp, 0, sizeof(timestamp)); pause(200); } } } }
This can be used for keeping some information while a prop reboots. I used it at some project to transfer a 'commandline' to the next starting P1 program.
And, yes the module has quite a drifting, but it is not that bad, who cares about some seconds per month.
I actually liked your idea to set time/date on loading the program, on a P1 it may not be as usable as on a P2, but with a 64 bit cnt on the P2 you are good for decades.
Anyways, me being a COBOL programmer I naturally hate C programmers - no offence here - but your source code does read nicely compared to most C programs.
Enjoy!
Mike
I must have recieved a lemon, because mine actually gains about 30 seconds per hour
Yea, I stumbled across _DATE_ and _TIME_ accidentally. and I thought wow, I can use these to set the date and time on the RTC with an offset. Then I discovered that someone had already done it with a different RTC module. Of course, I wanted to be the first to come up with idea, but that wasn't the case
I will take that as a compliment
After reviewing some firmware for the ChronoDot V2.1, I see they provide an option for writing an ISO 8601 timestamp (E.G.: 2000-01-01T12:34:56).
Is anyone interested in me updating my last example to include this option?
Sure, it would be good to have an ISO 8601 timestamp example as well...
// DS1302_Timestamps.c #include "simpletools.h" #include <time.h> #include <stdbool.h> ////////////////////////////////////////////////////////////////// // OVERVIEW // This code is intended to read the time and date of your DS1302 // and write timestamps to a file based upon pushbutton trigger // events. Please note that DS1302 has time drift issues. ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #1 - One time setting // Define the I/0 pin going from your Propeller chip to the DS1302 // CE pin. #define DS1302_CE 0 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #2 - One time setting // Define the I/0 pin going from your Propeller chip to the DS1302 // SCLK pin. #define DS1302_SCLK 1 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #3 - One time setting // Define the I/0 pin going from your Propeller chip to the DS1302 // I/O pin. #define DS1302_IO 2 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #4 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD DO (Data Out) #define SD_DO 22 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #5 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD CLK (Clock) #define SD_CLK 23 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #6 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD DI (Data In) #define SD_DI 24 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #7 - One time setting // Define the I/0 pin going from your Propeller chip to the // SD CS (Chip Select) #define SD_CS 25 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #8 - One time setting // Define the I/0 pin going from your Propeller chip to a pushbutton, // which will trigger the creation of a folder if it does not exist // and it will create a file for data logging (timestamps). This // pushbutton trigger also closes the file. #define PB_FOLDER_FILE 13 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #9 - One time setting // Define the I/0 pin going from your Propeller chip to a pushbutton, // which will trigger the writing of a timestamp to an open file. #define PB_TIMESTAMP 4 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #10 - One time setting // Define the type of timestamp to be written to the log file by // "commenting" and "uncommenting" the "#define(s)" below. You can // only use one or the other, unless you modify the source code. //#define WRITE_UNIX_TIMESTAMP // E.G.: 1585922355 #define WRITE_ISO8601_TIMESTAMP // E.G.: 2000-01-01T12:34:56 ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Step #11 - Run with the terminal and push some buttons :) // Please note: All "print" and "printf" instructions may be // removed from the following source code, if you do not require // the use of a terminal. ////////////////////////////////////////////////////////////////// int second; int minute; int hour; int weekday; int month; int date; int year; int second_bcd; int minute_bcd; int hour_bcd; int weekday_bcd; int month_bcd; int date_bcd; int year_bcd; int converted_second; int converted_minute; int converted_hour; int converted_date; int converted_month; int converted_year; struct tm current; time_t current_time; FILE* file_pointer; // Reset and enable the DS1302 void Reset() { low(DS1302_SCLK); low(DS1302_CE); high(DS1302_CE); } int BCDToDecimal(int BCD) { return (((BCD >> 4) * 10) + (BCD & 0xF)); } // Read all clock and calender registers in burst mode void Get_DS1302_Time() { Reset(); shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, (int)0xBF); second = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); minute = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); hour = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); date = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); month = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); weekday = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); year = shift_in(DS1302_IO, DS1302_SCLK, LSBPRE, 8); Reset(); converted_second = BCDToDecimal(second); converted_minute = BCDToDecimal(minute); converted_hour = BCDToDecimal(hour); converted_date = BCDToDecimal(date); converted_month = BCDToDecimal(month) - 1; converted_year = BCDToDecimal(year) + 2000 - 1900; current.tm_sec = converted_second; current.tm_min = converted_minute; current.tm_hour = converted_hour; current.tm_mday = converted_date; current.tm_mon = converted_month; current.tm_year = converted_year; current_time = mktime(¤t); } // This function will write a timestamp to an opened log file. // The type of timestamp written will depend upon the timetamp // constant defined at the begiining of this source code. // E.G.: #define WRITE_UNIX_TIMESTAMP or WRITE_ISO8601_TIMESTAMP. // If you need a prefix, suffix, or both, to be added to the // timestamp, this would be the function to modify. The entry // written to the opened file, within this function, can easily // be modified by using the string functions defined in "string.h". // For further information about these string functions, please // refer to: http://www.cplusplus.com/reference/cstring/ void WriteFileData() { //////////////////////////////////////////////////////////////////////// #ifdef WRITE_UNIX_TIMESTAMP char timestamp[15]; // May need modification dependant upon requirements sprint(timestamp, "%d", current_time); printf("Timestamp Written: %d\n", current_time); // Any additional modifications should begin after this point strcat(timestamp, "\r\n"); fwrite(timestamp, sizeof(char), strlen(timestamp), file_pointer); //////////////////////////////////////////////////////////////////////// #elif defined WRITE_ISO8601_TIMESTAMP char timestamp[24]; // May need modification dependant upon requirements strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", ¤t); print("Timestamp Written: %s", timestamp); print("\n"); // Any additional modifications should begin after this point strcat(timestamp, "\r\n"); fwrite(timestamp, sizeof(char), strlen(timestamp), file_pointer); //////////////////////////////////////////////////////////////////////// #endif } int main() { char folder_name[9]; char file_name[11]; char file_path[20]; bool bLogging; bLogging = false; sd_mount(SD_DO, SD_CLK, SD_DI, SD_CS); print("Press your buttons to create folders, files, and timestamps\n\n"); while(1) { if(bLogging == false) { if(input(PB_FOLDER_FILE) == 1) { Get_DS1302_Time(); strftime(folder_name, sizeof(folder_name), "%Y%m%d", ¤t); strftime(file_name, sizeof(file_name), "%H%M%S", ¤t); // Add the desired file extension to complete the file name strcat(file_name, ".txt"); if(mkdir(folder_name, 0) == 0) { print("Folder Created: %s\n", folder_name); } else { print("Folder Must Already Exist: %s\n", folder_name); } // Creating the file path strcpy(file_path, folder_name); strcat(file_path, "\\"); strcat(file_path, file_name); print("File Path: %s\n", file_path); file_pointer = fopen(file_path, "w"); if(file_pointer != NULL) { print("File Opened: %s\n", file_name); WriteFileData(); } bLogging = true; pause(200); } } else { if(input(PB_FOLDER_FILE) == 1) { fclose(file_pointer); bLogging = false; print("File Closed: %s\n\n", file_name); memset(folder_name, 0, sizeof(folder_name)); memset(file_name, 0, sizeof(file_name)); memset(file_path, 0, sizeof(file_path)); pause(200); } else if(input(PB_TIMESTAMP) == 1) { Get_DS1302_Time(); WriteFileData(); pause(200); } } } }
Thank you, I'll check it out when I have a chance.
Thank you idbruce! I found this thread very helpful while using the DS1302 on my Propeller Pro Dev Board. For completeness, I wanted to add two things that I discovered while working on my project.
1) If you want to stop the clock, in the file Set_The_DS1302.c, find the line
<=shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, second_bcd);
modify the line to read
<=shift_out(DS1302_IO, DS1302_SCLK, LSBFIRST, 8, second_bcd + 128);
to set the CH (Clock Halt) bit. I'm not sure why you would want to set the time AND stop the clock, but that's your business. This is only included for your inspiration.
2) If you are using the PPDB (p/n 32111 RevB), I found that on my board, the battery connection terminals aren't connected to the DS1302 regardless of the J13 jumper positions. I only had a battery backed up clock when I ran a wire from J13 VEXT to the BAT connection on header X22. If your clock isn't keeping time with the battery power, check the DS1302, pin 8 for voltage.
Happy coding!