Newbie question please help!

Hello everybody,

My name is Jim and I am new to the arduino environment as well as the forums. I've been using arduino UNO for the last two weeks (and not very often to be honest) for academic purposes since I need it for the Emerging technologies and Themes class in my university. 2 weeks ago my instructor gave us an assignment to work in groups. Unfortunatelly I am the only one from my group who cares about his grade so I am the only one worrying about doing it. He asked for an alarm clock (only the code on IDE not a real clock) with the following functions:

a) The user should be asked to put current time (hh:mm:ss) in order to set the clock running. b) The user should be asked to put alarm time (hh:mm:ss) in order to set alarm on. c) The user should be able to either stopping the alarm by pressing "P" or snooze it for 5 minutes by pressing "N"

The alarm should be displayed using a blinking LED.

After wondering around in the arduino playground I found the Time library that REALLY made my life a lot easier in setting the clock. But the problem is that I cannot make it the way my instructor wants. I use the " if Serial.available())" function in order to prohibit the clock start running on its own, and I use the Serial.read() function to give the time manually. The problem is that the code completely ignores the Serial.available function and it doesn't wait for me to send something as it should. Instead, the clock starts running from time 00:00:00. I can set the current time and the alarm time manually through the code directly, but this is not what I need. My main part of code is the example in the TimeAlarm library of arduino and I modify this code in order to match it for my needs. I also have the same problem with the snooze and stop functions since the IDE console ignores ANYTHING I try to send.

Please it is really essential if you can give me an idea on how to make the time to be set by the user and I would appreciate it if you could give me an idea on how to work with the snooze and stop functions.

Due respect, Jim

Let me ask you this. Is the purpose of the assignment to show that you have learned how to program an arduino to perform the application assigned to you? If so, then even using the library code you found may not be in the spirit of the assignment?

