Custom Internal Memory for PWM Slope w/ Expansion Module

Expansion modules and attachments
Post Reply
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

I've been talking with Roberto about finding a way to adjust my PWM values "on the fly" via the Android app when using the PWM Expansion Module. He informed me that it can be done, but will need custom coding that requires creating custom internal memory locations to be able to do this. He asked me to create a new thread to get some discussion going and see how it can be done.

To begin with, this is a copy of my current ino file: (It's a bit unorganized because I borrowed bits and pieces from others on the forum to get the functions I wanted, but everything seems to work fine except I can't change the PWM value of the slope via Android app.)

Code: Select all

// Autogenerated file by RAGen (v1.2.1.158), (02/21/2012 22:03)
// RA_022112_2203.ino
//
// This version designed for v0.9.0 or later

/* The following features are enabled for this File: 
#define DirectTempSensor
#define DisplayLEDPWM
#define wifi
#define SaveRelayState
#define RelayExp
#define InstalledRelayExpansionModules 1
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 3
#define PWMEXPANSION
#define CUSTOM_MAIN
#define RFEXPANSION
*/

#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 <RF.h>
#include <ReefAngel.h>
//**************************************************************************************************************
// These are the mode numbers for the RF Expansion Module
//#define Constant      0
//#define Random1       1 // Lagoonal
//#define Random2       2 // Reef Crest
//#define ShortWave     3
//#define LongWave      4
//#define Smart_NTM     5 // Nutrient Transport Mode
//#define Smart_TSM     6 // Tidal Swell Mode
//#define Feeding_Start 7
//#define Feeding_Stop  8
//#define Night         9
//#define Slave_Start   97
//#define Slave_Stop    98
//#define None          99
//**************************************************************************************************************
//Start of PWM Expansion Code Header

// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5

// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};

//End of PWM Expansion Code Header
//*************************************************************************************************************
//boolean ForceCloud=false;

prog_char menu1_label[] PROGMEM = "Feeding Mode";
prog_char menu2_label[] PROGMEM = "Water Change Mode";
prog_char menu3_label[] PROGMEM = "Clear ATO Timeout";
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label};

void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ReefAngel.ATOClear();
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}

#include <avr/pgmspace.h>

//***********************************************************************************************************************
//-------------------------------------Custom Main for PWM Expansion Module----------------------------------------------
byte x,y;
char text[10];

void DrawCustomMain()
{
  // the graph is drawn/updated when we exit the main menu &
  // when the parameters are saved
  ReefAngel.LCD.Clear(BtnActiveColor,5,0,127,11);
  ReefAngel.LCD.DrawText(DefaultBGColor,BtnActiveColor,15,3,"George's 75G Reef");
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  ReefAngel.LCD.DrawMonitor(15, 20, ReefAngel.Params,
  ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  pingSerial();
  ReefAngel.LCD.Clear(DefaultFGColor,5,52,127,52);
  ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,30,55,"PWM Expansion");
  x=15;
  y=68;
  for (int a=0;a<6;a++)
  {
    if (a>2) x=75;
    if (a==3) y=68;
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x,y,"Ch :");
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+12,y,a);
    ConvertNumToString(text, ReefAngel.PWM.GetChannelValue(a), 1);
    strcat(text,"  ");
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+24,y,text);
    y+=10;
  }
  pingSerial();
    // Display Main Relay Box
    byte TempRelay = ReefAngel.Relay.RelayData;
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;
    ReefAngel.LCD.DrawOutletBox(13, 97, TempRelay);
    pingSerial();

    // Display Expansion Relay Box 1
    TempRelay = ReefAngel.Relay.RelayDataE[0];
    TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
    TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
    ReefAngel.LCD.DrawOutletBox(13, 109, TempRelay);
    pingSerial();
}

void DrawCustomGraph()
{
}


void setup()
{
    ReefAngel.Init();  //Initialize controller
    ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));

    ReefAngel.FeedingModePorts =         B10000001;
    ReefAngel.WaterChangePorts =         B11100001;
    ReefAngel.OverheatShutoffPortsE[0] = B00001111;
    ReefAngel.LightsOnPortsE[0] =        B00001111;

    // Ports that are always on
    ReefAngel.Relay.On(Port1);
    ReefAngel.Relay.On(Port3);
    ReefAngel.Relay.On(Port5);
    ReefAngel.Relay.On(Port6);
    ReefAngel.Relay.On(Port7);
    ReefAngel.Relay.On(Port8);
    ReefAngel.Relay.On(Box1_Port7);
    ReefAngel.Relay.On(Box1_Port8);
