Manipulating time variables

Do you have a question on how to do something.
Ask in here.
Post Reply
User avatar
joshlawless
Posts: 138
Joined: Thu May 23, 2013 2:52 pm

Manipulating time variables

Post by joshlawless »

I would like to make use of the internal memory variables for storing standard light times, and then calculate offsets from those times for different lighting channels (e.g., red channels start earlier and end later, to simulate warm light at sunrise/sunset).

I'm not sure how best to calculate offsets against the minutes, however, as the internal memory stores the hours and minutes separately, and an offset that would take the minutes higher than 60 or lower than 0 would probably cause a problem.

If I were using a PWM code to calculate the light level for a given time, how could I modify this to calculate the correct hour and minute values if I want to offset it by 30 minutes, and don't know whether that will take me past an hour threshhold?

Code: Select all

PWMSmoothRampHighRes(InternalMemory.StdLightsOnHour_read(), InternalMemory.StdLightsOnMinute_read(), InternalMemory.StdLightsOffHour_read(), InternalMemory.StdLightsOffMinute_read(), 0, 100, 120, 0);


Is there a function somewhere that can accommodate this, or can someone help me with some custom code to take the existing hour and minute variables and calculate a new variable based on the offset?

something like

Code: Select all

if (InternalMemory.StdLightsOnMinute_read()+Offset>60) 
{
  byte newMinutes=InternalMemory.StdLightsOnMinute_read()-60;
  byte newHour=InternalMemory.StdLightsOnHour_read()+1
  for (int a=0;a<5;a++) {
    if newMinutes > 60 (newMinutes=newMinutes-60; newHour=newHour+1;)
  };
};
If the Offset is a byte, and therefore limited to 255, I figure I cant wind up adding more than five hours, so I iterate that check of exceeding 60 five times.

This doesn't seem terribly efficient, and would require another function to accommodate offsets going the other way, and potentially another to handle offsets that push the hour past midnight.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Manipulating time variables

Post by rimai »

I think Alan already created a function that does what you want:

Code: Select all

void SIXTEENChannelPWMSmoothRamp(byte Channel, int Start, int End, byte SlopeLength, int MinuteOffset);
Roberto.
User avatar
joshlawless
Posts: 138
Joined: Thu May 23, 2013 2:52 pm

Re: Manipulating time variables

Post by joshlawless »

Code: Select all

void SIXTEENChannelPWMSmoothRamp(byte Channel, int Start, int End, byte SlopeLength, int PreMinuteOffset, int PostMinuteOffset)
{
	int onTime=NumMins(InternalMemory.StdLightsOnHour_read(), InternalMemory.StdLightsOnMinute_read()) - PreMinuteOffset;
	int offTime=NumMins(InternalMemory.StdLightsOffHour_read(), InternalMemory.StdLightsOffMinute_read()) + PostMinuteOffset;
	Set16ChannelRaw(Channel,PWMSmoothRampHighRes(
		onTime/60,
		onTime%60,
		offTime/60,
		offTime%60,
		Start,
		End, 
                SlopeLength,
		OldValue
	));	
}
It looks like this relies on the library code for implementing a single 16-channel expansion. To get it functional with my two 16-channel expansion modules, I imagine I'll have to define something similar in my code, so I can choose which device (0x41 or 0x42) to send it to:

Code: Select all


void loop()
{
CustomExpansion(0x41,0,OffsetSmoothRamp(-30,30,0,100,120,0)) 
/* This sends a signal to first 16-channel board (0x41) on channel 0, with the 12-bit PWM value returned by the function that turns on 30 minutes early w/r/t standardtime, turns off 30 minutes late, ramps from 0 to 100 over 120 minutes, with oldValue=0 (not sure what oldValue does -- sends value for when outside of slope calculation, I think?) */
}



void OffsetPWMSmoothRamp(int OnMinutesLate, int OffMinutesLate, int StartPercent, int EndPercent, byte SlopeLength, int OldValue)
{
	int onTime=NumMins(InternalMemory.StdLightsOnHour_read(),InternalMemory.StdLightsOnMinute_read())+OnMinutesLate;
	int offTime=NumMins(InternalMemory.StdLightsOffHour_read(),InternalMemory.StdLightsOffMinute_read())+OffMinutesLate;
        PWMSmoothRampHighRes(onTime/60, onTime%60, offTime/60, offTime%60, StartPercent, EndPercent, SlopeLength, OldValue);
}

