Reef Central Online Community

Go Back   Reef Central Online Community > General Interest Forums > Do It Yourself
Blogs FAQ Calendar

Notices

User Tag List

Reply
Thread Tools
Unread 12/07/2011, 11:57 AM   #826
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Quote:
Originally Posted by der_wille_zur_macht View Post
Then I'm assuming SPLC780D is HD44780 compatible. Good to know. I am surprised they don't come out and say that, since the HD44780 seems to be the name people recognize.

I have a TC1604A-01 display, and it uses the SPLC780D1 controller. Although it works fine in parallel mode and LiquidCrystal.. the 3rd and 4th lines start at 5th column.. unless address is stated at (-4,2) or (-4,3). It's "HD44780 compatible".. but it also doesn't work with the i2clcd backpack.. garbled text.

Will be getting an actual HD44780 display from AdaFruit instead.


But "trying" to play along with this project, and I'm getting errors.. thinking library issues...

It originally said no Wiring.h. Googling, someone suggested copying the Wiring.h from the arduino/hardware/cores directory.. so I copied the file from there to the Button library directory.

Now...

Code:
/home/spuzzum/arduino-0018/libraries/Button/Wiring.h:69: error: ‘uint8_t’ does not name a type

/home/spuzzum/arduino-0018/libraries/Button/Wiring.h:70: error: ‘uint8_t’ does not name a type

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp: In constructor ‘Button::Button(uint8_t, uint8_t)’:

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp:41: error: ‘bitWrite’ was not declared in this scope

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp: In member function ‘bool Button::isPressed()’:

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp:87: error: ‘bitRead’ was not declared in this scope

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp:87: error: ‘bitWrite’ was not declared in this scope

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp: In member function ‘bool Button::wasPressed()’:

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp:158: error: ‘bitRead’ was not declared in this scope

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp: In member function ‘bool Button::stateChanged()’:

/home/spuzzum/arduino-0018/libraries/Button/Button.cpp:168: error: ‘bitRead’ was not declared in this scope

Using a more recent version of arduino.. arduino-0023 (linux) gives..

Code:
sketch_dec07a:85: error: ‘PULLDOWN’ was not declared in this scope
sketch_dec07a:86: error: ‘PULLDOWN’ was not declared in this scope
sketch_dec07a:87: error: ‘PULLDOWN’ was not declared in this scope
sketch_dec07a:88: error: ‘PULLDOWN’ was not declared in this scope

So sticking with arduino-0018...


I have the Button and EEPROMVar libraries installed ok.. would error on those otherwise. Are you guys using a modified Button library? I grabbed the one from the link in the typhon script.. is there something else I'm missing?


Spuzzum is offline   Reply With Quote
Unread 12/07/2011, 12:13 PM   #827
der_wille_zur_macht
Team RC Member
 
der_wille_zur_macht's Avatar
 
Join Date: Sep 2003
Location: NY
Posts: 17,749
I can't tell what you're missing but it does look like a library issue. I would run a "hello world" sketch against each library in turn and just see if they compile.


__________________
Inconveniencing marine life since 1992

"It is my personal belief that reef aquaria should be thriving communities of biodiversity, representative of their wild counterparts, and not merely collections of pretty specimens growing on tidy clean rock shelves covered in purple coralline algae." (Eric Borneman)
der_wille_zur_macht is offline   Reply With Quote
Unread 12/07/2011, 12:52 PM   #828
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Quote:
Originally Posted by der_wille_zur_macht View Post
I can't tell what you're missing but it does look like a library issue. I would run a "hello world" sketch against each library in turn and just see if they compile.
Thanks DWZM...


ok.. feeling like a noob :P

Seems I "didn't" have EEPROMVar in my arduino-0018 library directory.. only in my arduino-0023 directory... doh!

Added to the 0018 directory, now it's just 1 error...

Code:
error: ‘PULLDOWN’ was not declared in this scope
Looking at the Button.cpp.. it has BUTTON_PULLDOWN.. tried that in the script..

Code:
error: ‘BUTTON_PULLDOWN’ was not declared in this scope

That wasn't it. Did I put Wiring.h in the right place? I'm guessing it would error on that if it was though.


And LiquidCrystal works fine...




Spuzzum is offline   Reply With Quote
Unread 12/07/2011, 01:16 PM   #829
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
ALAS!!!


A few issues... the script calls "Wiring.h" but it's actually called "wiring.h". Changed in the script. I also directed the Button.cpp to the arduino cores directory...
Code:
#include "/home/spuzzum/arduino-0018/hardware/arduino/cores/arduino/wiring.h"

Then it gave the "PULLDOWN" error again.. changed to "BUTTON_PULLDOWN"...
Code:
// create the buttons
Button menu     = Button(12,BUTTON_PULLDOWN);
Button select   = Button(13,BUTTON_PULLDOWN);
Button plus     = Button(14,BUTTON_PULLDOWN);
Button minus    = Button(15,BUTTON_PULLDOWN);

Success!!
Code:
Binary sketch size: 16208 bytes (of a 30720 byte maximum)


Now I can play..............


