Author Topic: Displaying Time to LCD  (Read 3750 times)

0 Members and 1 Guest are viewing this topic.

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Displaying Time to LCD
« on: August 25, 2020, 04:20:25 am »
Dear All,

I am trying to implement a count down timer with a PIC16F628A. I am using <MikroC pro for PIC> for coding.
My code starts with following defines:

#define Lo(param) ((char *)&param)[0]
#define Hi(param) ((char *)&param)[1]
...
...

Also, I have declared variables in my code like:

short minutes, seconds, hours;
...

Also I read from EEPROM like -
... 
  Dealy_ms(30);
  Lo(minutes) = EEPROM_Read(0x12);
  Delay_ms(30);
  Hi(minutes) = EEPROM_Read(0x13);
  Delay_ms(30);
  Lo(seconds) = EEPROM_Read(0x14);
  Delay_ms(30);
  Lo(seconds) = EEPROM_Read(0x14);
...
Now I need to display two minutes digits and two seconds digits on the LCD in the following format:

MM:SS (eg., 30:20).

I tried like-
Lcd_Chr(1, 8, 'Hi(minutes)');
or even, Lcd_Chr(1, 9, 'minutes'+48);

But failed to display correct digits.

I suppose Lo(minutes) returns 8 bits data. But I do not know how to display that data as a number on LCD!

Need assistance.
Would you please tell me how to display the minutes and seconds on the LCD as shown above? Thanks. 
« Last Edit: August 25, 2020, 04:45:48 am by asadulhuq »
 

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3249
  • Country: us
Re: Displaying Time to LCD
« Reply #1 on: August 25, 2020, 05:31:14 am »
 
The following users thanked this post: asadulhuq

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 13091
Re: Displaying Time to LCD
« Reply #2 on: August 25, 2020, 06:27:12 am »
You cant break up a short into two bytes (char) and get a decimal result.  You have to process it as a whole.
For a  clock, you probably want the string padded with leading zeros, and although one could do that using sprintf() and a carefully chosen format specifier, the printf() family of functions are extremely large and complex, and will probably take up all your code space!  The phrase "Using a Sledgehammer to crack a nut" comes to mind.

