Hello!
I am trying to develop a Clock for Arduino using DuinOS. The idea is to use a task in order to manage the system time while others task are running.
To set the clock, it is used an UNIX format, for example: T1291036511. Where "T" is a special char to identify the UNIX time. We give the unix time to the system using the serial connection.
When I put the unix time in the serial port, the system goes very slow... and it freezes.
Here is my code (based on MoreComplexBlinking):
#include <Time.h>
#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER 'T' // Header tag for serial time sync message
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
#define INITIAL_GREEN_DELAY 200
#define NEW_GREEN_DELAY 20
int ledPinRed = 8;
int ledPinGreen = 9;
unsigned int greenDelay = INITIAL_GREEN_DELAY;
boolean redLED_isOn = false;
boolean greenLED_isOn = false;
//Forward declaration, to let redLED call to resumeTask(greenLED). It's not necessary if we put the greenLED
//itself here, but declareLoopTask may be usefull in more complex situations:
declareTaskLoop(greenLED);
declareTaskLoop(clock);
taskLoop(redLED)
{
static unsigned char counter = 0;
if (!greenLED_isOn)
{
if (counter >2)
resumeTask(greenLED);
counter++;
}
redLED_isOn = false;
delay(1000);
redLED_isOn = true;
delay(1000);
}
taskLoop(greenLED)
{
static unsigned char counter = 1;
digitalWrite(ledPinGreen, HIGH); // set the LED on
delay(greenDelay);
digitalWrite(ledPinGreen, LOW); // set the LED off
delay(greenDelay);
if ( (counter >= 9) && (greenDelay != NEW_GREEN_DELAY) )
greenDelay = NEW_GREEN_DELAY; //now, after 10 blinks, accelerates
if (counter >= 99)
{
//Reset vars, so next time, if the task is resumed, it executes all again:
counter = 0;
greenDelay = INITIAL_GREEN_DELAY;
greenLED_isOn = false;
suspend(); //After a while, the tasks suspends itself (forever)
}
counter++;
}
taskLoop(clock)
{
if(Serial.available() )
{
processSyncMessage();
}
if(timeStatus()!= timeNotSet)
{
digitalWrite(13,timeStatus() == timeSet); // on if synced, off if needs refresh
digitalClockDisplay();
}
delay(1000);
}
// The setup() method runs once, when the sketch starts
void setup()
{
// Initialize the digital pins as outputs:
pinMode(ledPinRed, OUTPUT);
pinMode(ledPinGreen, OUTPUT);
Serial.begin(9600);
setSyncProvider( requestSync); //set function to call when sync required
Serial.println("Waiting for sync message...");
createTaskLoop(clock, HIGH_PRIORITY);
createTaskLoop(redLED, NORMAL_PRIORITY);
createTaskLoop(greenLED, LOW_PRIORITY);
//This initializes the main loop's with a different priority (default is LOW_PRIORITY):
//initMainLoopPriority(NORMAL_PRIORITY);
//Try this and see what happends:
//suspendTask(redLED);
}
// This is the main loop() method, wich runs over and over again,
// as long as the Arduino has power. Is a LOW_PRIORITY taskLoop:
void loop()
{
if (redLED_isOn)
{
digitalWrite(ledPinRed, LOW); // set the LED off
delay(25); // The OS can be tested reducing these delays, and seeing how both LEDs work together...
digitalWrite(ledPinRed, HIGH); // set the LED on
delay(25);
}
else
{
digitalWrite(ledPinRed, LOW); // LED is off
//If nextTask is not called, the application will not hang, because the OS is preemptive. BUT, the current task
//will consume a lot of computational resources (due to it's lack of a delay() in this branch), the application will
//turn slower, and the other tasks may be affected by this, loossing precision in their timing:
nextTask();
}
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void processSyncMessage() {
// if time sync available from serial port, update time and return true
while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits
Serial.println("Serial.available");
char c = Serial.read() ;
Serial.print(c);
if( c == TIME_HEADER ) {
time_t pctime = 0;
for(int i=0; i < TIME_MSG_LEN -1; i++){
c = Serial.read();
if( c >= '0' && c <= '9'){
pctime = (10 * pctime) + (c - '0') ; // convert digits to a number
}
}
Serial.println(pctime);
setTime(pctime); // Sync Arduino clock to the time received on the serial port
}
}
}
time_t requestSync()
{
Serial.print(TIME_REQUEST,BYTE);
return 0; // the time will be sent later in response to serial mesg
}