PWMSmoothRampHighRes

Do you have a question on how to do something.
Ask in here.
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

PWMSmoothRampHighRes

Post by tanked_kiwi »

I see in the new libraries there's a heap of hi res dimming functions. I tried this in place of PWMSlope and it didn't work. Just cycled rather quickly from start to finish over and over.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

Were you using it on a dimming expansion? The hi-res functions only work on a newer, 12 bit dimming expansion. They won't work correctly on the Daylight or Actinic ports or on an old dimming expansion.
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: PWMSmoothRampHighRes

Post by lnevo »

That's not true the HighRes should work on all the dimming ports. You'll only get 12bit on the newer ones, but the rest are 0-255 which is 8bit. Before we only had 0-100 increments on the built in and older units. But now with the HighRes that should be 256 increments.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

Not exactly sure where in this function it differentiates between ports. Looks like it returns 0-4095 to me.

Code: Select all

int PWMSmoothRampHighRes(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, byte endPWM, byte slopeLength, int oldValue)
{
  LightsOverride=true;
  int current_hour = hour();
  long start = NumMins(startHour, startMinute)*60L;
  long end = NumMins(endHour, endMinute)*60L;
  long slopeLengthSecs = slopeLength*60L;

  // convert PWM inputs from percents to 12-bit int values.
  if (startPWM > 100)
     startPWM = 100;
  if (endPWM > 100)
     endPWM = 100;
  int startPWMint = map(startPWM, 0, 100, 0, 4095);
  int endPWMint = map(endPWM, 0, 100, 0, 4095);

  if (start > end) // Start is greater than End so it is over midnight
  {
    if (current_hour < endHour) start -= 1440L*60L; // past midnight
    if (current_hour >= startHour) end += 1440L*60L; // before midnight
  }
  long current = NumMins(current_hour, minute())*60L + second();
  if (slopeLengthSecs > ((end-start)/2) ) slopeLengthSecs = (end-start)/2; // don't allow a slope length greater than half the total period
  if (current <= start || current >= end) 
    return oldValue; // it's before the start or after the end, return the default
  else
  { // do the slope calculation
    int pwmDelta = endPWMint - startPWMint;
    float smoothPhase;
    if ((current > (start + slopeLengthSecs)) && (current < (end - slopeLengthSecs))) 
      return endPWMint; // if it's in the middle of the slope, return the high level
    else if ((current - start) < slopeLengthSecs) 
    {  // it's in the beginning slope up
      smoothPhase = (((float)(current-start)/(float)slopeLengthSecs)*180.0) + 180.0;
      //smoothPhase = constrain(map(current, start, start+slopeLengthSecs, 180, 360), 180, 360);
    }
    else if ((end - current) < slopeLengthSecs)
    { // it's in the end slope down
      smoothPhase = (((float)(current-start)/(float)slopeLengthSecs)*180.0);
      //smoothPhase = constrain(map(current, end-slopeLengthSecs, end, 0, 180), 0, 180);
    }
    return startPWMint + (int)(pwmDelta*((1.0+(cos(radians(smoothPhase))))/2.0));

  }
}
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

I'm using this http://nicegear.co.nz/electronics-gear/ ... e-pca9685/ which is 12 bit capable. Does it need to be coded differently or should it work 'out of the box'?
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

By that I mean, when writing the code for the lights do I simply substitute PWMSlope for PWMSmoothRampHighRes, leaving all my byte values in the brackets alone? This is what I did, and it didn't work. Will try again today and see what I get.
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

OK just tried it again. It looks like its half working, as in, it increments a lot faster than PWMSlope to make it smooth, but the increments are still 1% each not 1 bit of 4095. I hope that makes sense.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

You need to use something like this:

Code: Select all

ReefAngel.PWM.SetChannelRaw(Channel Number,12 bit value);
--Colin
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: PWMSmoothRampHighRes

Post by lnevo »

Yeah lets see what your code is.
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

Right, thank you. I thought there must be some other coding to do. So I do this for each channel and then code the dimming and timing as I was? Eg

Code: Select all

ReefAngel.PWM.SetChannel(0, PWMSmoothRampHighRes(13, 00, 22, 00, 0, 52, 120, 0));
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

Or would it be

Code: Select all

ReefAngel.PWM.SetChannelRaw(0, PMSmoothRampHighRes(13, 00, 22, 0, 2129, 120, 0));
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

Both wrong. You forgot the "Raw" on the first one, which is otherwise correct. :D

Code: Select all

ReefAngel.PWM.SetChannelRaw(0, PWMSmoothRampHighRes(13, 00, 22, 00, 0, 52, 120, 0));
0 to 52%, from 1300 to 2200, with a 120 minute ramp up and ramp down. It should return a range of 0 to ~2130.