As a lighter weight alternative, see K&R section 3.6 for one possible itoa() implementation (or [here].  You'ld have to tweak it a bit to implement leading zero padding.

Also see https://download.mikroe.com/documents/compilers/mikroc/pic/help/conversions_library.htm

N.B. Number to string functions are commonly called itoa() because they are the inverse of the standard library function atoi(), but there is no itoa() function in the ANSI C standard.

 
The following users thanked this post: asadulhuq

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #3 on: August 25, 2020, 08:41:39 am »
Do you need do go over 59 seconds or 59 minutes ? If not, than a simple uint8_t is enough to store the values and you don't need the "Lo" and "Hi".
Also, I see your code reads twice Lo(seconds). Is it normal ?

Then, a single "divide by 10" gives you the first digit:
Code: [Select]
   uint8_t d1,d2,c1,c2;
   uint8_t minutes;

   minutes = 59;       // just an exemple
   d1 = minutes / 10;  //  -> 5;
Modulo give you the second digit:
Code: [Select]
  d2 = minutes % 10 ;  //  -> 9
Then, to obtain the characters for the display, simply add '0'
Code: [Select]
  c1 = d1 + (uint8_t)'0';  // code for digit '5'
  c2 = d2 + (uint8_t)'0';  // code for digit '9'

Of course, when you do a division and then a modulo, you do more of less twice the same thing and that's time consuming. It's better to replace the modulo by a multiplication and a subtraction (multiplication is done by hardware and is fast):
Code: [Select]
  d2 = minutes - (d1 * 10);  // equivalent to d2 = minutes % 10



Correction: 16F628 has no hardware multiplier
« Last Edit: August 25, 2020, 08:51:30 am by ggchab »
 
The following users thanked this post: asadulhuq

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #4 on: August 25, 2020, 09:15:36 am »
ggchab (on: 25-Aug-2020 at 08:41:39 am),
Thanks a lot. Probably my problem will be solved using your procedure.
BTW, <Also, I see your code reads twice Lo(seconds). Is it normal ?>, that was a copy paste issue.
Thanks again.
 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #5 on: August 25, 2020, 12:16:09 pm »
ggchab<<
Your method works. I am implementing a count down timer. When I start the timer the display value always shows the remaining time. This is good and needed. However, I also want to display the set up time in the 1st line on the LCD. (In the 2nd line 'remaining time' while the timer is running, which is implemented now). Do you have any idea of how to display the setup time from the EEPROM (this time will not change untilI I write a new setup time in EEPROM)?  You may have a look on the complete timer code bellow. Thanks.
« Last Edit: August 25, 2020, 02:54:22 pm by asadulhuq »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #6 on: August 25, 2020, 02:58:13 pm »
I am not sure I understand what you want to do because there should be no difference between displaying the value of a counter or a fixed value ?

I don't know why, but I could not download your code.
 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #7 on: August 25, 2020, 03:28:09 pm »
ggchab<<
Now you can download. Please try again. I want that Lcd line 1 will show like "Preset on time: 30 minutes' once power is aplied or start button is pushed. However, the Line 2 will show 'Remaining Time' like 30.. 29...28....3..2..1..0.. minutes and the relay will be OFF. Preset time will not change untill it is adjusted.
« Last Edit: August 25, 2020, 03:47:24 pm by asadulhuq »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #8 on: August 25, 2020, 03:48:57 pm »
I still don't understand what is your problem  :-// Why not using the function
Code: [Select]
Lcd_Chr(1,1,"some text")to write what you want on the first line of the LCD ?
 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #9 on: August 25, 2020, 03:56:24 pm »
ggchab<<
I want to adjust that 'Preset time' with push button switches when required. I want to use this timer to control my water heater. In winter the preset time will be 50 minutes for example. In summer it will be 15 minutes. Also, day time preset will be lower than the night  time preset ON time. So, it will be convenient to display the current preset time.
« Last Edit: August 25, 2020, 04:05:10 pm by asadulhuq »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #10 on: August 25, 2020, 04:40:23 pm »
I see you have commented the "display_time();" after the LCD initialization. You may re-use this function to display the initial time on the first line if you simply add a parameter to the function:

Code: [Select]
// Displays minutes and seconds on line 'line' (1 or 2) at position 8
void display_time(unsigned short line) {
md1 = ...
...
Lcd_Out(line,8,"[");
...
}

Then, in your code, call the function and specify the line:

Code: [Select]
display_time(1);  // Displays minutes and seconds on line 1

I think there are some big errors in your code, especially when reading data from the eeprom: with the "Lo", "Hi", you assign 16 bit values to 8 bit variables (unsigned short). You are lucky this is working: when you initialize "seconds", you probably overwrite the content of minutes, ...

You don't need 16 bit values to store seconds, minutes, hours if they are limited to 59,59, less than 255.

So, use only one eeprom byte for each variable:
Code: [Select]
  hours = EEPROM_Read(0x10);      //Load from eeprom
  Delay_ms(30);
  minutes = EEPROM_Read(0x11);
  Delay_ms(30);
  seconds = EEPROM_Read(0x12);

Same thing when you write the eeprom:
Code: [Select]
     EEPROM_Write(0x12,seconds);
     Delay_ms(50);
     EEPROM_Write(0x11,minutes);
     Delay_ms(50);
     EEPROM_Write(0x10,hours);
     Delay_ms(50);


 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #11 on: August 25, 2020, 04:57:07 pm »
ggchab<<
Lot of thanks again. I will try to apply your recommendation on my code and surely I will let you know the result.

But what will happen to the top 2 lines of the code? Seems that these are MikroC inline routines. They may be found in MikroC  library.

#define Lo(param) ((char *)&param)[0]
#define Hi(param) ((char *)&param)[1]

 Don't I need to modify those 2 lines? I do not understand these 2 lines well. Could you please explain the meaning of the lines? Or is there a way to simplify these lines?

Actually, am new to the programming world. My hobby is Analog electronic circuit and system design.  In this Covid time I stay home. So, I started microcontroller programming to utilize this time. It is clear that you are expert in programming. Thank you for your nice and clear explanations.
« Last Edit: August 25, 2020, 05:20:20 pm by asadulhuq »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #12 on: August 25, 2020, 05:31:39 pm »
You don't need those 2 lines. They are used to initialize a 16 bit variable from two 8 bit values. They "transform" a 16 bit variable into an array of 2 char, each char then being initialized with a 8 bit value.

&param -> pointer to 'param' that is a 16 bit variable

(char*) tells the compiler the pointer is no longer a pointer to a 16 bit value but to a 8 bit value

This pointer can also be seen as an array (an array is a pointer to a list of "things")

So, ((char*)&param)[0] is the first element of the array and, in fact, the 8 least significant bit of 'param' and ((char*)&param)[1] is the second element of the array, the 8 most significant bit of 'param'.

But all this might dependent on how the compiler stores a 16 bit value in memory...
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #13 on: August 25, 2020, 05:37:15 pm »
Quote
Actually, am new to the programming world. My hobby is Analog electronic circuit and system design.  In this Covid time I stay home. So, I started microcontroller programming to utilize this time.

The more you will learn, the more you will have fun  ;D
 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #14 on: August 26, 2020, 02:17:03 am »
Thanks for the explanation of the top two lines. I shall omit those lines and let you know the result. Also, I shall modify my EEPROM reading and writing sub-routines. Today I have to conduct the weekly zoom online class for my undergraduate students. After completing the class I will come back to my programming session.
 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #15 on: August 26, 2020, 04:26:53 pm »
ggchab (Yesterday at 05:31:39 pm)<<

Thank you for all your recommendations. The timer is working correctly as required. I have attached the new <timer.c>.  A video of the Proteus simulation, 65MB .mp4 file is in the following link.

BTW, would you give me an idea how to up/down the ON time value using 2 push buttons when the timer is ON?

Please note the timer itself is a count down timer. The beginning time will be a preset time which is loaded from the EEPROM.

https://drive.google.com/drive/folders/1o7E6cmL4AFLufr_B3Mo1qqayQgNUmsks?usp=sharing

Thanks.
« Last Edit: August 26, 2020, 05:36:02 pm by asadulhuq »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #16 on: August 26, 2020, 07:35:11 pm »
Why not reuse the existing time edition procedure :
Always test the buttons, not only when (start == false). But you still have to test the 'start' flag to take some decisions:
 - if (start == false) save time in eeprom
 - if (start == true), stop the interrupts while updating the variables (to avoid any conflict with the interrupts function)

something like this (not tested - also, I don't know what variable  'a' is doing)

Code: [Select]
   if (!SEC_sw || !MIN_sw || !HRS_sw){
    Delay_ms(200);
    if (!SEC_sw || !MIN_sw || !HRS_sw){
     Delay_ms(50);
     
     if (start)
       INTCONbits.T0IE = 0;    // Stops TMR0 interrupts (I don't know if that's the correct syntax)
     
     a = 1;
     if (!SEC_sw) {            // SEC buton is PRESSED
      if (seconds < 59) seconds++;
      else seconds = 0;
     }
     if (!MIN_sw) {            // MIN buton is PRESSED
      if (minutes < 59) minutes++;
      else minutes = 0;
     }
     if (!HRS_sw) {            // HRS buton is PRESSED
      if (hours < 99) hours++;
      else hours = 0;
     }
     
     if (!start)               // Save new time if timer is not running
       Write_EEPROM();
     else
       INTCONbits.T0IE = 1;    // otherwise, re-enable TMR0 interrupts
    }
   }


Something else:

Each time you modify a time variable, you write the new time into the eeprom. This can make a lot of unnecessary writes ! I would add a delay (a few seconds) before writing the eeprom. This can be done with the help of your existing TMR0 interrupts function:
  - in your main loop: add a new counter (C) that you reset to 0 each time you update one of the time variables
  - add a flag (F1) that you reset to false each time you update one of the time variables
  - add a flag (F2) that you set to true each time you update one of the time variable and (start == false). So, you know time must be saved.
  - in the interrupts function, increment the counter C (about every ms). When it reaches a specific value (ex.: 5000 for about 5s), set the flag F1 to true
  - in your main loop, when both F1 and F2 are true, write the eeprom and then reset F2

When you modify the counter and F1, you should disable TMR0 interrupts to avoid any strange behavior if an interrupt occurs while variables are updated!

Just some ideas. They might have to be developed a bit more.


 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #17 on: August 27, 2020, 03:27:30 am »
ggchab<<
Thanks for your comments on the timer. You are correct about writing to EEPROM every time I push a time setting switch. I was thinking about that. The program surely  needs lot of fine tuning. I will try to accommodate your ideas regarding writing to EEPROM. However,  did you notice what my new modification plan?

My current flow chart of the device (in short):
DC Power ON to Timer -> Heater ON with the Preset time settings loaded from EEPROM -> Count down -> Stop Heater if Time reaches to 0.

I want to modify the flowchart to a new one as follows:
DC Power ON to Timer -> Heater ON with the Preset time settings loaded from EEPROM -> Count down -> [increase or decrease ON time duration (if required) with push buttons while the timer is continuing  counting down! (New stop time set on the go!)] -> Stop Heater (if) new set Time reaches to 0.

Is above flowchart implementable? I mean, modifying time without stopping the heater and set a temporary new stop time. This is required since some family members will like more or less hot water than the preset hot water! They can increase or decrease the time with the push buttons for him/herself on the go. Also, this new personal settings will not be stored in to EEPROM. Please note, it is not good to stop the heater and then set a new time and start it again . I say this because the heater draws about 10 Amp on 220V. It is not good to ON/OFF such a large current device many times! I am not sure whether you understand what I say here!

Would you say something about my new flowchart? Thanks.

NB: You may please have a look on my current analog water heater count down timer video on my google drive share drive (115 MB).
https://drive.google.com/drive/folders/1o7E6cmL4AFLufr_B3Mo1qqayQgNUmsks?usp=sharing
 
« Last Edit: August 27, 2020, 04:50:03 am by asadulhuq »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #18 on: August 27, 2020, 07:31:59 am »
That's what my proposal is supposed to do: while the timer is running, the variables 'hours', 'minutes' and 'seconds' may be dynamically modified with the buttons but are not saved in the eeprom. The (updated) remaining time will continue to be displayed on the second line of the LCD :D
 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #19 on: August 27, 2020, 08:04:47 am »
ggchab<<
Thanks. I will change my code. Also, I have thought that I will remove hours option, since my water heater doesn't require more than 60 minutes ever. Seconds will be there in display to show that timer is counting down, but no push button for setting seconds! In addition to that current hours button will be used with the minutes button to push simultaneously to decrease seup time (minutes only). This will make settings
convenient. Setup Minutes ++, or even -- ! Ultimately, the timer will be a 99 minute timer. Please leave a comment about my new setting method. Thanks again. I learned   many aspects of Microcontroller programming from you.
I am a teacher (professor) in the University of Dhaka, in Bangladesh. My department is Electrical Engineering (Research field is Digital Signal Processing). I am 60 years old. Did you imagine my age!!

BTW, did you watch the video of my Analog Timer?
« Last Edit: August 27, 2020, 08:30:55 am by asadulhuq »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #20 on: August 27, 2020, 09:24:17 am »
Always good to have options to change a counter back and forth !
Glad I could help you  :)
Nice way to reuse a PC power supply case  :-+
Yes, I thought you were younger  ;D
 

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #21 on: August 27, 2020, 09:36:01 am »
ggchab<<
I don't know any thing personal about you. I understand you are a good and kind person. Also you are an excellent programmer. By the way, where are you from? Thanks.
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #22 on: August 27, 2020, 10:25:38 am »
I live not far from Namur, a small city in Belgium.
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 281
  • Country: be
Re: Displaying Time to LCD
« Reply #23 on: August 27, 2020, 10:28:09 am »
Some more pictures ...
 
The following users thanked this post: asadulhuq

Offline asadulhuqTopic starter

  • Contributor
  • Posts: 36
  • Country: bd
Re: Displaying Time to LCD
« Reply #24 on: August 28, 2020, 08:25:09 am »
ggchab<<
You are lucky since you are living in a beautiful country. At the same time your city photos are eye catching. I shall also post some pictures of my city later. Thank you.
« Last Edit: August 28, 2020, 08:27:36 am by asadulhuq »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf