AVR EEPROM understanding.

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello once again to everyone. I am now planning to create a RTC timer using DS1307 RTC chip and Atmega16 I have come a long way though but requires a little help in Avr Eeprom. I know how to use the Eeprom but the code which i found out on the internet use something i didn't understand i tried but didn't really know why this thing is here. This code uses four address of the eeprom to store the startHr, startMin, stopHr and stopMin but what this coder has used to update these blocks is tough for me to understand for example i did'nt know why he has stored 0xaa55 in the eeprom.Please help.



#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <stdio.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include "main.h"
#include "LCD_4bit.h"
#include "i2c_routines.h"
#include "RTC_routines.h"

void port_init(void)
{
	PORTB = 0x00;	//
	DDRB  = 0x3f;	//6 o/p pins for LCD
	PORTC = 0x00;	
	DDRC  = 0x00;	
	PORTD = 0x1c;	//pull-up enables for 3 pushbuttons	
	DDRD  = 0xe2;	//2 o/p for relays, 1 o/p for LED, 1 o/p for TXD and 3 i/p for pushbuttons
}


//****** Function to update EEPROM with new set time *******
void updateEEPROM (void)
{
	eeprom_write_byte((uint8_t*)10, startHr);
	eeprom_write_byte((uint8_t*)12, startMin);
	eeprom_write_byte((uint8_t*)14, stopHr);
	eeprom_write_byte((uint8_t*)16, stopMin);
	eeprom_write_word((uint16_t*)20, 0xaa55); //why this is here?
}

//***** Function to respond to any button-press during RTC set*******
void buttonResponseRTC(void)
{
	if(SET_PRESSED)
	{
		switch(screen)
		{
			case 0: sprintf(line2, "Date: %02x        ", DATE);
					screen = 1;	
					break;
			case 1: sprintf(line2, "Month: %02x       ", MONTH);
					screen = 2;
					break;
			case 2: sprintf(line2, "Year: 20%02x      ", YEAR);
					screen = 3;
					break;
			case 3: sprintf(line2, "Hour: %02x        ", HOURS);
					screen = 4;
					break;
			case 4: sprintf(line2, "Minute: %02x      ", MINUTES);
					screen = 5;
					break;
			case 5: SECONDS = 0;
					screen = 6;
					break;
			default:break;
		}
	}
	
	if(UP_PRESSED)
	{
		switch(screen)
		{
			case 1: DATE++;
					if((DATE % 16) == 0x0a) DATE += 0x06;
					if(DATE >= 0x32) DATE = 0x01;
					sprintf(line2, "Date: %02x        ", DATE);
					break;
			case 2: MONTH++;
					if(MONTH == 0x0a) MONTH = 0x10;
					if(MONTH >= 0x13) MONTH = 0x01;
					sprintf(line2, "Month: %02x       ", MONTH);
					break;
			case 3: YEAR++;
					if((YEAR % 16) == 0x0a) YEAR += 0x06;
					if(YEAR >= 0xa0) YEAR = 0x01;
					sprintf(line2, "Year: 20%02x      ", YEAR);
					break;
			case 4: HOURS++;
					if(HOURS == 0x0a) HOURS = 0x10;
					if(HOURS == 0x1a) HOURS = 0x20;
					if(HOURS >= 0x24) HOURS = 0x00;
					sprintf(line2, "Hour: %02x        ", HOURS);
					break;
			case 5: MINUTES++;
					if((MINUTES % 16) == 0x0a) MINUTES += 0x06;
					if(MINUTES >= 0x60) MINUTES = 0x00;
					sprintf(line2, "Minute: %02x      ", MINUTES);
					break;
			default:break;
		}
	}
	
	if(DWN_PRESSED)
	{
		switch(screen)
		{
			case 1: DATE--;
					if(DATE == 0x00) DATE = 0x31;
					else if((DATE % 16) == 0x0f) DATE -= 0x06;
					sprintf(line2, "Date: %02x        ", DATE);
					break;
			case 2: MONTH--;
					if(MONTH == 0x00) MONTH = 0x12;
					else if(MONTH == 0x0f) MONTH = 0x09;
					sprintf(line2, "Month: %02x       ", MONTH);
					break;
			case 3: if(YEAR == 0x00) YEAR = 0x99;
					else YEAR--;
					if((YEAR % 16) == 0x0f) YEAR -= 0x06;
					sprintf(line2, "Year: 20%02x      ", YEAR);
					break;
			case 4: if(HOURS == 0) HOURS = 0x23;
					else HOURS--;
					if(HOURS == 0x1f) HOURS = 0x19;
					if(HOURS == 0x0f) HOURS = 0x09;
					sprintf(line2, "Hour: %02x        ", HOURS);
					break;
			case 5: if(MINUTES == 0) MINUTES = 0x59;
					else MINUTES --;
					if((MINUTES % 16) == 0x0f) MINUTES -= 0x06;
					sprintf(line2, "Minute: %02x      ", MINUTES);
					break;
			default:break;
		}
	}
}


//***** Function to respond to any button-press during timer set*******
void buttonResponse(void)
{
	if(SET_PRESSED)
	{
		switch(screen)
		{
			case 0: sprintf(line2, "S:%02x:%02x  E:%02x:%02x", startHr, startMin, stopHr, stopMin);
					screen = 1;	
					break;
			case 1: screen = 0;
					break;
			case 2: sprintf(line2, "Start Min: %02x   ", startMin);
					screen = 3;
					break;
			case 3: sprintf(line2, "Stop Hour: %02x   ", stopHr);
					screen = 4;
					break;
			case 4: sprintf(line2, "Stop Min: %02x    ", stopMin);
					screen = 5;
					break;
			case 5: updateEEPROM();	
					LCD_DisplayString_F(2,1,PSTR("Time updated!   "));
					_delay_ms(1000);
					screen = 0;
					break;
			default:break;
		}
	}
	
	if(UP_PRESSED)
	{
		switch(screen)
		{
			case 1:	sprintf(line2, "Start Hour: %02x  ", startHr);
					screen = 2;
					break;
			case 2: startHr++;
					if(startHr >= 0x24) startHr = 0x00;
					if(startHr == 0x0a) startHr = 0x10;
					if(startHr == 0x1a) startHr = 0x20;
					sprintf(line2, "Start Hour: %02x  ", startHr);
					break;
			case 3: startMin += 0x05;
					if((startMin % 16) == 0x0a) startMin += 0x06;
					if(startMin >= 0x60) startMin = 0x00;	
					sprintf(line2, "Start Min: %02x   ", startMin);
					break;
			case 4: stopHr++;
					if(stopHr >= 0x24) stopHr = 0x00;
					if(stopHr == 0x0a) stopHr = 0x10;
					if(stopHr == 0x1a) stopHr = 0x20;
					sprintf(line2, "Stop Hour: %02x   ", stopHr);
					break;
			case 5: stopMin += 0x05;
					if((stopMin % 16) == 0x0a) stopMin += 0x06;
					if(stopMin >= 0x60) stopMin = 0x00;
					sprintf(line2, "stop Min: %02x    ", stopMin);
					break;
			default:break;
		}
	}
	
	if(DWN_PRESSED)
	{
		switch(screen)
		{
			case 1:	sprintf(line2, "Start Hour: %02x  ", startHr);
					screen = 2;
					break;
			case 2: if(startHr == 0) startHr = 0x23;
					else startHr--;
					if(startHr == 0x1f) startHr = 0x19;
					if(startHr == 0x0f) startHr = 0x09;
					sprintf(line2, "Start Hour: %02x  ", startHr);
					break;
			case 3: if(startMin == 0) startMin = 0x55;
					else startMin -= 0x05;
					if((startMin % 16) == 0x0b) startMin -= 0x06;
					sprintf(line2, "Start Min: %02x   ", startMin);
					break;
			case 4: if(stopHr == 0) stopHr = 0x23;
					else stopHr--;
					if(stopHr == 0x1f) stopHr = 0x19;
					if(stopHr == 0x0f) stopHr = 0x09;
					sprintf(line2, "stop Hour: %02x  ", stopHr);
					break;
			case 5: if(stopMin == 0) stopMin = 0x55;
					else stopMin -= 0x05;
					if((stopMin % 16) == 0x0b) stopMin -= 0x06;
					sprintf(line2, "stop Min: %02x   ", stopMin);
					break;
			default:break;
		}
	}
}

//call this routine to initialize all peripherals
void init_devices(void)
{
	port_init();
//	UART_init();
	LCD_init();
	twi_init();
	
	MCUCR = 0x00;
	GICR  = 0x00;
	TIMSK = 0x00;
}