--Colin
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

Awesome thanks! As you can tell, I'm pretty new to all this coding stuff. Really appreciate the help. In future, how's the best way to find out this stuff other than asking you guys? Is it in the libraries somewhere? Have had a look but can never find anything that makes sense to me.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

It's in the libraries. You just have to look at the functions and decode them as best you can. Some are better documented than others. You'll get better at it with time. :geek:
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

Cool, cheers for the help anyway!
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: PWMSmoothRampHighRes

Post by lnevo »

You can browse the libraries in a nice html form here:

www.easte.net/ra/html
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

Thanks Inevo, that's alot easier to read.
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

ok so i ran the code above today. Ramp up was good, apart from the 1st 3 or so steps you couldn't see the brightness stepping up, great! Come 9pm, I thought the tank still looked far too bright. Upon checking the controller I see all channels still at the end %. How come its not ramping down? I changed the sketch and swapped PWMSmoothRampHighRes for PWMSlopeHighRes and it seems to be working fine. Whats the difference between the 2?
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

I've used it for quite some time with no issues.

Post your entire code.

--Colin
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

Code: Select all

#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>

////// DON'T USE MEMORY LOCATION 199 - IT IS CORRUPT!
////// Place global variable code below here
#define Mem_B_LedOverride 100
#define Mem_B_Led100Percent 101

/////// Regular slope End%
#define Mem_B_SlopeEndCh0  259 
#define Mem_B_SlopeEndCh1  262
#define Mem_B_SlopeEndCh2  265
#define Mem_B_SlopeEndCh3  268


////// Place global variable code above here


void setup()
{
  // This must be the first line
  ReefAngel.Init();  //Initialize controller
  ReefAngel.SetTemperatureUnit( Celsius );  // set to Celsius Temperature

  ReefAngel.Use2014Screen();  // Let's use 2014 Screen 
  // Ports toggled in Feeding Mode
  ReefAngel.FeedingModePorts = Port3Bit | Port5Bit | Port6Bit | Port8Bit;
  // Ports toggled in Water Change Mode
  ReefAngel.WaterChangePorts = Port3Bit | Port5Bit | Port6Bit | Port7Bit | Port8Bit;
  // Ports toggled when Lights On / Off menu entry selected
  ReefAngel.LightsOnPorts = Port2Bit | Port4Bit;
  ReefAngel.LightsOnPortsE[0] = Port1Bit;
  // Ports turned off when Overheat temperature exceeded
  ReefAngel.OverheatShutoffPorts = Port7Bit;
  // Use T1 probe as temperature and overheat functions
  ReefAngel.TempProbe = T1_PROBE;
  ReefAngel.OverheatProbe = T1_PROBE;


  // Ports that are always on
  ReefAngel.Relay.On( Port6 );
  ReefAngel.Relay.On( Port8 );
  ReefAngel.Relay.On( Box1_Port8 );


  ////// Place additional initialization code below here

  InternalMemory.write(Mem_B_LedOverride, 0); //sets the controller to non masked LED mode upon boot. 
  InternalMemory.write(Mem_B_Led100Percent, 0);
  ////// Place additional initialization code above here
}