Spuzzum is offline   Reply With Quote
Unread 12/07/2011, 01:54 PM   #830
mmakay
Registered Member
 
Join Date: Sep 2004
Posts: 55
tweeking the sketch

Hey all,

I want to alter the sketch so that the "On" and "%" overrides relate to the channel's MAX settings rather than full power. I think the following modification should work, but would appreciate it if more experienced eyes would confirm:
}
void ovrSetAll(int pct){
analogWrite(oneLed,map(pct,0,100,0,oneMax));
analogWrite(twoLed,map(pct,0,100,0,twoMax));
analogWrite(threeLed,map(pct,0,100,0,threeMax));
analogWrite(fourLed,map(pct,0,100,0,fourMax));
}

I'd also like a add an additional override state of "actinic only" but haven't dug into what that might entail.

Is it feasible to have a very short ramp up/down (1 or 2 seconds) between these override states? This would give the controller a more polished feel, and help avoid startling the fish. I have a feeling it may be complicated to implement.

Thanks,
Mickey


mmakay is offline   Reply With Quote
Unread 12/07/2011, 01:57 PM   #831
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Happy Happy Happy, Joy Joy Joy...





Thanks DWZM.. greatly appreciated. May Santa spoil you this year........


Spuzzum is offline   Reply With Quote
Unread 12/07/2011, 02:51 PM   #832
Baghyyy
Registered Member
 
Join Date: Aug 2008
Posts: 29
Quote:
Originally Posted by der_wille_zur_macht View Post
There is only one totally "free" pin on the AVR. In the 1.0 hardware I broke it out to a header pin next to the PWM headers. You could use that for a one wire network to read temps from a DS18B20.
ok ...
One pin free is analog-in and it can only use to measure temperature with DS18B20.
if we use a DS18B20 to operate the fans we want to port digital I\O with relais or a PWM, but this is not available!
alternative solution is to change AVR ATMEGA328 with a 1280 or 2560.
must also change the design of the board, while the sketch remains the same, changing only the name at the pin.
is that correct?


Baghyyy is offline   Reply With Quote
Unread 12/07/2011, 03:30 PM   #833
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
You could also slave another 328 for more pins.. I've seen articles on instructables showing how called "Core2Duino". Can link as many as you can code for.. within reason.


Spuzzum is offline   Reply With Quote
Unread 12/07/2011, 04:22 PM   #834
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
There's also an atmega2560 breakout board... $25
http://jkdevices.com/index.php?route...&product_id=49

Or there seems to be pcb files here..
http://code.google.com/p/gruvin9x/so...ble).URL?r=536


Spuzzum is offline   Reply With Quote
Unread 12/08/2011, 07:41 AM   #835
der_wille_zur_macht
Team RC Member
 
der_wille_zur_macht's Avatar
 
Join Date: Sep 2003
Location: NY
Posts: 17,749
You guys are thinking way too complicated for what he's trying to achieve.

Set up the free pin as a one-wire port. You now have one-wire, I2C, and serial available. Put a DS18B20 on the one-wire port and use it to sense temperature. Find a dedicated fan controller IC (or a generic PWM generator) that can work on one-wire or I2C and use that to control the fan. I don't think you need (or want) to switch AVRs or slave a second just to accomplish this specific goal.