I would think that the assignment has a couple of objectives. 1. To be able to demonstrate that your project is done on time and functions to all the specifications assigned to it. 2. That you mastered the skills needed to build and code the assignment, which may include (I'm asking) the ablity to write the code from scratch.

Lefty

Let's start with part a. The Arduino only makes "uptime" available, as you've already figured out.

If we knew when the reset occurred, then we could add the uptime to the reset time to calculate the "now" time, right?

So, how can we determine the (world) reset time? Please don't hate me when I point out that when the user enters the current time, all that's needed is to subtract the uptime to have the reset time, which you'll want to save for reference.

After having done that, all that's necessary is to add the reset time to the current uptime to have the current world time. :)

Here's some code that I'm using:

typedef unsigned long long time_t; /* From a header file */
/*----------------------------------------------------------------------------*/
/* Define a translation unit scope variable to hold latest RESET time         */
/*----------------------------------------------------------------------------*/
static time_t rst_time = 0-0;          /* Epochal time of latest RESET        */
/*----------------------------------------------------------------------------*/
/* Extend micros() for 64-bit up-time                                      TU */
/*----------------------------------------------------------------------------*/
static time_t u64(void)
{  static union                        /* Definitions to allow accessing time */
   {  time_t hl;                       /* As a whole, or as...                */
      struct                           /* Anonymous struct container          */
      {  unsigned long l;              /* Lower half and...                   */
         unsigned long h;              /* Upper half                          */
      };                               /*  end: (anonymous) {}                */
   }  u = { 0 };                       /* Initialize to zero                  */
   static unsigned long t;             /* Variable to hold micros() value     */
   if (u.l > (t = micros())) ++u.h;    /* If micros() wrapped, adjust         */
   u.l = t;                            /* Save updated low half               */
   return u.hl;                        /* Return 64-bit usec time             */
}                                      /*  end: u64()                         */
/*----------------------------------------------------------------------------*/
/* Return current date/time as usec into the epoch                            */
/*----------------------------------------------------------------------------*/
time_t now(void)
{  return rst_time + u64();            /* Return reset time + uptime          */
}                                      /*  end: now()                         */
/*----------------------------------------------------------------------------*/
/* Set RESET date/time using externally-supplied current epochal date/time    */
/*----------------------------------------------------------------------------*/
void set_time(time_t t)
{  rst_time = t - u64();
}
/*----------------------------------------------------------------------------*/

Edited to correct comment

@ retrolefty: I don't think that using available libraries is anything like plagiarism. Otherwise they wouldn't be there. By this logic I shouldn't even use println function since it is not made by me from scratch. The instructor will see that I used the library since I declare it at the beggining of the code, but even so, I don't ask for ready piece of code just for an advice and probably a clarification on how I can make the IDE wait for me till I set the time manually.

@Morris Dovey: Ok I kinda understood this. I may be mistaken but by reading the code I don't see any way to "pause" the code before the loop until the user enters the current time though. My main problem is that no matter what I try, the Serial Monitor ignores anything I try to send and it just runs the code, resulting to the time being printed starting from 0:00:00.

Read it again as many times as necessary because you won’t be able to complete the assignment without wrapping your head around the concept.

Yes, millis() and micros() are always reset to zero and cannot be user-adjusted. As one would-be poet once said: “What can’t be cured must be endured.” Unless you wire in an RTC, you’ll need to get the current time from the user, and until he provides his/her notion of world time, you’re stuck with up time.

If you’re having difficulty communicating with the serial monitor, post what you’ve written that’s not working and perhaps we can help you past that hurdle…

So there is no way I can make the IDE post a message like “Give hours” and then take the input and use it in the setTime function as the hours variable?

skypse: So there is no way I can make the IDE post a message like "Give hours" and then take the input and use it in the setTime function as the hours variable?

Yes of course. And if done in the setup portion of the sketch you should be able to not have a problem with the power up default time value being displayed, correct?

An as far as my questions before, I would not consider it plagirism if the library code still retains it's author and usage licence information for your instructor to see. I just asked what is your instructor's expectation in that regard?

Correct. So why does the setup function ignore my if Serial.available command, and how can I get the input inside the setTime function?

I tried declaring 6 different variables for each element, (hour, min,sec etc) and then inside if Serial.available { } print messages like "enter current hour" and then assign the Serial.read to its respective variable.

But it just ignores me, and setTime gets 0:00:00 by default. This is what I want to fix.

EDIT: I don't know what his expectation is, but I guess it's ok to use libaries. After all noone uses pure scratch code. Libraries are there for a reason. And this reason is to be used. Anyway I don't think anyone knows the println() author or have usage licence information when they use it :) Open source library is open source :)

Open source library is open source

I agree and fully support the use of open source projects. I was just curious of what your instructor's intent was, and you said you didn't know. So I guess if he has an issue with it after the fact then shame on him for not making his expectations up front on such matters, as it doesn't sound like you are going to hide the fact that you are using and modifying an existing open source application library.

If you could post at least the complete setup function of your sketch, we can help tell you why the setup function might be 'falling through' to the main function without waiting for user input. It's just a case of using proper structure in the setup function.

Lefty

Of course I am not going to hide anything. I obviously need more practice and help on using the arduino and after all this is our first assignment so I don’t think he expect us to deliver it perfectly.

This is the code part that the serial monitor ignores:

int h, m, s, mo, d, y;
void setup()
{
  Serial.begin(9600);
  if(Serial.available())
 {
  Serial.println("Please enter the current hour");
  h=Serial.read();
  Serial.println("Please enter the current minutes");
  m=Serial.read();
  Serial.println("Please enter the current seconds");
  s=Serial.read();
  Serial.println("Please enter the current day");
  d=Serial.read();
  Serial.println("Please enter the current month");
  mo=Serial.read();
  Serial.println("Please enter the current year");
  y=Serial.read();
  setTime(h,m,s,d,mo,y);

I don’t know if it is correct. I am only trying to experiment. I saw the readme file in the Time library and as I figured, this is how the setTime function works as it needs 6 int values. I declare the int values globally so I can use them everywhere and then I ask the user through the serial port to give the values. I guess I should put something in the if Serial.available statement so it won’t get ignored but I can’t guess what since I am waiting for 6 different values. I know the problem is at that part of the code because I print various stuff before that and they get printed perfectly. I just can’t figure what I should put in that statement in order to make it wait for something.

I also tried different Serial.available for each respective value, and I tried a conditioned based Serial.available for hours like this:

if ((Serial.available() > 1) && (Serial.available() <24))

In case it needed something like that and accept the value only if it was between those two numbers but still it got ignored.

Seeing your code helps a lot. I’m going to respond with another piece of my own code - which doesn’t do what you want, but should provide some insights that will let you do what you want:

/*----------------------------------------------------------------------------*/
/* Get a single character from the host                                       */
/*----------------------------------------------------------------------------*/
static int getb(void)
{  while (!(Serial.available() > 0));  /* Wait for data to arrive             */
   return Serial.read();               /* Return next character               */
}                                      /*  end: getb()                        */
/*----------------------------------------------------------------------------*/
/* Get current date/time and set the system reset time                        */
/*----------------------------------------------------------------------------*/
void get_time(void)
{  time_t t;                           /* Current system time                 */
   int c;                              /* Input character                     */
   do                                  /* Until end of message                */
   {  Serial.println("?T");            /* Send time query to host via USB     */
      t = 0;                           /* Initialize time value               */
      while ('T' != getb()) ;          /* Watch for start of time response    */
      while (('0' <= (c = getb())) && (c <= '9')) /* Is this a decimal digit? */
      {  t = 10 * t + (c & 0x0F);      /* If so, build time value             */
      }                                /*  end: building time value           */
   }  while (c != '!');                /* Until a valid time is received      */
   set_time(ss(t));                    /* Calculate and save reset time       */
}                                      /*  end: get_time()                    */
/*----------------------------------------------------------------------------*/

(The time I’m getting from the serial monitor is the number of seconds since 00:00:00 Jan 1, 1970.)

Hmmm So I guess I could use this while to get the respective values right? I can store the values in a 6 space array of integers and then use that array to give setTime the variables it wants. What about using 6 different if instead of the while? Would it have the same effect? It would be more “pretty” to have 6 different messages printed in the serial monitor and I don’t think I can make an array of 6 strings to print them in the while loop using different variable each time. Plus I think this while works for only 1 input since it will go out of the loop as soon as Serial.available gets a value. Maybe a for loop for int i=<6 would work better?

The message format and read/decode strategy is your baby. Note, however that the simplistic little getb() function takes advantage of the fact that Serial.read() returns only a single character each time called…

Nothing... I modified the code, I adjusted it in my needs, I tried with a for loop, a while loop, multiple ifs, anything I could think of. Nothing works. The serial monitor just ignores the serial.available command and it starts counting from time 0:00:00

Try what I suggested - query Serial.available() for each and every character.

I did. At least I think I understand what you mean. I have a serial.available for each value, and it doesn't even wait for me to type the value. It just prints "Please enter the current hour" and starts counting from 0

In your code you commented that with the while loop the monitor should wait for input. It just doesn't do anything.

The sequence of operations you show is

Serial.begin(9600);
  if(Serial.available()) /* Ask if there's anything in the buffer ONCE */
 {
  Serial.println("Please enter the current hour"); /* Send a message */
  h=Serial.read(); /* get nothing from Serial.read() */
  Serial.println("Please enter the current minutes"); /* Send a message */
  m=Serial.read(); /* get nothing from Serial.read() */
  Serial.println("Please enter the current seconds"); /* Send a message */
  s=Serial.read(); /* get nothing from Serial.read() */
  Serial.println("Please enter the current day"); /* Send a message */
  d=Serial.read(); /* get nothing from Serial.read() */
  Serial.println("Please enter the current month"); /* Send a message */
  mo=Serial.read(); /* get nothing from Serial.read() */
  Serial.println("Please enter the current year"); /* Send a message */
  y=Serial.read(); /* get nothing from Serial.read() */
  setTime(h,m,s,d,mo,y);

You did [u]not[/u] query for each and every character - you simply assumed that each Serial.read() call would deliver what you wanted.