void loop()
{
  ReefAngel.ActinicLights( Port2 );
  ReefAngel.ActinicLights( Port4 );
  //ReefAngel.SingleATO( true,Port5,10,1 ); <----------------------------Untested Change---------------See ATO Delay 
  ReefAngel.StandardHeater( Port7 );    


  ////// Place your custom code below here

  ////// Delay ATO after Waterchange or Feeding Mode<---------------------------------------------UNTESTED!
  static time_t wcTimer;
  if ((ReefAngel.DisplayedMenu == FEEDING_MODE) || (ReefAngel.DisplayedMenu == WATERCHANGE_MODE)) wcTimer=now();
  if (now()-wcTimer > 0 && now()-wcTimer < 600) 
  {
    ReefAngel.Relay.Off(Port5);
  } 
  else if (bitRead(ReefAngel.Relay.RelayMaskOnE[0],2)) 
  {
    ReefAngel.Relay.Off(Port5);
  }  
  else 
  {
    ReefAngel.SingleATO( true,Port5,10,1 );
  }

  ////// Clear Overheat Flag after feeding or waterchange mode
  if (now()-wcTimer == 600)
  {
    if (ReefAngel.isOverheat())
    {
      if (ReefAngel.Params.Temp[T1_PROBE] <= 266)
      {
        ReefAngel.OverheatClear();
      }
    }
  }


  ////// Turn On LED Fan & PSU whenever any LEDs are on
  if (ReefAngel.PWM.GetChannelValue(0) > 0 || ReefAngel.PWM.GetChannelValue(1) > 0 || ReefAngel.PWM.GetChannelValue(2) > 0 || ReefAngel.PWM.GetChannelValue(3) > 0){
    ReefAngel.Relay.On(Port2);
    ReefAngel.Relay.On(Port4);
  }

  ////// ---------------Override PWM Light Channels--------------------

  // Custom Memory Location To Store Overide State for Regular Light End Values
  if (bitRead(ReefAngel.Relay.RelayMaskOnE[0],0)) { 
    if (InternalMemory.read(Mem_B_LedOverride)!=1){
      InternalMemory.write(Mem_B_LedOverride, 1);
    }  
  }
  else if (InternalMemory.read(Mem_B_LedOverride)!=0){
    InternalMemory.write(Mem_B_LedOverride, 0);
  }  

  // Custom Memory Location To Store Overide State for 100% Light values
  if (bitRead(ReefAngel.Relay.RelayMaskOnE[0],1)) { 
    if (InternalMemory.read(Mem_B_Led100Percent)!=1){
      InternalMemory.write(Mem_B_Led100Percent, 1);
    }  
  }
  else if (InternalMemory.read(Mem_B_Led100Percent)!=0){
    InternalMemory.write(Mem_B_Led100Percent, 0);
  }

  // Removes LED's from a Overridden State
  if ( InternalMemory.read(Mem_B_LedOverride) == 0){
    if (InternalMemory.read(Mem_B_Led100Percent) == 0)
    {
      /*
      ////////PWMSlopeHighRes Working
       ReefAngel.PWM.SetChannelRaw( 0, PWMSlopeHighRes(13,00,22,00,0,28,120,0)); //Set Channel 0 to PWMSlope using internal memory settings for Channel 0
       ReefAngel.PWM.SetChannelRaw( 1, PWMSlopeHighRes(13,00,22,00,0,23,120,0)); //Set Channel 1 to PWMSlope using internal memory settings for Channel 1
       ReefAngel.PWM.SetChannelRaw( 2, PWMSlopeHighRes(13,00,22,00,0,28,120,0)); //Set Channel 2 to PWMSlope using internal memory settings for Channel 2
       ReefAngel.PWM.SetChannelRaw( 3, PWMSlopeHighRes(13,00,22,00,0,32,120,0)); //Set Channel 3 to PWMSlope using internal memory settings for Channel 3
       */
       

       ReefAngel.PWM.SetChannelRaw( 0, PWMSmoothRampHighRes(13,00,22,00,0,28,120,0)); //Set Channel 0 to PWMSlope using internal memory settings for Channel 0
       ReefAngel.PWM.SetChannelRaw( 1, PWMSmoothRampHighRes(13,00,22,00,0,23,120,0)); //Set Channel 1 to PWMSlope using internal memory settings for Channel 1
       ReefAngel.PWM.SetChannelRaw( 2, PWMSmoothRampHighRes(13,00,22,00,0,28,120,0)); //Set Channel 2 to PWMSlope using internal memory settings for Channel 2
       ReefAngel.PWM.SetChannelRaw( 3, PWMSmoothRampHighRes(13,00,22,00,0,32,120,0)); //Set Channel 3 to PWMSlope using internal memory settings for Channel 3
      
    }
  }

  // Override LED's to End% Intensity for each Channel
  if (( InternalMemory.read(Mem_B_LedOverride) == 1) && (Mem_B_Led100Percent == 0 ))
  {
    ReefAngel.PWM.SetChannel( 0, Mem_B_SlopeEndCh0 ); //Set channel 0 to channel 0 end%
    ReefAngel.PWM.SetChannel( 1, Mem_B_SlopeEndCh1 ); //Set channel 1 to channel 1 end%
    ReefAngel.PWM.SetChannel( 2, Mem_B_SlopeEndCh2 ); //Set channel 2 to channel 2 end%
    ReefAngel.PWM.SetChannel( 3, Mem_B_SlopeEndCh3 ); //Set channel 3 to channel 3 end%
  }

  // Override LED's to 100% Intensity for each Channel
  if (Mem_B_Led100Percent == 1 )
  {
    ReefAngel.PWM.SetChannel( 0, 100 ); //Set channel 0 to channel 0 100%
    ReefAngel.PWM.SetChannel( 1, 100 ); //Set channel 1 to channel 1 100%
    ReefAngel.PWM.SetChannel( 2, 100 ); //Set channel 2 to channel 2 100%
    ReefAngel.PWM.SetChannel( 3, 100 ); //Set channel 3 to channel 3 100%
  }


  ////// Prevent Filling ATO past float switch even if overridden
  if (bitRead(ReefAngel.Relay.RelayMaskOn,4)){
    if (!ReefAngel.LowATO.IsActive()){
      ReefAngel.Relay.Off(Port5);
      bitClear(ReefAngel.Relay.RelayMaskOn,4);
    }
  }

  ////// Override Float Switch for Waterchange Drum
  if (bitRead(ReefAngel.Relay.RelayMaskOnE[0],3)) {
    ReefAngel.Relay.On(Port1); 
  }

  else { 
    ReefAngel.Relay.Off(Port1);  
  }


  /////// Refill (Salt Water) after water change to ATO height Relay Port 1 
  if (ReefAngel.DisplayedMenu != WATERCHANGE_MODE){
    if (bitRead(ReefAngel.Relay.RelayMaskOn,0)){
      if (!ReefAngel.LowATO.IsActive()){
        ReefAngel.Relay.Off(Port1);
        bitClear(ReefAngel.Relay.RelayMaskOn,0);
      }
    }
  }

  ////// Place your custom code above here

  // This should always be the last line
  ReefAngel.Portal( "tanked_kiwi" );
  ReefAngel.ShowInterface();
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

I take that back. I'm not using SmoothRamp. I'll try it and report back.

--Colin
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

So I've had this running for several days. It's unpredictable. Some days the whites would dim really fast at the end of the cycle. Last night they were at about half brightness near the end and then instantly 0. Not sure why.

I'm going back to PWMSlopeHighRes instead.

--Colin
AlanM
Posts: 263
Joined: Wed Jan 01, 2014 7:26 am

Re: PWMSmoothRampHighRes

Post by AlanM »

cosmith71 wrote:So I've had this running for several days. It's unpredictable. Some days the whites would dim really fast at the end of the cycle. Last night they were at about half brightness near the end and then instantly 0. Not sure why.

I'm going back to PWMSlopeHighRes instead.

--Colin
Colin, what code were you using on the PWMSmoothRampHighRes calls? Can you post up a snippet? I have a unit that I can run tests on and would like to try to see what's going on with it.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

Something like this:

Code: Select all

    ReefAngel.PWM.SetChannelRaw(0,PWMSmoothRampHighRes(9,30,22,30,0,70,60,0));
AlanM
Posts: 263
Joined: Wed Jan 01, 2014 7:26 am

Re: PWMSmoothRampHighRes

Post by AlanM »

OK. So you have that in your loop without any other time-based if statements around it that might be changing when the profile starts or stops?
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

Yup.

What shape is SmoothRamp? Is it a parabolic beginning and end?
AlanM
Posts: 263
Joined: Wed Jan 01, 2014 7:26 am

Re: PWMSmoothRampHighRes

Post by AlanM »

cosmith71 wrote:Yup.

What shape is SmoothRamp? Is it a parabolic beginning and end?
Actually, it's intended to be flat in the middle with a half-period of a Cosine function at the beginning and the end which is shifted up and divided by 2 so that it goes from 0 to 1 instead of from -1 to 1. The intent is to have a tail at the beginning of the day and the end of the day rather than an immediate slope upwards in the morning.

I did it that way because I can really see the difference between 1 and 5 in dimming levels when my meanwell LDDs are really dim, but it's impossible to see the difference between 2001 and 2005 in the middle of the ramp.

I actually like the sigmoid ones better than smoothramp because the tails are longer. That's what I run on my lights.

I'm using internal memory for my lights final intensities and start and end times, but I do:

Code: Select all

  ReefAngel.PWM.SIXTEENChannelPWMSigmoid(2,0,InternalMemory.PWMSlopeEnd0_read()); // RB channel, startpwm, endpwm, offsets
Where my Royal Blue channel goes from 0 to the slope end value on 16 channel dimming module channel 2.
AlanM
Posts: 263
Joined: Wed Jan 01, 2014 7:26 am

Re: PWMSmoothRampHighRes

Post by AlanM »

Colin,

I described SmoothRamp and Sigmoid with graphs here (at least what they're supposed to do):

http://forum.reefangel.com/viewtopic.php?f=7&t=4812

And you can see what it looks like actually running on my lights here:

http://forum.reefangel.com/status/chart ... er=scpwme2
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: PWMSmoothRampHighRes

Post by cosmith71 »

I'm going to run it again tonight and pay closer attention to see what it does. I'll look at the graph, too.

--Colin
tanked_kiwi
Posts: 37
Joined: Thu May 22, 2014 3:25 am

Re: PWMSmoothRampHighRes

Post by tanked_kiwi »

Thank you both for looking into this. AlanM, I have the same issue you do with the meanwell LDD drivers, that is the whole reason I went looking at the high res and different slopes. Will try sigmoid and see how I get on.
Post Reply