RTC for Propeller
Discovery
Posts: 606
Is there a "C" code Real Time Clock file available for running on one COG of the 8 COG Propeller chip?
Would it be more accurate than a DS1307?
Sincerely,
Discovery
Would it be more accurate than a DS1307?
Sincerely,
Discovery
Comments
Ray
The clock is running and I established an accuracy test.
Sincerely,
Discovery
How would you use the Code to detect 13 hours, 20 minutes, and 16 seconds?
Sincerely,
Discovery
Ray
My "C" programming skills are not very good.
It is too bad that Jazzed cannot take a whak at solving the problem...chances are he would know precisely what to do.
Sincerely,
Discovery
Of course it would be tied to the accuracy of the crystal on both platforms. 10PPM is normal for both if you are using off the shelf crystal for the DS or the Propeller. There are more precise crystals available :
http://www.mouser.com/Passive-Components/Frequency-Control-Timing-Devices/Oscillators/TCXO-Oscillators/_/N-7jdmj
Ray
HA! Thanks, Dave. That takes care of that. I stumbled into this thread checking out something else entirely, now I've got the answer to a question I didn't even have to ask!
void Get_Time()
{
char timebuff[16];
time_t now = 0;
now = time(&now);
strftime(timebuff,16,"%T",localtime(&now));
print("%s\n",timebuff);
}
I figured that timebuff would be the char string that would do the trick since it is used as the printed variable.
Using
static volatile char s;
in my definations I figured that putting
s = timebuff;
command into the Get_Time() function would make it available in the main COG. But when I print it in the main COG...it is empty.
What's wrong?
Discovery
If you want to use s to hold the address of timebuf you need to declare it as a char pointer, and not just char. If just declared as a char, s will only hold the least significant byte of the address of timebuf. So s should be declared as "char *s". Note that timebuff must still be declared as static or declare outside of the Get_Time routine to move it off of the stack.
When you build the code you should look at the warnings that are generated. Declaring s as a char and then storing the address of timebuff to s should have generated a warning message from the compiler.
Sincerely,
Discovery
The project was going to use an AB, sht11 module, XBee module, and be powered by some batteries( or power pack). After adding the code necessary for accessing the SD card, sht11 module, XBee module, and the softRTC, using CMM, I only had something like 2K of memory left to work with, as I recall. That does not include code for starting and stopping events which would be running in their own cogs. Plus expanding the project to include some CO2 sensors, amongst other things was out of the question.
So, you just may want to be sure if you are using the correct equipment and tools before you get too far into a project. Lessons learned the hard way.
Ray
My application is really simple. All I want is a RTC that I can access in a loop that will compare the hour, minutes, and seconds from the RTC to a short list of start times. When there is a match, a pump turns on for a certain number of minutes.
Dave,
I made changes you suggested, character pointer and inside the function declaration and outside. The problem persists...can not gain access to timebuff that should have the result of Get_ Time.
Would it be simpler to use someone's existing propeller code that interfaces to a DS1307?
Discovery
Ray
Discovery
/*
PPC Factory Main Program ***2015/5/10 ***
*/
#include "simpletools.h"
#include "propeller.h"
#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "adcDCpropab.h"
#include <sys/rtc.h>
#define BUFFERLEN 10
void Help();
void Set_Clock();
int getdst();
int prompttime(char *prompt);
void Get_Time();
void Get_Date();
void Valves();
void StartOps();
void SetValve();
int i;
int j;
int hour;
int Selection;
int AirValve;
int Air;
int Amount;
int Water=8150;
int Acid=500;
int A=500;
int B=500;
int Base=500;
int Valve;
static volatile char *s;
int main()
{
uint8_t buffer[40];
_rtc_start_timekeeping_cog();
print("This is SoftRTC\n");
print("help - for menu\n");
while(1)
{
print("> ");
gets(buffer);
if(!strcmp(buffer, "run")) break;
else if(!strcmp(buffer, "help")) Help();
else if(!strcmp(buffer, "setclock")) Set_Clock();
else if(!strcmp(buffer, "time")) Get_Time();
else if(!strcmp(buffer, "date")) Get_Date();
else
{
print("Invalid Command!\n");
}
}
// while(1) ///Main Program Loop
// {
if(1 == 1)
{
print("Hello.\n");
Get_Time();
print("Time is %c\n",s); //****Will not display timebuff from Get_Time()***
Selection = 0;
Valve = 1;
Valves();
}
// }
}
//Subroutines//
void Help()
{
print("Commands are: setclock, time, date, run.\n");
}
void Set_Clock()
{
struct timeval tv;
struct tm t;
t.tm_isdst = getdst();
t.tm_year = prompttime("Year")-1900;
t.tm_mon = prompttime("Month")-1;
t.tm_mday = prompttime("Day of the month");
t.tm_hour = prompttime("Hour");
t.tm_min = prompttime("Minute");
t.tm_sec = prompttime("Second");
tv.tv_sec = mktime(&t);
settimeofday(&tv, 0);
}
int getdst()
{
int rc = 0;
print("Use daylight savings time [y/n] ? ");
fflush(stdout);
rc = (getchar() == 'y') ? 1 : 0;
getchar();
return rc;
}
int prompttime(char *prompt)
{
int rc = 0;
char *endp;
char buffer[BUFFERLEN];
do
{
print("Enter %: ",prompt);
fflush(stdout);
fgets(buffer, BUFFERLEN,stdin);
fflush(stdin);
rc = strtol(buffer, &endp, 10);
if(endp == buffer)
{
if('\n' == *endp)
{
rc = 0;
break;
}
print("Invalid entry \"%c....\" Please enter a number.\n", *endp);
}
}
while(endp == buffer);
return rc;
}
void Get_Time()
{
char timebuff[16];
time_t now = 0;
now = time(&now);
strftime(timebuff,16,"%T",localtime(&now));
print("%s\n",timebuff);
s = timebuff;
}
void Get_Date()
{
char timebuff[16];
time_t now = 0;
now = time(&now);
strftime(timebuff,16,"%b %d, %Y",localtime(&now));
print("%s\n",timebuff);
}
void ZeroBus()
{
low(0); //Bus 0
low(1); //Bus 1
low(2); //Bus 2
low(3); //Bus 3
low(4); //Bus 4
low(5); //Bus 5
low(6); //Bus 6
low(7); //Bus 7
}
void DispenseRoutine()
{
if(Selection == 0)
{
AirValve = Air*Amount;
}
if(Selection == 1)
{
high(8); //Vent valve open
pause (20000);
high(9); //Acid Valve open
for(j=1; j<Amount+1; j++)
{
pause (Acid);
}
low(9); //Acid valve closed
pause (1000);
high(10); //Water valve open
for(j=1; j<Amount; j++)
{
pause (Water);
}
low(10); //Water valve closed
pause (1000);
AirValve = Air*Amount;
}
if(Selection == 2)
{
high(8); //Vent valve open
pause (20000);
high(9); //Acid valve open
for(j=1; j<Amount+1; j++)
{
pause (Acid);
}
low(9); //Acid valve closed
pause (1000);
high(11); //Nutrient A valve open
for(j=1; j<Amount+1; j++)
{
pause (A);
}
low(11); //Nutrient A valve closed
high(12); //Nutrient B valve open
for(j=1; j<Amount+1; j++)
{
pause (B);
}
low(12); //Nutrient B valve closed
pause (1000);
high(10); //Water valve open
for(j=1; j<Amount+1; j++)
{
pause (Water);
}
low(10); //Water valve closed
low(8); //Vent valve closed
pause (1000);
AirValve = Air*Amount;
}
}
void VentTank()
{
high(8); //Vent open
pause (1000);
low(8); //Vent closed
pause (100);
}
void Valves()
{
for(i=1; i<255; i++)
{
if(Valve == i) //Valve 1
{
Amount = 1;
A = 2500;
B = 2500;
Acid = 500;
Base = 0;
StartOps();
}
if(Valve == i) //Valve 2
{
Amount = 2;
A = 2500;
B = 2500;
Acid = 500;
Base = 0;
StartOps();
}
}
}
void StartOps()
{
pause (2000);
DispenseRoutine();
SetValve();
}
void SetValve()
{
for(i=1; i<10; i++)
{
if(i == 1)
{
high(0); //Bus 0
high(26);
pause (2000);
low(0);
low(26);
}
pause (2000);
if(i == 2)
{
high(1); //Bus 1
high(27);
pause (2000);
low(1);
low(27);
}
pause (2000);
if(i == 3)
{
high(0);
high(26);
high(1);
high(27);
pause (2000);
low(0);
low(26);
low(1);
low(27);
}
}
}
static volatile *timebuff ?
The original author uses timebuff in both the Get_Time and Get_Date functions...should they be different as in timebuffA and timeBuffB?
Should the stack size be increased?
Sincerely,
Discovery
I can now use the time of day in my main program.
The changes are:
static volatile char *timebuff[16];
static volatile char *s;
char timebuff[16]; was removed from the Get_Time function
In the main program
A call to Get_Time followed by
s = timebuff;
print("Time is %s\n",s);
Works fine.
Thank you Dave.
Sincerely,
Discovery
Ray
In the code below in the second would be WHILE loop, I am trying to compare the TIME character string from the SoftRTC to the T1 character string and it will not match.
Ray and Dave...why not?
Discovery
/*
PPC Factory Main Program ***2015/5/10 ***
*/
#include "simpletools.h"
#include "propeller.h"
#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "adcDCpropab.h"
#include <sys/rtc.h>
#define BUFFERLEN 10
void Help();
void Set_Clock();
int getdst();
int prompttime(char *prompt);
void Get_Time();
void Get_Date();
void Valves();
void StartOps();
void SetValve();
int i;
int j;
int hour;
int Selection;
int AirValve;
int Air;
int Amount;
int Water=8150;
int Acid=500;
int A=500;
int B=500;
int Base=500;
int Valve;
char U[] = "09:12:00";
char V[] = "09:12:00";
static volatile char *s;
static volatile char *timebuff[16];
static volatile char *T1;
int main()
{
uint8_t buffer[40];
_rtc_start_timekeeping_cog();
print("This is SoftRTC\n");
print("help - for menu\n");
while(1)
{
print("> ");
gets(buffer);
if(!strcmp(buffer, "run")) break;
else if(!strcmp(buffer, "help")) Help();
else if(!strcmp(buffer, "setclock")) Set_Clock();
else if(!strcmp(buffer, "time")) Get_Time();
else if(!strcmp(buffer, "date")) Get_Date();
else
{
print("Invalid Command!\n");
}
}
// while(1) ///Main Program Loop
// {
if(1 == 1)
{
Get_Time();
print("Time is %s\n",timebuff);//Works
T1 = "09:54:00";
s = timebuff;
print("Time is %s\n",s);//Works
if(!strcmp(T1,s)) //Fails comparison
{
print("Match\n");
high(26);
high(27);
}
else
{
print("No Match\n");
low(26);
low(27);
}
Selection = 0;
Valve = 1;
Valves();
}
// }
}
//Subroutines//
void Help()
{
print("Commands are: setclock, time, date, run.\n");
}
void Set_Clock()
{
struct timeval tv;
struct tm t;
t.tm_isdst = getdst();
t.tm_year = prompttime("Year")-1900;
t.tm_mon = prompttime("Month")-1;
t.tm_mday = prompttime("Day of the month");
t.tm_hour = prompttime("Hour");
t.tm_min = prompttime("Minute");
t.tm_sec = prompttime("Second");
tv.tv_sec = mktime(&t);
settimeofday(&tv, 0);
}
int getdst()
{
int rc = 0;
print("Use daylight savings time [y/n] ? ");
fflush(stdout);
rc = (getchar() == 'y') ? 1 : 0;
getchar();
return rc;
}
int prompttime(char *prompt)
{
int rc = 0;
char *endp;
char buffer[BUFFERLEN];
do
{
print("Enter %: ",prompt);
fflush(stdout);
fgets(buffer, BUFFERLEN,stdin);
fflush(stdin);
rc = strtol(buffer, &endp, 10);
if(endp == buffer)
{
if('\n' == *endp)
{
rc = 0;
break;
}
print("Invalid entry \"%c....\" Please enter a number.\n", *endp);
}
}
while(endp == buffer);
return rc;
}
void Get_Time()
{
time_t now = 0;
now = time(&now);
strftime(timebuff,16,"%T",localtime(&now));
print("%s\n",timebuff);
}
void Get_Date()
{
char timebuff[16];
time_t now = 0;
now = time(&now);
strftime(timebuff,16,"%b %d, %Y",localtime(&now));
print("%s\n",timebuff);
}
void ZeroBus()
{
low(0); //Bus 0
low(1); //Bus 1
low(2); //Bus 2
low(3); //Bus 3
low(4); //Bus 4
low(5); //Bus 5
low(6); //Bus 6
low(7); //Bus 7
}
void DispenseRoutine()
{
if(Selection == 0)
{
AirValve = Air*Amount;
}
if(Selection == 1)
{
high(8); //Vent valve open
pause (20000);
high(9); //Acid Valve open
for(j=1; j<Amount+1; j++)
{
pause (Acid);
}
low(9); //Acid valve closed
pause (1000);
high(10); //Water valve open
for(j=1; j<Amount; j++)
{
pause (Water);
}
low(10); //Water valve closed
pause (1000);
AirValve = Air*Amount;
}
if(Selection == 2)
{
high(8); //Vent valve open
pause (20000);
high(9); //Acid valve open
for(j=1; j<Amount+1; j++)
{
pause (Acid);
}
low(9); //Acid valve closed
pause (1000);
high(11); //Nutrient A valve open
for(j=1; j<Amount+1; j++)
{
pause (A);
}
low(11); //Nutrient A valve closed
high(12); //Nutrient B valve open
for(j=1; j<Amount+1; j++)
{
pause (B);
}
low(12); //Nutrient B valve closed
pause (1000);
high(10); //Water valve open
for(j=1; j<Amount+1; j++)
{
pause (Water);
}
low(10); //Water valve closed
low(8); //Vent valve closed
pause (1000);
AirValve = Air*Amount;
}
}
void VentTank()
{
high(8); //Vent open
pause (1000);
low(8); //Vent closed
pause (100);
}
void Valves()
{
for(i=1; i<255; i++)
{
if(Valve == i) //Valve 1
{
Amount = 1;
A = 2500;
B = 2500;
Acid = 500;
Base = 0;
StartOps();
}
if(Valve == i) //Valve 2
{
Amount = 2;
A = 2500;
B = 2500;
Acid = 500;
Base = 0;
StartOps();
}
}
}
void StartOps()
{
pause (2000);
DispenseRoutine();
SetValve();
}
void SetValve()
{
for(i=1; i<10; i++)
{
if(i == 1)
{
high(0); //Bus 0
high(26);
pause (2000);
low(0);
low(26);
}
pause (2000);
if(i == 2)
{
high(1); //Bus 1
high(27);
pause (2000);
low(1);
low(27);
}
pause (2000);
if(i == 3)
{
high(0);
high(26);
high(1);
high(27);
pause (2000);
low(0);
low(26);
low(1);
low(27);
}
}
}
Also, when you post code please wrap it in [noparse] [/noparse] tags.
I inserted some code, this is the way I would go about trying narrow down the problem.
Ray
[ CODE ] [ /CODE ]
09:54:00
And the print out to the screen for T1 is:
09:54:00
They appear as identical on the print to screen but
if(!strcmp(T1,s))
fails the comparison.
Discovery
Discovery
1. Get_Time reads the RTC and dumps the value into timebuff.
2. Timebuff is then copied into the global static variable s.
3. A start time character string is generated as a line of code and placed into T1.
4. I print out T1 and s to compare the values on the screen.
5. The values look identical on the screen.
6. The two strings, T1 and s are compared with !strcmp and fail to match.
The output is:
> setclock
Use daylight savings time [y/n] ? y
Enter 2015
Enter 5
Enter 12
Enter 9
Enter 53
Enter 50
> time
09:53:52
> run
09:53:59
Time is 09:53:59
Time is 09:54:00
Time is 09:53:59
No Match
Oh...
I set the start time to 09:54:00 then set the clock time to 09:53:50...checked the time and pressed run. It appears that it would be just plane luck if the clock time was 09:54:00 when the comparison was made.
I must put the Get_Time and comparison lines in a WHILE loop to insure that !strcmp catches the RTC at 09:54:00.
Dave...would you agree?
Discovery