//********************************************************************************************************************
//RF Module Setup
  ReefAngel.RF.SetMode(Slave_Start,0,0);
  /*
  
  If you get a compile error similar to this:
  'class ReefAngelClass' has no member named 'RF'
  Please make sure that you enabled RF Expansion on your features file.
  
  Open RAGen and make sure you have RF Expansion checked under the Features tab.

  Or, you can manually edit the file.
  The file is located at "Documents\Arduino\libraries\ReefAngel_Features.h" file and has to include this line in it:
  #define RFEXPANSION  
  
  */
  
  InternalMemory.RFMode_write(0);
  InternalMemory.RFSpeed_write(128);
  InternalMemory.RFDuration_write(10);
//********************************************************************************************************************  
}

void loop()
{
    // Specific functions
    ReefAngel.StandardLights(Box1_Port1); //Left Blue LEDs
    ReefAngel.StandardLights(Box1_Port2); //Right Blue LEDs
    ReefAngel.MHLights(Box1_Port3); //Left White LEDs
    ReefAngel.MHLights(Box1_Port4); //Right White LEDs
 
    ReefAngel.StandardHeater(Port2);
    ReefAngel.MoonLights(Box1_Port5); //Left Moonlight
    ReefAngel.MoonLights(Box1_Port6); //Right Moonlight
    ReefAngel.MoonLights(Port4); //Fuge light on when main lights are out
    ReefAngel.Portal("tanksnstuff");
    
//    ReefAngel.Relay.Set(Port4, (ReefAngel.StandardLights!=true));  //Need to find way to make fuge light come one when Actinics are off.
//*********************************************************************************************************************************
//Start of PWM Expansion Code for Slope
PWMChannel[LEDPWM0]=PWMSlope(8,0,22,0,10,50,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(8,0,22,0,10,50,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(10,0,20,30,10,50,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(10,0,20,30,10,50,75,PWMChannel[LEDPWM3]);

// The lines above are what calculates the slope.
// You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
// The are as follow:
// 1st parameter: hour to start slope
// 2nd parameter: minute to start slope
// 3rd parameter: hour to end slope
// 4th parameter: minute to end slope
// 5th parameter: % of the PWM signal to start slope
// 6th parameter: % of the PWM signal to end slope
// 7th parameter: duration of slope in minutes
// 8th parameter: always the same as the variable before the PWMSlope() call

//PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);

// In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
// Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
// Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
//CheckCloud();
ReefAngel.PWM.Expansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
ReefAngel.PWM.Expansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
ReefAngel.PWM.Expansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
ReefAngel.PWM.Expansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
//End of PWM Expansion Code for Slope
//*********************************************************************************************************************************
    ReefAngel.ShowInterface();
}

Here's my internal memory file I originally uploaded: ( I've changed a few of these via Android App since, so can't guarantee the values are the same right now.)

Code: Select all

// Autogenerated file by RAGen (v1.2.1.158), (02/19/2012 15:48)
// Memory_021912_1548.ino
//
// This file sets the default values to the Internal Memory
//


#include <ReefAngel_Features.h>
#include <Globals.h>
#include <Time.h>
#include <OneWire.h>
#include <RA_NokiaLCD.h>
#include <avr/pgmspace.h>
#include <InternalEEPROM.h>
#include <Wire.h>
#include <Memory.h>


RA_NokiaLCD e;

void setup()
{
    e.Init();
    e.Clear(COLOR_WHITE,0,0,132,132);
    e.BacklightOn();

    InternalMemory.MHOnHour_write(10);
    InternalMemory.MHOnMinute_write(0);
    InternalMemory.MHOffHour_write(20);
    InternalMemory.MHOffMinute_write(30);
    InternalMemory.MHDelay_write(5);
    InternalMemory.StdLightsOnHour_write(8);
    InternalMemory.StdLightsOnMinute_write(0);
    InternalMemory.StdLightsOffHour_write(22);
    InternalMemory.StdLightsOffMinute_write(0);
    InternalMemory.DP1OnHour_write(20);
    InternalMemory.DP1OnMinute_write(0);
    InternalMemory.DP2OnHour_write(22);
    InternalMemory.DP2OnMinute_write(30);
    InternalMemory.DP1Timer_write(0);
    InternalMemory.DP2Timer_write(0);
    InternalMemory.DP1RepeatInterval_write(60);
    InternalMemory.DP2RepeatInterval_write(60);
    InternalMemory.ATOTimeout_write(60);
    InternalMemory.ATOHighTimeout_write(60);
    InternalMemory.ATOHourInterval_write(0);
    InternalMemory.ATOHighHourInterval_write(0);
    InternalMemory.FeedingTimer_write(900);
    InternalMemory.LCDTimer_write(600);
    InternalMemory.LEDPWMActinic_write(0);
    InternalMemory.LEDPWMDaylight_write(0);
    InternalMemory.WM1Timer_write(0);
    InternalMemory.WM2Timer_write(354);
    InternalMemory.HeaterTempOn_write(780);
    InternalMemory.HeaterTempOff_write(791);
    InternalMemory.ChillerTempOn_write(810);
    InternalMemory.ChillerTempOff_write(785);
    InternalMemory.OverheatTemp_write(1500);
    InternalMemory.PHMax_write(840);
    InternalMemory.PHMin_write(550);
    InternalMemory.SalMax_write(2550);
    InternalMemory.RFMode_write(Constant);
    InternalMemory.RFSpeed_write(140);
    InternalMemory.RFDuration_write(8);
    InternalMemory.RFDuration_write(8);
    InternalMemory.PWMSlopeStartD_write(10);
    InternalMemory.PWMSlopeEndD_write(128);
    InternalMemory.PWMSlopeDurationD_write(60);
    InternalMemory.PWMSlopeStartA_write(10);
    InternalMemory.PWMSlopeEndA_write(128);
    InternalMemory.PWMSlopeDurationA_write(60);
    InternalMemory.IMCheck_write(0x5241494D);
}

void loop()
{
    // display success screen
    e.DrawText(COLOR_BLACK, COLOR_WHITE, MENU_START_COL, MENU_START_ROW*2, "Internal Memory Set");
    e.DrawText(COLOR_BLACK, COLOR_WHITE, MENU_START_COL, MENU_START_ROW*4, "Now load your");
    e.DrawText(COLOR_BLACK, COLOR_WHITE, MENU_START_COL, MENU_START_ROW*5, "   RA code file");
    delay(5000);
}
Not sure it's needed for this, but just in case, here's my Features file too:

Code: Select all

// AutoGenerated file by RAGen (v1.2.1.158), (02/22/2012 01:14)

/*
 * Copyright 2010-12 Curt Binder
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef __REEFANGEL_FEATURES_H__
#define __REEFANGEL_FEATURES_H__


#define DirectTempSensor
#define DisplayLEDPWM
#define wifi
#define SaveRelayState
#define RelayExp
#define InstalledRelayExpansionModules 1
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 3
#define PWMEXPANSION
#define CUSTOM_MAIN
#define RFEXPANSION


#endif  // __REEFANGEL_FEATURES_H__
OK, now that you should have enough info about my files, lets get to it. I know the android app gives the ability to change internal memory for the "PMW Slope Daylight End %" and "PWM Slope Actinic End %", which would do what I want if I was only using the 2 channels on the main relay box. However, changing these memory locations doesn't do anything to the 6 PWM Expansion channels for the slope (granted, I'm only using channels 0-3 at the moment). I'm able to hard code the max % of the slope with these lines added into my .ino (the 6th data field in parenthesis, 50 in each case, is the "Max %" or "End %" of the slope):

Code: Select all

PWMChannel[LEDPWM0]=PWMSlope(8,0,22,0,10,50,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(8,0,22,0,10,50,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(10,0,20,30,10,50,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(10,0,20,30,10,50,75,PWMChannel[LEDPWM3]);
But, in order to adjust any of those data values, I currently have to manually change them in my .ino and then re-upload to the controller. So, I'm likely going to need to be able to add some custom memory locations for those values, and then possibly add them via the "custom memory location" option on the android app. I'm not sure if there's a max number that can be created with that or not either, so this may involve having Curt add this feature into the app at some point too.

I'm really looking to temporarily adjust the "current" PWM % for each channel I'm using (override the slope's current %)... so I can find a color combination I'm happy with for the "MAX %" to be used during the slope. Once I find a combination of whites/blues that I'm happy with, I can just set the 4 PMWChannel slopes as I am already doing, and then leave it alone. Would be nice to manually change the "current" value of any of them via the android app though... just as people using the 2 standard PWM channels can.

So, any ideas on what I need to do to have this feature?

I just ordered the RA+ board by the way, so my .ino code length shouldn't be an issue in the very near future. :ugeek: Any help would be greatly appreciated.
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by binder »

Regarding the memory locations...

What I can do is simply add in the same memory locations as we did for the Actinic and Daylight channels. I'll add in 3 locations per channel on the PWM Expansion board. That way each channel can have a Start, End, Duration that is customizable.
Here's what the locations will be (in the next release of the libraries of course):

Code: Select all

#define Mem_B_PWMSlopeStart0      VarsStart+58
#define Mem_B_PWMSlopeEnd0	      VarsStart+59
#define Mem_B_PWMSlopeDuration0   VarsStart+60
#define Mem_B_PWMSlopeStart1      VarsStart+61
#define Mem_B_PWMSlopeEnd1	      VarsStart+62
#define Mem_B_PWMSlopeDuration1   VarsStart+63
#define Mem_B_PWMSlopeStart2      VarsStart+64
#define Mem_B_PWMSlopeEnd2	      VarsStart+65
#define Mem_B_PWMSlopeDuration2   VarsStart+66
#define Mem_B_PWMSlopeStart3      VarsStart+67
#define Mem_B_PWMSlopeEnd3	      VarsStart+68
#define Mem_B_PWMSlopeDuration3   VarsStart+69
#define Mem_B_PWMSlopeStart4      VarsStart+70
#define Mem_B_PWMSlopeEnd4	      VarsStart+71
#define Mem_B_PWMSlopeDuration4   VarsStart+72
#define Mem_B_PWMSlopeStart5      VarsStart+73
#define Mem_B_PWMSlopeEnd5	      VarsStart+74
#define Mem_B_PWMSlopeDuration5   VarsStart+75
This just means that I will start to use location 858 for the pwm slope expansion stuff. Also, with the above code, the variable VarsStart is 800. Hopefully you should be able to figure that one out. Then I'll add these same things to the Android app and push out a release (hopefully soon).

So for your code, I took the liberty of adapting it to work using those locations. I did NOT put in the value for the duration. I just did the start and end slope percentages.

Code: Select all

PWMChannel[LEDPWM0]=PWMSlope(8,0,22,0,
		InternalMemory.read(858),  // start %
		InternalMemory.read(859),  // end %
		60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(8,0,22,0,
		InternalMemory.read(861),  // start %
		InternalMemory.read(862),  // end %
		60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(10,0,20,30,
		InternalMemory.read(864),  // start %
		InternalMemory.read(865),  // end %
		75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(10,0,20,30,
		InternalMemory.read(867),  // start %
		InternalMemory.read(868),  // end %
		75,PWMChannel[LEDPWM3]);
It's not "easily readable" but it will work. Make sure that you SET those locations FIRST before you upload this code in your INO file. Otherwise you will get undesirable results (I'm sure you already know this but wanted to spell it out just in case and for everybody else too).
If you want to change the duration of the slope as well, that can be easily added to your INO file (but I didn't, like I said).

I'm not quite sure about changing the "current" value of the PWM channels on the expansion device. I'll have to think a little more about it and see what else you and Roberto come up with on ideas.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

Thanks Curt! It's going to take a few days to get my RA+board so I'll have some time to get this all Thanksgiving's out.

When you say SET those locations first, do you mean use the Custom Location option in the android app or do I need to create a new internal memory file, add them manually, then upload to the controller?
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by binder »

TanksNStuff wrote: When you say SET those locations first, do you mean use the Custom Location option in the android app or do I need to create a new internal memory file, add them manually, then upload to the controller?
Either. Since you already have the controller up and running, you might as well just use the android app and set them.....unless you really want to reload the internal memory file.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

First off Curt, I forgot to mention you don't have to apologise for stating the obvious. I have a basic understanding of this stuff and even though I may sound like I know what I'm talking about... I'm a newb and need all the details spelled out for me right now, lol.

OK, I'll add them via Android app then. I wasn't sure if there was a limitation on how many you could add that way (I thought I read somewhere that you could only add 2 with that, but maybe I was mistaken.)

Just to be sure I'm doing that part right, the first Custom Location I make would be:
Location: 858 (I didn't see a field to name the memory location... how do I label it for the dropdown?)
Type: Byte
Value: (whatever % I want that channel to start with, from 1-100... or is this 0-255?)

Also, I don't want to make this more complicated than it needs to be... but do you think we should change the memory location names to PWMExpSlopeStart0 instead of PWMSlopeStart0? I don't want the people using the standard channels getting confused and choosing the wrong memory location and the "Exp" part should help differentiate between them. I'll understand it either way, but just trying to prevent issues with the masses later on.

Next question...
Will I also need to add all the #defines (you showed me above) into the globals.h file, underneath :

Code: Select all

#define Mem_B_RFDuration		  VarsStart+57
and change the "next value" comment to be VarsStart+76 ? I'm thinking I'd need all that in there to make the code you gave me work and if you're going to add it in next release anyway then it won't mess anything up when I update the libraries.

Last question...
You mentioned that you didn't put in the value for the duration in the code you gave me, and I understand that you just used:

Code: Select all

      60,PWMChannel[LEDPWM0]);
to show the duration (as an integer) and then the channel.

If I were to also use these new memory locations to control the duration manaully (android app) too, then the code for the first channel would be like this right?:

Code: Select all

PWMChannel[LEDPWM0]=PWMSlope(8,0,22,0,
      InternalMemory.read(858),  // start %
      InternalMemory.read(859),  // end %
      InternalMemory.read(860),  // duration
      PWMChannel[LEDPWM0]);
In fact, I could also add the start hour, start minute, end hour, end minute in by using InternalMemory.read(###) for each instead of the (8,0,22,0 if I wanted too also?

Not sure if I would need those, but just seeing if I'm understanding how it works and if it's possible.

That's it for now. Thanks in advance Curt.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by rimai »

No need to add anything to globals.h.
You can use this and use the same StandardLights schedule:

Code: Select all

PWMChannel[LEDPWM0]=PWMSlope(
      InternalMemory.StdLightsOnHour_read(),
      InternalMemory.StdLightsOnMinute_read(),
      InternalMemory.StdLightsOffHour_read(),
      InternalMemory.StdLightsOffMinute_read(),
      InternalMemory.read(858),  // start %
      InternalMemory.read(859),  // end %
      InternalMemory.read(860),  // duration
      PWMChannel[LEDPWM0]);
Roberto.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

Ah, so I'd just be using the StdLights memory locations for the 2 blue channels, then the MHLights memory locations for the 2 white channels? I think that's the best way to go because that would force me to automatically start my slope the same time the outlets get energized. I like that idea Roberto!

If this works, then couldn't I also just use the PWM Slope Actinic Start % location (852) as my start % for both actinics, PWM Slope Actinic End % (853) as my end %, etc.... like this:

Code: Select all

PWMChannel[LEDPWM0]=PWMSlope(
      InternalMemory.StdLightsOnHour_read(),
      InternalMemory.StdLightsOnMinute_read(),
      InternalMemory.StdLightsOffHour_read(),
      InternalMemory.StdLightsOffMinute_read(),
      InternalMemory.read(852),  // start %
      InternalMemory.read(853),  // end %
      InternalMemory.read(854),  // duration
      PWMChannel[LEDPWM0]);
      
      PWMChannel[LEDPWM1]=PWMSlope(
      InternalMemory.StdLightsOnHour_read(),
      InternalMemory.StdLightsOnMinute_read(),
      InternalMemory.StdLightsOffHour_read(),
      InternalMemory.StdLightsOffMinute_read(),
      InternalMemory.read(852),  // start %
      InternalMemory.read(853),  // end %
      InternalMemory.read(854),  // duration
      PWMChannel[LEDPWM1]);

      PWMChannel[LEDPWM2]=PWMSlope(
      InternalMemory.MHOnHour_read(),
      InternalMemory.MHOnMinute_read(),
      InternalMemory.MHOffHour_read(),
      InternalMemory.MHOffMinute_read(),
      InternalMemory.read(849),  // start %
      InternalMemory.read(850),  // end %
      InternalMemory.read(851),  // duration
      PWMChannel[LEDPWM2]);

      PWMChannel[LEDPWM3]=PWMSlope(
      InternalMemory.MHOnHour_read(),
      InternalMemory.MHOnMinute_read(),
      InternalMemory.MHOffHour_read(),
      InternalMemory.MHOffMinute_read(),
      InternalMemory.read(849),  // start %
      InternalMemory.read(850),  // end %
      InternalMemory.read(851),  // duration
      PWMChannel[LEDPWM3]);
This would probably work without having to create the new memory locations that Curt suggested... it would just require changing the slope coding in my .ino (just like I posted here) and then putting the values into the appropriate locations with the android app. Might save Curt some work anyway. ;)

I doubt I'll have the memory space available to change the coding (until I get the RA+ board), but if I do, I'll test it out tonight. Maybe I'll temporarily comment out some of the custom main stuff to see if I can squeeze it in to test.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by rimai »

Instead of repeating the same calculation, because they are just the same, you can use this:

Code: Select all

PWMChannel[LEDPWM0]=PWMSlope(
      InternalMemory.StdLightsOnHour_read(),
      InternalMemory.StdLightsOnMinute_read(),
      InternalMemory.StdLightsOffHour_read(),
      InternalMemory.StdLightsOffMinute_read(),
      InternalMemory.read(852),  // start %
      InternalMemory.read(853),  // end %
      InternalMemory.read(854),  // duration
      PWMChannel[LEDPWM0]);
      
PWMChannel[LEDPWM1]=PWMChannel[LEDPWM0];

PWMChannel[LEDPWM2]=PWMSlope(
      InternalMemory.MHOnHour_read(),
      InternalMemory.MHOnMinute_read(),
      InternalMemory.MHOffHour_read(),
      InternalMemory.MHOffMinute_read(),
      InternalMemory.read(849),  // start %
      InternalMemory.read(850),  // end %
      InternalMemory.read(851),  // duration
      PWMChannel[LEDPWM2]);

PWMChannel[LEDPWM3]=PWMChannel[LEDPWM2];
Roberto.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

Ahh, that makes it simpler and cleaner for sure.

I guess the only downside to doing it all this way would be if I want to add cloud/storm effects at some point, or if I wanted to stagger the slope start times or something silly like that? No need to explain how that would work as I'm not interested in that at the moment. Maybe once I get the RA+ and add all

Thanks for the help guys!
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

Roberto... you are a genius my friend! I used the last section of code you posted in lieu of what I originally had (in my first post this thread) and it not only fit size-wise but also worked as intended!

After switching that around, I was able to use the original PWM Slope Start %, End %, and Duration memory locations to change my settings on the fly via the Android App.

Curt, there really is no need for you to add any of those extra memory locations now (for me at least) since I just needed to get creative with my coding to have the same effect.

I do have another minor issue that one of you can probably help me fix easily...

On my Custom Main screen, my PMW channel values are being displayed as 0-255 instead of % (0-100).

My code is in my original post this thread, but here's the part that displays these values:

Code: Select all

byte x,y;
char text[10];

void DrawCustomMain()
{
  // the graph is drawn/updated when we exit the main menu &
  // when the parameters are saved
  ReefAngel.LCD.Clear(BtnActiveColor,5,0,127,11);
  ReefAngel.LCD.DrawText(DefaultBGColor,BtnActiveColor,15,3,"George's 75G Reef");
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  ReefAngel.LCD.DrawMonitor(15, 20, ReefAngel.Params,
  ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  pingSerial();
  ReefAngel.LCD.Clear(DefaultFGColor,5,52,127,52);
  ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,30,55,"PWM Expansion");
  x=15;
  y=68;
  for (int a=0;a<6;a++)
  {
    if (a>2) x=75;
    if (a==3) y=68;
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x,y,"Ch :");
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+12,y,a);
    ConvertNumToString(text, ReefAngel.PWM.GetChannelValue(a), 1);
    strcat(text,"  ");
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+24,y,text);
    y+=10;
  }
I just copied that straight from the Example Code "CustomMainScreen_PWMExpansion" so I'm not sure exactly how it works... nor how to fix it to display a % instead. Any ideas? Is there an easier way to display this? I'd be even happier if it just showed the channels I'm using (0-3).
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by binder »

Like Roberto said, you won't have to add anything to your Globals.h file. Those locations are not needed to be in there. They are just a simple / easy way to refer to them for other aspects (so you don't have to always put in a numeric value AND if the memory locations were ever changed in the future it would be really simple and would not require a lot of code changes).

I'm still going to keep the memory locations for the PWM slope values for the expansion box because they are needed. I've already added them into the libraries but not released them yet. I'm also going to be adding them to the Android App too. So they will be in the list and easy to pick. It's not a tough thing to do, so it will be simple.
You were correct, the memory location is a Byte value and can be between 0 and 255 but the value that makes the most sense is 0-100. I'm hoping to get this done tomorrow and possibly have an update on Wednesday.

So feel free to use whatever locations you want for the slope percentages.

As for your percentages, you have to convert it to % from 255. Give this code a try:

Code: Select all

byte x,y;
char text[10];
int v;

void DrawCustomMain()
{
  // the graph is drawn/updated when we exit the main menu &
  // when the parameters are saved
  ReefAngel.LCD.Clear(BtnActiveColor,5,0,127,11);
  ReefAngel.LCD.DrawText(DefaultBGColor,BtnActiveColor,15,3,"George's 75G Reef");
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  ReefAngel.LCD.DrawMonitor(15, 20, ReefAngel.Params,
  ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  pingSerial();
  ReefAngel.LCD.Clear(DefaultFGColor,5,52,127,52);
  ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,30,55,"PWM Expansion");
  x=15;
  y=68;
  for (int a=0;a<6;a++)
  {
    if (a>2) x=75;
    if (a==3) y=68;
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x,y,"Ch :");
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+12,y,a);
    v = int(ReefAngel.PWM.GetChannelValue(a)/2.55);
    ConvertNumToString(text, v, 1);
    strcat(text,"  ");
    ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+24,y,text);
    y+=10;
  }
}
That adds a variable v and then converts v to the percentage (0-100) and then displays it on the screen.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

Thanks Curt. I'm at work right now so I'll have to try that code out tonight.

As for adding the new memory locations anyway, I guess that couldn't hurt if it's a simple thing to do. It will help when trying to have different start/stop/durations for each channel if you wanted (like if you had a separate fixture on a QT tank that you wanted to run on a different cycle than you main tank.)
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by binder »

TanksNStuff wrote:Thanks Curt. I'm at work right now so I'll have to try that code out tonight.

As for adding the new memory locations anyway, I guess that couldn't hurt if it's a simple thing to do. It will help when trying to have different start/stop/durations for each channel if you wanted (like if you had a separate fixture on a QT tank that you wanted to run on a different cycle than you main tank.)
Yep, that's exactly what I was thinking. I might as well add it in because if I don't, somebody will inevitably want it in the future. Plus it needs to be in there anyways for complete customization (which is something EVERYBODY on here loves, myself included) :ugeek:
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

Plus it needs to be in there anyways for complete customization (which is something EVERYBODY on here loves, myself included)
Yea, that's the main reason I decided to buy this controller too. If something isn't possible, you just add stuff yourself (or get you or Roberto to add it) to make it possible! ;)
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

Curt, that code did the trick. There were a few minor issues with the display being 1% lower than what I set my PWM % to... but that might be a rounding issue or something.

For instance, when I set my End % to 50, the controller displays 49; when I changed it to 51, it showed 50; when I changed it to 100, it displayed as 100; when I tried 80, it showed 80. It's not a big deal because with the PWM slope being used it's going to show weird numbers anyway.
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by binder »

yes, it is a rounding issue. that code simply takes the whole integer of the division. if you want to round handle rounding, you would need to do something like this:

Code: Select all

/// ... other declarations
int r;

void DrawCustomMain()
{
    // ... other code
    v = int(ReefAngel.PWM.GetChannelValue(a)/2.55);
    // take the remainder 
    r = int(ReefAngel.PWM.GetChannelValue(a)%2.55);
    if ( r >= 5 ) v++;
    // ... rest of code
}
it will take some tweaking to get it to work properly or it may work without any problems. i haven't tested it so i don't know.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Custom Internal Memory for PWM Slope w/ Expansion Module

Post by TanksNStuff »

I can live with it being 1% off occasionally. :lol:
Post Reply