void CustomExpansion(byte id, byte channel, int level)
{
  Wire.beginTransmission(id);
  Wire.write(0);
  Wire.write(0xa1);
  Wire.endTransmission();
  Wire.beginTransmission(id);
  Wire.write(0x8+(4*channel));
  Wire.write(level&0xff);
  Wire.write(level>>8);
  Wire.endTransmission();
}
Not sure why the library code sends "SIXTEENChExpansionChannel[Channel]" as the final variable to the PWMSmoothRampHighRes function -- I thought that the final variable was the default value to return when the slope is not calculated (i.e., outside the slope start and end times -- variable "oldValue" in the library code.
User avatar
joshlawless
Posts: 138
Joined: Thu May 23, 2013 2:52 pm

Re: Manipulating time variables

Post by joshlawless »

Do you see anything amiss with using arrays in this way (to define the board address, for example)?

Code: Select all

//global variables:
//
// NWE = Neutral White East, CBN = Cool Blue North, VIW = Violet West, etc.
//
// LED Arrays organized as  { NWE,  NWW,  NWN,  WWE,  WWW,  WWN,  RDE,  RDW,  RDN,  CYE,  CYW,  CYN,  CBE,  CBW,  CBN,  RBE,  RBW,  RBN,  INE,  INW,  INN,  VIE,  VIW,  VIN}
byte LEDBoardAddress [24] = {0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42}
byte LEDBoardChannel [24] = {   0,    8,    0,    1,    9,    1,    2,   10,    2,    3,   11,    3,    4,   12,    4,    5,   13,    5,    6,   14,    6,    7,   15,    7}
int  LEDTurnOnDelay  [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}
int  LEDTurnOffDelay [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}
int  LEDStartPercent [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}
int  LEDEndPercent   [24] = { 100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100}
byte LEDRampRate     [24] = { 120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120}
int  LEDDefaultLevel [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}


void loop()
{
  for (int a=0;a<24;a++) 
  {
    CustomExpansion(LEDBoardAddress[a], LEDBoardChannel[a], OffsetPWMSMoothRamp(LEDTurnOnDelay[a], LEDTurnOffDelay[a], LEDStartPercent[a], LEDEndPercent[a], LEDRampRate[a], LEDDefaultLevel[a]));
  }
}


void OffsetPWMSmoothRamp(int OnMinutesLate, int OffMinutesLate, int StartPercent, int EndPercent, byte SlopeLength, int OldValue)
{
  int onTime=NumMins(InternalMemory.StdLightsOnHour_read(),InternalMemory.StdLightsOnMinute_read())+OnMinutesLate;
  int offTime=NumMins(InternalMemory.StdLightsOffHour_read(),InternalMemory.StdLightsOffMinute_read())+OffMinutesLate;
  PWMSmoothRampHighRes(onTime/60,onTime%60,offTime/60,offTime%60,StartPercent,EndPercent,SlopeLength,OldValue);	
}


void CustomExpansion(byte id, byte channel, int level)
{
  Wire.beginTransmission(id);
  Wire.write(0);
  Wire.write(0xa1);
  Wire.endTransmission();
  Wire.beginTransmission(id);
  Wire.write(0x8+(4*channel));
  Wire.write(level&0xff);
  Wire.write(level>>8);
  Wire.endTransmission();
}


Also, is there any reason the time delays and start percents need to be defined as type int? Seems like so long as the value will always be less than 256, that byte would be a more efficient use of space.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Manipulating time variables

Post by rimai »

Looks good to me.
Roberto.
User avatar
joshlawless
Posts: 138
Joined: Thu May 23, 2013 2:52 pm

Re: Manipulating time variables

Post by joshlawless »

For posterity, I noticed when I tried to compile that there was an error in the code above. The function OffsetPWMSmoothRamp() needed to be defined in a way to actually return an integer:

Code: Select all

//global variables:
//
// NWE = Neutral White East, CBN = Cool Blue North, VIW = Violet West, etc.
//
// LED Arrays organized as  { NWE,  NWW,  NWN,  WWE,  WWW,  WWN,  RDE,  RDW,  RDN,  CYE,  CYW,  CYN,  CBE,  CBW,  CBN,  RBE,  RBW,  RBN,  INE,  INW,  INN,  VIE,  VIW,  VIN}
byte LEDBoardAddress [24] = {0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42, 0x41, 0x41, 0x42}
byte LEDBoardChannel [24] = {   0,    8,    0,    1,    9,    1,    2,   10,    2,    3,   11,    3,    4,   12,    4,    5,   13,    5,    6,   14,    6,    7,   15,    7}
int  LEDTurnOnDelay  [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}
int  LEDTurnOffDelay [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}
int  LEDStartPercent [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}
int  LEDEndPercent   [24] = { 100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100,  100}
byte LEDRampRate     [24] = { 120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120,  120}
int  LEDDefaultLevel [24] = {   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}


void loop()
{
  for (int a=0;a<24;a++) 
  {
    CustomExpansion(LEDBoardAddress[a], LEDBoardChannel[a], OffsetPWMSMoothRamp(LEDTurnOnDelay[a], LEDTurnOffDelay[a], LEDStartPercent[a], LEDEndPercent[a], LEDRampRate[a], LEDDefaultLevel[a]));
  }
}


int OffsetPWMSmoothRamp(int OnMinutesLate, int OffMinutesLate, int StartPercent, int EndPercent, byte SlopeLength, int OldValue)
{
  int onTime=NumMins(InternalMemory.StdLightsOnHour_read(),InternalMemory.StdLightsOnMinute_read())+OnMinutesLate;
  int offTime=NumMins(InternalMemory.StdLightsOffHour_read(),InternalMemory.StdLightsOffMinute_read())+OffMinutesLate;
  PWMSmoothRampHighRes(onTime/60,onTime%60,offTime/60,offTime%60,StartPercent,EndPercent,SlopeLength,OldValue);   
}


void CustomExpansion(byte id, byte channel, int level)
{
  Wire.beginTransmission(id);
  Wire.write(0);
  Wire.write(0xa1);
  Wire.endTransmission();
  Wire.beginTransmission(id);
  Wire.write(0x8+(4*channel));
  Wire.write(level&0xff);
  Wire.write(level>>8);
  Wire.endTransmission();
}
Post Reply