PWMSmoothRampHighRes
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
PWMSmoothRampHighRes
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.
Re: PWMSmoothRampHighRes
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.
Re: PWMSmoothRampHighRes
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.
Re: PWMSmoothRampHighRes
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));
}
}
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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'?
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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.
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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.
Re: PWMSmoothRampHighRes
You need to use something like this:
--Colin
Code: Select all
ReefAngel.PWM.SetChannelRaw(Channel Number,12 bit value);
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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));
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
Or would it be
Code: Select all
ReefAngel.PWM.SetChannelRaw(0, PMSmoothRampHighRes(13, 00, 22, 0, 2129, 120, 0));
Re: PWMSmoothRampHighRes
Both wrong. You forgot the "Raw" on the first one, which is otherwise correct. 
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

Code: Select all
ReefAngel.PWM.SetChannelRaw(0, PWMSmoothRampHighRes(13, 00, 22, 00, 0, 52, 120, 0));
--Colin
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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.
Re: PWMSmoothRampHighRes
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. 

-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
Cool, cheers for the help anyway!
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
Thanks Inevo, that's alot easier to read.
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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?
Re: PWMSmoothRampHighRes
I've used it for quite some time with no issues.
Post your entire code.
--Colin
Post your entire code.
--Colin
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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();
Re: PWMSmoothRampHighRes
I take that back. I'm not using SmoothRamp. I'll try it and report back.
--Colin
--Colin
Re: PWMSmoothRampHighRes
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
I'm going back to PWMSlopeHighRes instead.
--Colin
Re: PWMSmoothRampHighRes
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.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
Re: PWMSmoothRampHighRes
Something like this:
Code: Select all
ReefAngel.PWM.SetChannelRaw(0,PWMSmoothRampHighRes(9,30,22,30,0,70,60,0));
Re: PWMSmoothRampHighRes
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?
Re: PWMSmoothRampHighRes
Yup.
What shape is SmoothRamp? Is it a parabolic beginning and end?
What shape is SmoothRamp? Is it a parabolic beginning and end?
Re: PWMSmoothRampHighRes
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.cosmith71 wrote:Yup.
What shape is SmoothRamp? Is it a parabolic beginning and end?
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
Re: PWMSmoothRampHighRes
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
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
Re: PWMSmoothRampHighRes
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
--Colin
-
- Posts: 37
- Joined: Thu May 22, 2014 3:25 am
Re: PWMSmoothRampHighRes
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.