//set stream pointer for using printf, scanf
//FILE uart_str = FDEV_SETUP_STREAM(transmitByte, receiveByte, _FDEV_SETUP_RW);

int main(void)
{    
	uint8_t prevSec;
	
	_delay_ms(100);
	init_devices();
	_delay_ms(10);
	//stdin = stdout = &uart_str;  //redirecting stdio to uart
	
	LCD_DisplayString_F(1,1,PSTR("Welcome!"));
	line1[16] = '\0';
	line2[16] = '\0';
	screen = 0;
	prevSec = 0;
	RELAY1_OFF;
	RELAY2_OFF;
	LED_OFF;
	relayON = 0;
	
	if(eeprom_read_word((uint16_t*)20) != 0xaa55) //i want to know what is the use of this 0xaa55
	{
		startHr = 0x12;
		startMin = 0x25;
		stopHr = 0x13;
		stopMin = 0x05;
		updateEEPROM();
	}
	else  // and how this block helped in updating of eeprom
	{
		startHr = eeprom_read_byte((uint8_t*)10);
		startMin = eeprom_read_byte((uint8_t*)12);
		stopHr = eeprom_read_byte((uint8_t*)14);
		stopMin = eeprom_read_byte((uint8_t*)16);
	} 
	
	//printf_P(PSTR("-- RELAY TIMER --\n\n"));
	//printf("\nStart Time: %02x:%02x", startHr, startMin);
	//printf("\nStop Time : %02x:%02x", stopHr, stopMin);
	//RTC_read();
	//printf("\nCrrent Date: %02x:%02x  Current Time: %02x:%02x", DATE, MONTH, HOURS, MINUTES);
	
	if(SET_PRESSED)
	{
		_delay_ms(20);
		if(SET_PRESSED)
		{
			LCD_DisplayString_F(1, 1, PSTR("RTC Setting..   "));
			RTC_read();		
			while(screen != 6)
			{
				if(ANY_BUTTON_PRESSED)
				{
					_delay_ms(20);		//key debouncing delay
					if(ANY_BUTTON_PRESSED) buttonResponseRTC();
					while(ANY_BUTTON_PRESSED);
					LCD_DisplayString (2, 1, line2);
				}
				_delay_ms(20);	//loop delay of 20msec
			}
		}
		
		RTC_writeTime();
		RTC_writeDate();
		screen = 0;
		_delay_ms(40);
	}
	
	
	while(1)
    {
		RTC_read();
		if(!relayON)
		{
			if((rtc_register[2] == startHr) && (rtc_register[1] == startMin))
			{
				RELAY1_ON;
				RELAY2_ON;
				LED_ON;
				relayON = 1;
			}
		}
		else
		{
			if((rtc_register[2] == stopHr) && (rtc_register[1] == stopMin))
			{
				RELAY1_OFF;
				RELAY2_OFF;
				LED_OFF;
				relayON = 0;
			}
		}
		
		if(SECONDS != prevSec)
		{
			sprintf(line1,"%02x/%02x  %02x:%02x:%02x ", DATE, MONTH, HOURS, MINUTES, SECONDS);
			if(screen == 0)
			{
				if(relayON) sprintf(line2,"O/P: ON         ");
				else sprintf(line2,"O/P: OFF        ");
			}
			
			LCD_DisplayString (1, 1, line1);
			LCD_DisplayString (2, 1, line2);
			prevSec = SECONDS; 
		}
		
		if(ANY_BUTTON_PRESSED)
		{
			_delay_ms(20);		//key debouncing delay
			if(ANY_BUTTON_PRESSED) buttonResponse();
			while(ANY_BUTTON_PRESSED);
		}
		
		_delay_ms(100);	//loop delay of 100msec
    }
	
	while(1);
	return 0;
}

//************************   END   **************************

 

This topic has a solution.

anshumaan kumar

Last Edited: Fri. Nov 15, 2019 - 12:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

commonly called a 'magic' value or 'token'. Used to determine if the eeprom has been initialised with default values. When you start up, read the eeprom for the 'magic' value. If it is not correct, you load the default values.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

 read the eeprom for the 'magic' value

Oh i see let me see it's like a reference value for the eeprom. It is changable or I had to use this same value for any atmega chip??

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's just a marker...when the EEPROM is fresh/erased, all locations contain 0xFF.