If you DID want to break out a second AVR, you could just use another Typhon board and only populate the portions you need (i.e. you'd leave the RTC, buttons, and LCD header off.)


__________________
Inconveniencing marine life since 1992

"It is my personal belief that reef aquaria should be thriving communities of biodiversity, representative of their wild counterparts, and not merely collections of pretty specimens growing on tidy clean rock shelves covered in purple coralline algae." (Eric Borneman)
der_wille_zur_macht is offline   Reply With Quote
Unread 12/08/2011, 11:38 AM   #836
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Quote:
Originally Posted by der_wille_zur_macht View Post
You guys are thinking way too complicated for what he's trying to achieve.

Set up the free pin as a one-wire port. You now have one-wire, I2C, and serial available. Put a DS18B20 on the one-wire port and use it to sense temperature. Find a dedicated fan controller IC (or a generic PWM generator) that can work on one-wire or I2C and use that to control the fan. I don't think you need (or want) to switch AVRs or slave a second just to accomplish this specific goal.

If you DID want to break out a second AVR, you could just use another Typhon board and only populate the portions you need (i.e. you'd leave the RTC, buttons, and LCD header off.)

True.. more work than benefit in the long run.

But if you wanted to free up 3 pins right away... convert the script for an ADC button pad that only uses 1 line for "all" buttons...



Code:
/*
  The circuit:
 * LCD RS pin to analog pin A1
 * LCD Enable pin to analog pin A2
 * LCD D4 pin to analog pin A3
 * LCD D5 pin to digital pin 12
 * LCD D6 pin to digital pin 8
 * LCD D7 pin to digital pin 7
 * LCD BL pin to digital pin 10 <-- not connected
 * KEY pin to analog pin A0
 */

#include 

LiquidCrystal lcd(15, 16, 17, 12, 8, 7);

char msgs[5][16] = {"Right Key OK ",
                    "Up Key OK    ",               
                    "Down Key OK  ",
                    "Left Key OK  ",
                    "Select Key OK" };

int adc_key_val[5] ={50, 200, 400, 600, 800 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;

void setup()
{
  pinMode(A1, OUTPUT); // analog 1 to digital 15
  digitalWrite(A1, HIGH);
  pinMode(A2, OUTPUT); // analog 2 to digital 16
  digitalWrite(A2, HIGH);
  pinMode(A3, OUTPUT); // analog 3 to digital 17
  digitalWrite(A3, HIGH);
  pinMode(A4, OUTPUT); // analog 4 to digital 18
  digitalWrite(A4, HIGH);
  
  lcd.clear(); 
  lcd.begin(16, 2);
  lcd.setCursor(0,0); 
  lcd.print("ADC key testing"); 
}

void loop()
{
  adc_key_in = analogRead(0);    // read the value from the sensor 
  key = get_key(adc_key_in);  // convert into key press
 
  if (key != oldkey)   // if keypress is detected
   {
    delay(50);  // wait for debounce time
    adc_key_in = analogRead(0);    // read the value from the sensor 
    key = get_key(adc_key_in);    // convert into key press
    if (key != oldkey)    
    {   
      lcd.setCursor(0, 1);
      oldkey = key;
      if (key >=0){
           lcd.print(msgs[key]);              
      }
    }
  }
 delay(100);
}

// Convert ADC value to key number
int get_key(unsigned int input)
{
    int k;
   
    for (k = 0; k < NUM_KEYS; k++)
    {
      if (input < adc_key_val[k])
 {
            return k;
        }
   }
   
    if (k >= NUM_KEYS)k = -1;  // No valid key pressed
    return k;
}
The LCD pinout can be changed to whatever you need.. this was just for testing. There's more examples here...
Code:
http://www.nuelectronics.com/estore/index.php?main_page=project_lcd
http://www.dfrobot.com/wiki/index.php?title=Arduino_LCD_KeyPad_Shield_(SKU:_DFR0009)



Spuzzum is offline   Reply With Quote
Unread 12/08/2011, 12:40 PM   #837
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Someone's "selling" your Typhon??

http://www.thereefuge.com/threads/ar...d-answers.745/

Typhon LED Controller Kit:
http://www.boostled.com/collections/...controller-kit


Spuzzum is offline   Reply With Quote
Unread 12/08/2011, 12:47 PM   #838
der_wille_zur_macht
Team RC Member
 
der_wille_zur_macht's Avatar
 
Join Date: Sep 2003
Location: NY
Posts: 17,749
Yes, the pre-1.0 version of the hardware was released without an NC clause on the license. No one participating in this thread has any involvement with that particular vendor and this thread is not intended to support or promote the version that they commercially sell (I did not know they were selling it until after it appeared on their web store). The original intent of this project was to get people to pull out their soldering irons and build something useful themselves.


__________________
Inconveniencing marine life since 1992

"It is my personal belief that reef aquaria should be thriving communities of biodiversity, representative of their wild counterparts, and not merely collections of pretty specimens growing on tidy clean rock shelves covered in purple coralline algae." (Eric Borneman)
der_wille_zur_macht is offline   Reply With Quote
Unread 12/08/2011, 01:16 PM   #839
TheFishMan65
Registered Member
 
Join Date: Aug 2009
Location: Northern VA
Posts: 4,618
Can the project be re-released/updated with the clause? If not perhaps we should start a new thread (and oh what a pain - find a new name). Is it worth it?


__________________
Click my home page for Thread Summaries

Current Tank Info: 75 gallon lps and fish
TheFishMan65 is offline   Reply With Quote
Unread 12/08/2011, 02:05 PM   #840
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Quote:
Originally Posted by der_wille_zur_macht View Post
Yes, the pre-1.0 version of the hardware was released without an NC clause on the license. No one participating in this thread has any involvement with that particular vendor and this thread is not intended to support or promote the version that they commercially sell (I did not know they were selling it until after it appeared on their web store). The original intent of this project was to get people to pull out their soldering irons and build something useful themselves.

That sucks...

I'm a die hard DIY'er, and I know the effort you put into this.. so seeing that was kind of an insult to the DIY community.


Spuzzum is offline   Reply With Quote
Unread 12/08/2011, 02:20 PM   #841
der_wille_zur_macht
Team RC Member
 
der_wille_zur_macht's Avatar
 
Join Date: Sep 2003
Location: NY
Posts: 17,749
The 1.0 version of the hardware is released already with an NC clause, which means it cannot be sold commercially (without explicit permission from the license holder, i.e. me). I plan on using the NC clause on future releases as well, if there are any.


__________________
Inconveniencing marine life since 1992

"It is my personal belief that reef aquaria should be thriving communities of biodiversity, representative of their wild counterparts, and not merely collections of pretty specimens growing on tidy clean rock shelves covered in purple coralline algae." (Eric Borneman)
der_wille_zur_macht is offline   Reply With Quote
Unread 12/08/2011, 02:37 PM   #842
Baghyyy
Registered Member
 
Join Date: Aug 2008
Posts: 29
Quote:
Originally Posted by der_wille_zur_macht View Post
The 1.0 version of the hardware is released already with an NC clause, which means it cannot be sold commercially (without explicit permission from the license holder, i.e. me). I plan on using the NC clause on future releases as well, if there are any.

So must also change the name in DWZM's controller


Baghyyy is offline   Reply With Quote
Unread 12/08/2011, 02:44 PM   #843
der_wille_zur_macht
Team RC Member
 
der_wille_zur_macht's Avatar
 
Join Date: Sep 2003
Location: NY
Posts: 17,749
Hey, it's not "my" controller, it's the DIY community's controller.


__________________
Inconveniencing marine life since 1992

"It is my personal belief that reef aquaria should be thriving communities of biodiversity, representative of their wild counterparts, and not merely collections of pretty specimens growing on tidy clean rock shelves covered in purple coralline algae." (Eric Borneman)
der_wille_zur_macht is offline   Reply With Quote
Unread 12/08/2011, 02:48 PM   #844
TheFishMan65
Registered Member
 
Join Date: Aug 2009
Location: Northern VA
Posts: 4,618
Maybe that is what is should be called "My Controller" since everyone's is slightly different.


__________________
Click my home page for Thread Summaries

Current Tank Info: 75 gallon lps and fish
TheFishMan65 is offline   Reply With Quote
Unread 12/09/2011, 04:34 PM   #845
Baghyyy
Registered Member
 
Join Date: Aug 2008
Posts: 29
Spuzzum, DWZM, good!!!
we can use i2c for all buttons and liberate the digital pin 18-19, change the pin 11PWM, currently connected to the display, on the digital pin 18.
so we can connect the fan to pin PWM11 and DS18B20 connected on 26-pin analog




Last edited by Baghyyy; 12/09/2011 at 04:42 PM.
Baghyyy is offline   Reply With Quote
Unread 12/09/2011, 05:26 PM   #846
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
I just played with the MCP23008 i2clcd circuit DWZM has in his Hydra schematic.. my lcd now works on i2c! Pinout's different than the one from adafruit..
http://www.adafruit.com/products/292


I then came across another design.. few pins different again, but it also works with the ADC keypad.. the type I posted above. Amazingly.. it works too.. including the "joystick" as the manufacturer calls it :P.



Deuligne Schematic



LCDI2C4Bit Adapter Schematic - Deuligne connections are black and in brackets


My DIP Switch Settings:

Code:
LCDI2C4Bit: 1, 2, 4

1 - on = RW disabled
2 - on = RS
3 - off
4 - on = E
5 - off
6 - off


Deuligne: 3, 5, 6

1 - off = RW disabled
2 - off
3 - on = RS
4 - off
5 - on = E
6 - on = RW enabled



LCDI2C4Bit Mode Successful





Deuligne Mode Successful


Spuzzum is offline   Reply With Quote
Unread 12/09/2011, 05:29 PM   #847
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
I then tested the LCDI2C "Hello World" script by modifying for use with Deuligne..

Code:
//LCDI2C modified for Deuligne:

// example use of LCDI2C library with the web4robot.com i2C lcd display

#include 
//#include 
#include 



//LCDI2C lcd = LCDI2C(2,16,0x4C,1);             // Number of lines and i2c address of the display
Deuligne lcd;


void setup() { 


  lcd.init();                          // Init the display, clears the display
 
  lcd.print("Hello World!");       // Classic Hello World!
 

  
}


void loop()
{
  
}

LCDI2C Trial Successful


I then tried the "joystick" test for Deuligne.. same as the ADC Keypad I made earlier.. the one that uses resistors to sense which key is which...












Joystick Test Successful

The keypad settings are actually more responsive than the ones in the script from Nuelectronics for the keypad schematic I built.

I love when things I make actually work .


Yeah.. had some issues.. and even screwed up "slightly" when wiring the DIP.. should've controlled RW pin connection with positions 1 and 2, instead of 1 and 6. Didn't realize I needed another connection until the input pins on the DIP had already been jumped for each line needing 2 output options. Oh well.. it's only a tester. In fact.. it's on a board salvaged from an old project I don't use anymore.. cheapskate, eh?


Spuzzum is offline   Reply With Quote
Unread 12/09/2011, 05:31 PM   #848
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Here's the files for the Deuligne.. including the Arduino library...

http://tronixstuff.wordpress.com/201...rduino-shield/
http://wiki.ultimaker.com/Deuligne_LCD_interface
http://shop.snootlab.com/lang-en/sno...-deuligne.html <--- download tab has schematics, board files, and user guide

https://github.com/Snootlab/Deuligne <--- Deuligne library for Arduino


Sorry.. had to split it up.. couldn't post all in one. Should be something we can work with though.. very adaptable. And look at all the pins it just freed up .


Spuzzum is offline   Reply With Quote
Unread 12/10/2011, 12:44 AM   #849
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
So I tried the Deuligne version in the Typhon script, but used DWZM's buttons instead of the ADC Key buttons... and it works . Just freed up 4 pins.. and it only took a $5 modification, and very minor changes to the script.. basically just calling Deuligne.h in place of LiquidCrystal.h, replacing the LiquidCrystal(x,x,x,x,x,x,x,x); LCD pin declaraton, and removing the (16,2) when the lcd is initiated.. blank screen otherwise .





Spuzzum is offline   Reply With Quote
Unread 12/10/2011, 12:54 AM   #850
Spuzzum
Registered Member
 
Join Date: Feb 2011
Posts: 70
Script with edits... total of 3 lines changed.

Code:
/*
// Typhon firmware
// v0.3 alpha 2011-16-11
// N. Enders, R. Ensminger
//
// This sketch provides firmware for the Typhon LED controller.
// It provides a structure to fade 4 independent channels of LED lighting
// on and off each day, to simulate sunrise and sunset.
//
// Current work in progress:
// - store all LED variables in EEPROM so they are not reset by a loss of power
// - allow for signals to be inverted for buckpucks or other drivers that consider 0 to be "on"
//
// Future developments may include:
// - moon phase simulation
// - storm simulation
// - support for plugin hardware modules for temperature, pH, relay control, etc.
// 
// Sketch developed in Arduino-22
// Requires LiquidCrystal, Wire, EEPROM, EEPROMVar, and Button libraries.
// Button is available here: http://www.arduino.cc/playground/Code/Button
// EEPROMVar is available here: http://www.arduino.cc/playground/uploads/Profiles/EEPROMVar_01.zip
*/

// include the libraries:
#include "Deuligne.h"        ////<------------- changed
#include "Wire.h"
#include "Button.h"
#include "EEPROM.h"
#include "EEPROMVar.h"


/**** Define Variables & Constants ****/
/******************
/*
  The circuit:
 * LCD RS pin to digital pin 8
 * LCD Enable pin to digital pin 7
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 16 (A2)
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
*/
//********************/

// set the RTC's I2C address
#define DS1307_I2C_ADDRESS 0x68
// create the LCD

Deuligne lcd;                ////  <------------- changed

// set up backlight
int bkl         = 6;        // backlight pin
byte bklIdle    = 10;       // PWM value for backlight at idle
byte bklOn      = 70;       // PWM value for backlight when on
int bklDelay    = 10000;    // ms for the backlight to idle before turning off
unsigned long bklTime = 0;  // counter since backlight turned on
// create the menu counter
int menuCount   = 1;
int menuSelect = 0;

//create the plus and minus navigation delay counter with its initial maximum of 250.
byte btnMaxDelay = 200;
byte btnMinDelay = 25;
byte btnMaxIteration = 5;
byte btnCurrIteration;

//create manual override variables
boolean override = false;
byte overmenu = 0;
int overpercent = 0;

// create the buttons
Button menu     = Button(14,BUTTON_PULLDOWN);
Button select   = Button(15,BUTTON_PULLDOWN);
Button plus     = Button(16,BUTTON_PULLDOWN);
Button minus    = Button(17,BUTTON_PULLDOWN);

// LED variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0;         // counter that resets at midnight.
int oldMinCounter = 0;      // counter that resets at midnight.
int oneLed = 9;             // pin for channel 1
int twoLed = 10;            // pin for channel 2
int threeLed = 11;          // pin for channel 3
int fourLed = 3;            // pin for channel 4

int oneVal = 0;             // current value for channel 1
int twoVal = 0;             // current value for channel 2
int threeVal = 0;           // current value for channel 3
int fourVal = 0;            // current value for channel 4

// Variables making use of EEPROM memory:

EEPROMVar oneStartMins = 750;      // minute to start this channel.
EEPROMVar onePhotoPeriod = 720;   // photoperiod in minutes for this channel.
EEPROMVar oneMax = 100;           // max intensity for this channel, as a percentage
EEPROMVar oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                                       //    this channel.
EEPROMVar twoStartMins = 810;
EEPROMVar twoPhotoPeriod = 600;
EEPROMVar twoMax = 100;
EEPROMVar twoFadeDuration = 60;

EEPROMVar threeStartMins = 810;
EEPROMVar threePhotoPeriod = 600;
EEPROMVar threeMax = 100;
EEPROMVar threeFadeDuration = 60;
                            
EEPROMVar fourStartMins = 480;
EEPROMVar fourPhotoPeriod = 510;  
EEPROMVar fourMax = 100;          
EEPROMVar fourFadeDuration = 60;  

// variables to invert the output PWM signal,
// for use with drivers that consider 0 to be "on"
// i.e. buckpucks. If you need to provide an inverted 
// signal on any channel, set the appropriate variable to true.
boolean oneInverted = false;
boolean twoInverted = false;
boolean threeInverted = false;
boolean fourInverted = false;

/*
int oneStartMins = 1380;      // minute to start this channel.
int onePhotoPeriod = 120;   // photoperiod in minutes for this channel.
int oneMax = 100;           // max intensity for this channel, as a percentage
int oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                                       //    this channel.                                    
int twoStartMins = 800;
int twoPhotoPeriod = 60;
int twoMax = 100;
int twoFadeDuration = 15;

int threeStartMins = 800;
int threePhotoPeriod = 60;
int threeMax = 100;
int threeFadeDuration = 30;
                            
int fourStartMins = 800;
int fourPhotoPeriod = 120;  
int fourMax = 100;          
int fourFadeDuration = 60;  
*/

/****** RTC Functions ******/
/***************************/

// Convert decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// Sets date and time, starts the clock
void setDate(byte second,        // 0-59
             byte minute,        // 0-59
             byte hour,          // 1-23
             byte dayOfWeek,     // 1-7
             byte dayOfMonth,    // 1-31
             byte month,         // 1-12
             byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time
void getDate(byte *second,
             byte *minute,
             byte *hour,
             byte *dayOfWeek,
             byte *dayOfMonth,
             byte *month,
             byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down

int   setLed(int mins,         // current time in minutes
            int ledPin,        // pin for this channel of LEDs
            int start,         // start time for this channel of LEDs
            int period,        // photoperiod for this channel of LEDs
            int fade,          // fade duration for this channel of LEDs
            int ledMax,        // max value for this channel
            boolean inverted   // true if the channel is inverted
            )  {
  int val = 0;
      
      //fade up
      if (mins > start || mins <= start + fade)  {
        val = map(mins - start, 0, fade, 0, ledMax);
      }
      //fade down
      if (mins > start + period - fade && mins <= start + period)  {
        val = map(mins - (start + period - fade), 0, fade, ledMax, 0);
      }
      //off or post-midnight run.
      if (mins <= start || mins > start + period)  {
        if((start+period)%1440 < start && (start + period)%1440 > mins )
          {
            val=map((start+period-mins)%1440,0,fade,0,ledMax);
          }
        else  
        val = 0; 
      }
    
    
    if (val > ledMax)  {val = ledMax;} 
    if (val < 0) {val = 0; } 
    
  if (inverted) {analogWrite(ledPin, map(val, 0, 100, 255, 0));}
  else {analogWrite(ledPin, map(val, 0, 100, 0, 255));}
  if(override){val=overpercent;}
  return val;
}

/**** Display Functions ****/
/***************************/

//button hold function
int btnCurrDelay(byte curr)
{
  if(curr==btnMaxIteration)
  {
    btnCurrIteration = btnMaxIteration;
    return btnMaxDelay;
  }
  else if(btnCurrIteration ==0)
  {
    return btnMinDelay;
  }
  else
  {
    btnCurrIteration--;
    return btnMaxDelay;
  }
}

// format a number of minutes into a readable time (24 hr format)
void printMins(int mins,       //time in minutes to print
               boolean ampm    //print am/pm?
              )  {
  int hr = (mins%1440)/60;
  int mn = mins%60;
    if(hr<10){
      lcd.print(" ");
    }
    lcd.print(hr);
    lcd.print(":");
    if(mn<10){
      lcd.print("0");
    }
    lcd.print(mn); 
}

// format hours, mins, secs into a readable time (24 hr format)
void printHMS (byte hr,
               byte mn,
               byte sec      //time to print
              )  
{
  
    if(hr<10){
      lcd.print(" ");
    }
    lcd.print(hr, DEC);
    lcd.print(":");
    if(mn<10){
      lcd.print("0");
    }
    lcd.print(mn, DEC);
    lcd.print(":");
    if(sec<10){
      lcd.print("0");
    }
    lcd.print(sec, DEC);
}
void ovrSetAll(int pct){
    analogWrite(oneLed,map(pct,0,100,0,255));
    analogWrite(twoLed,map(pct,0,100,0,255));
    analogWrite(threeLed,map(pct,0,100,0,255));
    analogWrite(fourLed,map(pct,0,100,0,255));
}

/**** Setup ****/
/***************/

void setup() {
  Wire.begin();
  pinMode(bkl, OUTPUT);
  lcd.init();                        //// <------------- changed
  digitalWrite(bkl, HIGH);
  lcd.print("Typhon-Reef");
  lcd.setCursor(0,1);
  lcd.print("");
  delay(5000);
  lcd.clear();
  analogWrite(bkl,bklIdle);
  btnCurrIteration = btnMaxIteration;
}

/***** Loop *****/
/****************/

void loop() {
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

  getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  oldMinCounter = minCounter;
  minCounter = hour * 60 + minute;
  
  //reset plus & minus acceleration counters if the button's state has changed
  if(plus.stateChanged())
  {
   btnCurrDelay(btnMaxIteration);
  }
  if(minus.stateChanged())
  {  
    btnCurrDelay(btnMaxIteration);
  }
       
  
  //check & set fade durations
  if(oneFadeDuration > onePhotoPeriod/2 && onePhotoPeriod >0){oneFadeDuration = onePhotoPeriod/2;}
  if(oneFadeDuration<1){oneFadeDuration=1;}
  
  if(twoFadeDuration > twoPhotoPeriod/2 && twoPhotoPeriod >0){twoFadeDuration = twoPhotoPeriod/2;} 
  if(twoFadeDuration<1){twoFadeDuration=1;}
  
  if(threeFadeDuration > threePhotoPeriod/2 && threePhotoPeriod >0){threeFadeDuration = threePhotoPeriod/2;}
  if(threeFadeDuration<1){threeFadeDuration=1;}
  
  if(fourFadeDuration > fourPhotoPeriod/2 && fourPhotoPeriod > 0){fourFadeDuration = fourPhotoPeriod/2;}
  if(fourFadeDuration<1){fourFadeDuration=1;}
  
  //check & set any time functions
  
  
  //set outputs
  if(!override){
  oneVal = setLed(minCounter, oneLed, oneStartMins, onePhotoPeriod, oneFadeDuration, oneMax, oneInverted);
  twoVal = setLed(minCounter, twoLed, twoStartMins, twoPhotoPeriod, twoFadeDuration, twoMax, twoInverted);
  threeVal = setLed(minCounter, threeLed, threeStartMins, threePhotoPeriod, threeFadeDuration, threeMax, threeInverted);
  fourVal = setLed(minCounter, fourLed, fourStartMins, fourPhotoPeriod, fourFadeDuration, fourMax, fourInverted);
  }
  else{
    ovrSetAll(overpercent);
  }
  
  
  //turn the backlight off and reset the menu if the idle time has elapsed
  if(bklTime + bklDelay < millis() && bklTime > 0 ){
    analogWrite(bkl,bklIdle);
    menuCount = 1;
    lcd.clear();
    bklTime = 0;
  }

  //iterate through the menus
  if(menu.uniquePress()){
    analogWrite(bkl,bklOn);
    bklTime = millis();
    if(menuCount < 20){
      menuCount++;
    }else {
      menuCount = 1;
    }
  lcd.clear();
  }
  if(menuCount == 1){
    //main screen turn on!!!
    if (minCounter > oldMinCounter){
      lcd.clear();
    }
    lcd.setCursor(0,0);
    printHMS(hour, minute, second);
    lcd.setCursor(0,1);
    lcd.print(oneVal);
    lcd.setCursor(4,1);
    lcd.print(twoVal);
    lcd.setCursor(8,1);
    lcd.print(threeVal);
    lcd.setCursor(12,1);
    lcd.print(fourVal);
    //debugging function to use the select button to advance the timer by 1 minute
    //if(select.uniquePress()){setDate(second, minute+1, hour, dayOfWeek, dayOfMonth, month, year);}
  }
  
  if(menuCount == 2){
    //Manual Override Menu
    lcd.setCursor(0,0);
    lcd.print("Manual Overrides");
    lcd.setCursor(0,1);
    lcd.print("All: ");
    if(select.uniquePress()){
      if(menuSelect < 3){menuSelect++;}
      else{menuSelect = 0;}
      bklTime = millis();
    }
    
    if(menuSelect == 0){
      lcd.print("Timer");
      override = false;}
    if(menuSelect == 1){
      lcd.print("ON   ");
      overpercent = 100;
      override = true;}
    if(menuSelect == 2){
      lcd.print("OFF  ");
      overpercent = 0;
      override = true;}    
    if(menuSelect == 3){
      override = true;
      lcd.print(overpercent,DEC);
      lcd.print("%  ");
      if(plus.isPressed() && overpercent <100)
        {
          overpercent++;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
        
        if(minus.isPressed() && overpercent > 0)
        {
          overpercent--;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
      }
}
  


  if(menuCount == 3){
    //set start time for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 Start");
    lcd.setCursor(0,1);
    printMins(oneStartMins, true);
    
    if(plus.isPressed() && oneStartMins < 1440){
        oneStartMins++;
        if(onePhotoPeriod >0){onePhotoPeriod--;}
        else{onePhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && oneStartMins > 0){
        oneStartMins--;
        if(onePhotoPeriod<1439){onePhotoPeriod++;}
        else{onePhotoPeriod=0;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 4){
    //set end time for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 End");
    lcd.setCursor(0,1);
    printMins(oneStartMins+onePhotoPeriod, true);
    if(plus.isPressed()){
      if(onePhotoPeriod < 1439){
      onePhotoPeriod++;}
      else{
        onePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(onePhotoPeriod >0){
        onePhotoPeriod--;}
      else{
        onePhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 5){
    //set fade duration for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 Fade");
    lcd.setCursor(0,1);
    printMins(oneFadeDuration, false);
    if(plus.isPressed() && (oneFadeDuration < onePhotoPeriod/2 || oneFadeDuration == 0)){
      oneFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && oneFadeDuration > 1){
      oneFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 6){
    //set intensity for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 Max");
    lcd.setCursor(1,1);
    lcd.print(oneMax);
    lcd.print("  ");
    if(plus.isPressed() && oneMax < 100){
      oneMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && oneMax > 0){
      oneMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 7){
    //set start time for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 Start");
    lcd.setCursor(0,1);
    printMins(twoStartMins, true);
    if(plus.isPressed() && twoStartMins < 1440){
        twoStartMins++;
        if(twoPhotoPeriod >0){twoPhotoPeriod--;}
        else{twoPhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && twoStartMins > 0){
        twoStartMins--;
        if(twoPhotoPeriod<1439){twoPhotoPeriod++;}
        else{twoPhotoPeriod=0;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 8){
    //set end time for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 End");
    lcd.setCursor(0,1);
    printMins(twoStartMins+twoPhotoPeriod, true);
    if(plus.isPressed()){
      if(twoPhotoPeriod < 1439){
      twoPhotoPeriod++;}
      else{
        twoPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(twoPhotoPeriod >0){
        twoPhotoPeriod--;}
      else{
        twoPhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 9){
    //set fade duration for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 Fade");
    lcd.setCursor(0,1);
    printMins(twoFadeDuration, false);
    if(plus.isPressed() && (twoFadeDuration < twoPhotoPeriod/2 || twoFadeDuration == 0)){
      twoFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && twoFadeDuration > 1){
      twoFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 10){
    //set intensity for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 Max");
    lcd.setCursor(1,1);
    lcd.print(twoMax);
    lcd.print("  ");
    if(plus.isPressed() && twoMax < 100){
      twoMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && twoMax > 0){
      twoMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 11){
    //set start time for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 Start");
    lcd.setCursor(0,1);
    printMins(threeStartMins, true);
    if(plus.isPressed() && threeStartMins < 1440){
        threeStartMins++;
        if(threePhotoPeriod >0){threePhotoPeriod--;}
        else{threePhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && threeStartMins > 0){
        threeStartMins--;
        if(threePhotoPeriod<1439){threePhotoPeriod++;}
        else{threePhotoPeriod=0;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 12){
    //set end time for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 End");
    lcd.setCursor(0,1);
    printMins(threeStartMins+threePhotoPeriod, true);
    if(plus.isPressed()){
      if(threePhotoPeriod < 1439){
      threePhotoPeriod++;}
      else{
        threePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(threePhotoPeriod >0){
        threePhotoPeriod--;}
      else{
        threePhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 13){
    //set fade duration for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 Fade");
    lcd.setCursor(0,1);
    printMins(threeFadeDuration, false);
    if(plus.isPressed() && (threeFadeDuration < threePhotoPeriod/2 || threeFadeDuration == 0)){
      threeFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && threeFadeDuration > 1){
      threeFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 14){
    //set intensity for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 Max");
    lcd.setCursor(1,1);
    lcd.print(threeMax);
    lcd.print("  ");
    if(plus.isPressed() && threeMax < 100){
      threeMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && threeMax > 0){
      threeMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 15){
    //set start time for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 Start");
    lcd.setCursor(0,1);
    printMins(fourStartMins, true);
    if(plus.isPressed() && fourStartMins < 1440){
        fourStartMins++;
        if(fourPhotoPeriod >0){fourPhotoPeriod--;}
        else{fourPhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && fourStartMins > 0){
        fourStartMins--;
        if(fourPhotoPeriod<1439){fourPhotoPeriod++;}
        else{fourPhotoPeriod=0;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 16){
    //set end time for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 End");
    lcd.setCursor(0,1);
    printMins(fourStartMins+fourPhotoPeriod, true);
    if(plus.isPressed()){
      if(fourPhotoPeriod < 1439){
      fourPhotoPeriod++;}
      else{
        fourPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(fourPhotoPeriod >0){
        fourPhotoPeriod--;}
      else{
        fourPhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 17){
    //set fade duration for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 Fade");
    lcd.setCursor(0,1);
    printMins(fourFadeDuration, false);
    if(plus.isPressed() && (fourFadeDuration < fourPhotoPeriod/2 || fourFadeDuration == 0)){
      fourFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && fourFadeDuration > 1){
      fourFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 18){
    //set intensity for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 Max");
    lcd.setCursor(1,1);
    lcd.print(fourMax);
    lcd.print("   ");
    if(plus.isPressed() && fourMax < 100){
      fourMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && fourMax > 0){
      fourMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }

  if(menuCount == 19){
    //set hours
    lcd.setCursor(0,0);
    lcd.print("Set Time: Hrs");
    lcd.setCursor(0,1);
    printHMS(hour, minute, second);
    if(plus.isPressed() && hour < 23){
      hour++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && hour > 0){
      hour--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  setDate(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  }
  
  if(menuCount == 20){
    //set minutes
    lcd.setCursor(0,0);
    lcd.print("Set Time: Mins");
    lcd.setCursor(0,1);
    printHMS(hour, minute, second);
    if(plus.isPressed() && minute < 59){
      minute++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && minute > 0){
      minute--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  setDate(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  }
}

Now just needs a temp sensor portion.....


Spuzzum is offline   Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Cheap Moonlight ticklesworth New to the Hobby 3 04/04/2010 04:09 PM
Cheap Moonlight ticklesworth Do It Yourself 0 04/03/2010 08:52 AM
Arduino base controller - power pack ONLY TODAY MaLi Do It Yourself 0 03/07/2010 05:56 AM
Sumps 101: Cheap, simple and effective for small tanks cody6766 Central Oklahoma Marine Aquarium Society 8 01/06/2009 10:57 AM


All times are GMT -6. The time now is 03:46 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Powered by Searchlight © 2024 Axivo Inc.
Use of this web site is subject to the terms and conditions described in the user agreement.
Reef CentralTM Reef Central, LLC. Copyright ©1999-2022
User Alert System provided by Advanced User Tagging v3.3.0 (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.