So you store something else as a "marker" to show the EEPROM has been "written to"

 

If you 100% knew a used location would never have 0xFF as a valid value, you could use that as a check instead...however, that is more dangerous..better to use a separate location & keep those tasks independent. 

Since the marker is written last, that also gives some assurance the proceeding data was actually written (since the marker is written last).  At least for the first run. 

 

It is wise to also include a checksum so you can verify the data is likely valid.  The simplest is just to add up all the ram values being saved (let sum rollover) & store the result (0-255).  This can be used as a check later, with a chance of missing any error of about 1 in 256 (better than no check).  There are more sophisticated methods.

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Wow, what a spooky coincidence. I explained this very thing just yesterday:

 

https://www.avrfreaks.net/commen...

 

In fact in this later post:

 

https://www.avrfreaks.net/commen...

 

I actually chose to use the value 0x55AA, very similar to the AA55 above.

 

Just two things about the code you show though. First the hard coded numbers in this:

void updateEEPROM (void)
{
	eeprom_write_byte((uint8_t*)10, startHr);
	eeprom_write_byte((uint8_t*)12, startMin);
	eeprom_write_byte((uint8_t*)14, stopHr);
	eeprom_write_byte((uint8_t*)16, stopMin);
	eeprom_write_word((uint16_t*)20, 0xaa55); //why this is here?
}

This would be far better to let the compiler/linker place these things in EEPROM. That is using EEMEM:

uint8_t EEMEM	eeprom_startHr;
uint8_t EEMEM	eeprom_startMin;
uint8_t EEMEM	eeprom_stopHr;
uint8_t EEMEM	eeprom_stopMin;
uint8_t EEMEM	eeprom_valid;

void updateEEPROM (void)
{
	eeprom_update_byte(&eeprom_startHr, startHr);
	eeprom_update_byte(&eeprom_startMin, startMin);
	eeprom_update_byte(&eeprom_stopHr, stopHr);
	eeprom_update_byte(&eeprom_stopMNin, stopMin);
	eeprom_update_word(&eeprom_valid, 0xaa55);
}

Also, as I've shown here never use eeprom_write_*() functions. Always use eeprom_update_*() instead. The reason is that the "update" versions first check to see if the location being written already holds the value given. If so it does not bother to erase/write the location. The _write_ functions just go ahead and do the operation even if nothing would change (but in doing so it "wears out" the EEPROM).

 

If you switch to using EEMEM then:

	else  // and how this block helped in updating of eeprom
	{
		startHr = eeprom_read_byte((uint8_t*)10);
		startMin = eeprom_read_byte((uint8_t*)12);
		stopHr = eeprom_read_byte((uint8_t*)14);
		stopMin = eeprom_read_byte((uint8_t*)16);
	} 

will become:

	else  // and how this block helped in updating of eeprom
	{
		startHr = eeprom_read_byte(&eeprom_startHr);
		startMin = eeprom_read_byte(&eeprom_startMin);
		stopHr = eeprom_read_byte(&eeprom_stopHr);
		stopMin = eeprom_read_byte(&eeprom_startMin);
	} 

Hopefully you can see the advantage in this already - not only does letting the linker choose the location guarantee (like variables in RAM) that there is no overlap or wastage in the bytes used. But the reading code now explains what is going on - an eeprom_read_byte((uint8_t *)14) could be reading anything while eeprom_read_byte(&eeprom_stopHr) says exactly what is being read!

Last Edited: Tue. Nov 12, 2019 - 09:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Always use eeprom_update_*() instead.

Yes. I know the benefits of using eeprom_update instead of eeprom_write which is why i was trying to update this code but you have done that for me. So kind of you.Thankssmiley Although my question has been answered but i still want to ask something regarding this code. But first tell me that if i have to create a new forum for a new problem i encountered in this code??

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
But first tell me that if i have to create a new forum for a new problem i encountered in this code??
If the question is still about EEPROM/EEMEM then this thread is appropriate. If it's not related to the thread title "AVR EEPROM Understanding" then do create a separate thread.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes. This problem is partially of the EEPROM used and regarding the placement of the operators to use the EEPROM in the exact way i want. 

if(!relayON)
		{
			if((rtc_register[2] == startHr) && (rtc_register[1] == startMin))
			{
				RELAY1_ON;
				RELAY2_ON;
				LED_ON;
				relayON = 1;
			}
		}
		else
		{
			if((rtc_register[2] == stopHr) && (rtc_register[1] == stopMin))
			{
				RELAY1_OFF;
				RELAY2_OFF;
				LED_OFF;
				relayON = 0;
			}
		}

Here you all can see that if the current time is equal to the time saved in the EEPROM then the output lights up. This is fine until you see it theoretically but when i have burned the program in the hardware it turns on the output at the set time but if somehow the power is disrupted the MCU then doesnt remember that the output was on.(because it was not told to do so).

What i want is that MCU should compare the start time and the stop time and then turn ON/OFF the output accordingly even when it is shut down many times. Can anyone tell me how can i do this i have tried storing the status of the output in the eeprom and used the <= and >= operators but still no luck.

I believe that this problem requires the correct placement of relational operators in the if statments in the code above.smiley

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would like to throw in a question on the timing.   The datasheet for the mega328p says that the EEPROM write takes 3.3 ms.  Is that per operation, so that eeprom_update_byte() would spin for 3.3 ms? 

 

One could use interrupt handlers to avoid the 3.3 ms hit.

 

Here is the code quoted from the mega328p datasheet:

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
  /* Wait for completion of previous write */
  while(EECR & (1<<EEPE))
     ;
  /* Set up address and Data Registers */
  EEAR = uiAddress;
  EEDR = ucData;
  /* Write logical one to EEMPE */
  EECR |= (1<<EEMPE);
  /* Start eeprom write by setting EEPE */
  EECR |= (1<<EEPE);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What i want is that MCU should compare the start time and the stop time and then turn ON/OFF the output accordingly

Surely it's just something like:

mins_since_midnight = (rtc_register[2] * 60) + rtc_register[1];
start_since_midnight = (startHr * 60) + startMin;
stop_since_midnight = (stopHr * 60) + stopMin;

if ((mins_since_midnight >= start_since_midnight) && (mins_since_midnight <= stop_since_midnight)) {
    // turn things on
}
else {
    // turn things off
}

I rather gratuitously added "_since_midnight" to that all over the place to make it clear that I was combining hours and minutes into a single number to make the range comparison easier but you could have "mins_now", "mins_start", "mins_stop" or something like that.

 

The point in all this is that to relative comparison of times it's easiest if you combine it all into a single number.

 

In fact this is such a common thing that there is a rather well know (and exceedingly widely use) technique for this. In "unixtime" (aka "epoch time") all times are given as the number of seconds since midnight on the 1st of January 1970. For example if I go to:

 

https://www.epochconverter.com/

 

then right now the time is 1573574146 which represents 2019-11-12, 15:55:45 Now since 1970 to 2019 there have been 49 years. While leap years and stuff (leap seconds even!) mean the number is not exact there are roughly 365*24*60*60 seconds per year. So that's about 31,536,000 seconds per year. In the 49 years since 1970 that is roughly 1545264000 seconds. Then from 1st January to 1st November 304 days and because we're on 12th Nov then it's 316 days so far this year. That is 27302400 seconds. Then since midnight to 3:55pm it's about 16 hours so 57,600 seconds. So 1545264000 + 27302400 + 57600 is 1572624000 seconds. Which is pretty close to the 1573574146 I started with (between 1970 and 2019 there have been quite a few leap years so years with an extra day which are 86,400 additional seconds each).

 

You may wonder why I explained all this. Well the point is this. Suppose I want to know exactly how long is it since 17:54:23 on 1989-07-23 and 2019-11-12 15:55:45 then subtracting one from the other looks (at first) impossible (or at least very, very complicated!) but then I realise it is 1573574146 -  617219665 then it is 956354481 seconds. That is 11068.917604166 days.

 

This is the point - when you have yy-mm-dd hh:mm:ss or time in any kind of mixed number base like this then convert to the lowest denominator (ss) in this case then checking for ranges is easy. Because, for example I know that 17:54:23 on 1989-07-23 is 617219665 and 2019-11-12, 15:55:45 is 1573574146 then I could tell you immediately that 937410369 falls between those two dates (as it happens it is Wednesday, September 15, 1999 3:46:09 PM )

Last Edited: Tue. Nov 12, 2019 - 04:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Clawson for the great concept i am not aware of this, due to your concept i was able to turn ON my output even if there are power disruptions but i have noticed something, the output turns ON quite well but it blinks same is the case when it has to be OFF. I know what has caused this, the relational operators <= and >= are here to blame because i have encountered the same problem before when i have used these operators.

while(1)
    {
		RTC_read();
		if(!relayON)
		{
			mins_since_midnight = ((rtc_register[2] * 60) + rtc_register[1]);
			start_since_midnight = ((startHr * 60) + startMin);
			stop_since_midnight = ((stopHr * 60) + stopMin);
			
			if((mins_since_midnight >= start_since_midnight) && (mins_since_midnight <= stop_since_midnight))
			{
				RELAY1_ON;
				RELAY2_ON;
				LED_ON;
				relayON = 1;
			}
		}
		else
		{
			RELAY1_OFF;
				RELAY2_OFF;
				LED_OFF;
				relayON = 0;
			
		}

This is what i have written(basically a cut and paste of what Clawson has given to me ).

Any advice is most welcome.smiley

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry my bad i must have done something wrong this code works pretty well but it doesn't turn OFF the outputs at the set time as it should. 

while(1)
    {
		RTC_read();
		if(!relayON)
		{
			mins_since_midnight = ((rtc_register[2] * 60) + rtc_register[1]);
			start_since_midnight = ((startHr * 60) + startMin);
			stop_since_midnight = ((stopHr * 60) + stopMin);
			
			if((mins_since_midnight >= start_since_midnight) && (mins_since_midnight <= stop_since_midnight))
			{
				RELAY1_ON;
				RELAY2_ON;
				LED_ON;
				relayON = 1;
			}
		}
		//else
		if((mins_since_midnight >= stop_since_midnight) && (mins_since_midnight <= start_since_midnight))
		{
			RELAY1_OFF;
				RELAY2_OFF;
				LED_OFF;
				relayON = 0;
			
		}

NOTE = There is no blinking.

anshumaan kumar

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

while(1){
    RTC_read();

 

    //need to be 16bit numbers (doing a *60 will get you >8bits)
    uint16_t Tnow = rtc_register[2] * 60 + rtc_register[1];
    uint16_t T1 = startHr * 60 + startMin;
    uint16_t T2 = stopHr * 60 + stopMin;

 

    //are we in the time Window?
    uint8_t isActive = (Tnow >= T1) && (Tnow < T2);

 

    //if relay on and should be off, turn off
    if( relayON && !isActive ){
        RELAY1_OFF;
        RELAY2_OFF;
        LED_OFF;
        relayON = 0;        
    }

 

    //if relay off and should be on, turn on
    if( !relayON && isActive ){
        RELAY1_ON;
        RELAY2_ON;
        LED_ON;
        relayON = 1;
    }
}

 

 

and can make this change in case start/stop times cross midnight-

 

    //are we in the time Window?
    //assume start/stop time are the same (invalid setting)
    uint8_t isActive = 0;
    //if no midnight crossing, normal compare
    if( T2 > T1 ) isActive = (Tnow >= T1) && (Tnow < T2);
    //if midnight crossed, need >= start OR < stop
    if( T1 > T2 ) isActive = (Tnow >= T1) || (Tnow < T2);

 

Last Edited: Wed. Nov 13, 2019 - 02:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your logic seems like a twist

 mins_since_mid is only computed some of the time, but used in multiple places?

 

READ TIME

IF OFF

   COMPUTE VALUES    <<<===WHY HERE??

   IF VALUES

         TURN ALL ON

ELSE

   IF VALUES

        TURN ALL OFF

  

edit:

Looks like Curt jumped in whilst I was typing.

   ...note for simplicity, relayON could be tossed in the trashcan, since there is no harm in repeatedly turning on the relay or the led. If it were more involved  (or took time) like writing to a SPI DAC, or  updating an lcd, you'd only want to do that ONCE per event change to prevent flicker, etc.

 

 

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. Nov 13, 2019 - 02:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Curtvm code works as expected i have learned a lot about epoch time and how to deal with such things ..Thank you people.One more thing that i want to say that how can i be such experts in embedded field like you guys???

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Anshumaan wrote:
how can i be such experts in embedded field like you guys???
Experience. I've been doing this for about 40 years so you build up a bit of knowledge over tine. Of course towards the latter end of things you then start to forget everything you previously knew - such is life !