New Buzzer is not working correctly.
Posted: Sun Jan 20, 2013 3:24 pm
I recently added the buzzer accessory to my generation 1 Reef Angel. I would like the buzzer to sound when my ATO reservior is empty or when the sump is going to overflow. I use both float switches to detect both of these conditions and the code seems to be working correctly but the buzzer will not sound. The buzzer is connected to the Actinic channel on my generation 1 relay box. The only time the buzzer does sound is when I manually turn on my Refugium Light which is connect to port 8 on my relay box. The Actinic channel displays 20% when the light is switched on using the controller or the RA Android application. I have intentionally temporarily commented out the buzzer code in my code sample below because it affects the ATO functionality (i.e. relay port 1 for the ATO is turned off). I would normally uncomment the section that starts with "/* added buzzer 1-19-13".
I am also trying to determine what the difference is between the TunzeShortPulse and TunzeLongPulse code so I have added an condition that will allow me to switch which Tunze code is in use while I have my hand in the tank so I can feel the changes in flow. I am not sure that I have coded the if statement correctly.
if ( Tunze_ShortPulse == 1 ){ // Determine which TunzePulse type has been selected.
I would appreciate any assistance you can provide to me.
Thanks,
John
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 <ReefAngel.h>
////// Place global variable code below here
// define what each relay port is used for.
#define ATO_pump Port1 // Auto Top Off
#define Dose_Alk Port2 // Dosing Pump Alk
#define Dose_Ca Port3 // Dosing Pump Ca
#define Dose_Mg Port4 // Dosing Pump Mg
#define Powerhead Port5 // Tunze 6105 Powerhead
// #define Unused Port6 // Unused
#define Heater Port7 // Heater
#define Refugium_Light Port8 // Refugium LED Light
// define Internal Memory variables for the 3 dosing pumps
#define Dose_Alk_Seconds 100 // Number of seconds to dose Alk (byte value=90)
#define Dose_Ca_Seconds 101 // Number of seconds to dose Ca (byte value=90)
#define Dose_Mg_Seconds 102 // Number of seconds to dose Mg (byte value=60)
// define Internal Memory variables for Tunze 6105 Powerhead
#define DTime_MinSpeed 103 // Tunze Powerhead Day time Minimum Speed (byte value=30)
#define DTime_MaxSpeed 104 // Tunze Powerhead Day time Minimum Speed (byte value=90)
#define DTime_Duration 105 // Tunze Powerhead Day time Minimum Speed (byte value=3)
#define NTime_MinSpeed 106 // Tunze Powerhead Night time Minimum Speed (byte value=30)
#define NTime_MaxSpeed 107 // Tunze Powerhead Night time Minimum Speed (byte value=50)
#define NTime_Duration 108 // Tunze Powerhead Night time Minimum Speed (byte value=3)
#define NTime_StartTime 109 // Tunze Powerhead Night Start time 10:00 pm (byte value=22)
#define NTime_EndTime 110 // Tunze Powerhead Night End time 8:00 am (byte value=8)
#define Tunze_ShortPulse 111 // TunzeShortPulse=1 or TunzeLongPulse=0 (byte value=1)
// added buzzer 1-19-13
// Initialize Buzzer variables
byte buzzer=0;
byte overheatflag=0;
byte atoflag=0;
/* added 1-19-13
byte iochannel0flag=0;
byte iochannel1flag=0;
byte iochannel2flag=0;
byte iochannel3flag=0;
byte iochannel4flag=0;
byte iochannel5flag=0;
*/
// define the custom menu descriptions.
#include <avr/pgmspace.h>
prog_char menu0_label[] PROGMEM = "Feeding";
prog_char menu1_label[] PROGMEM = "Water Change";
prog_char menu2_label[] PROGMEM = "ATO Clear";
prog_char menu3_label[] PROGMEM = "Overheat Clear";
prog_char menu4_label[] PROGMEM = "PH Calibration";
prog_char menu5_label[] PROGMEM = "Sump Light On/Off";
prog_char menu6_label[] PROGMEM = "Powerhead On/Off";
prog_char menu7_label[] PROGMEM = "Version";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label, menu5_label, menu6_label, menu7_label };
void MenuEntry1()
{
//ReefAngel.DisplayMenuEntry("Feeding");
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
//ReefAngel.DisplayMenuEntry("Water Change");
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry4()
{
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry5()
{
//ReefAngel.DisplayMenuEntry("PH Calibration");
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry6()
{
// Clear the screen
ReefAngel.ClearScreen(DefaultBGColor);
// Display some text on the screen.
ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 5, 10, "Sump Light On/Off");
// Determine whether the Sump Light is already on.
if (bitRead(ReefAngel.Relay.RelayData, Refugium_Light-1)) { // If relay is on.
// Toggle MaskOff for the light
bitWrite(ReefAngel.Relay.RelayMaskOff, Refugium_Light-1, 1-bitRead(ReefAngel.Relay.RelayMaskOff, Refugium_Light-1));
} else {
// Toggle the MaskOn for the light
bitWrite(ReefAngel.Relay.RelayMaskOn, Refugium_Light-1, 1-bitRead(ReefAngel.Relay.RelayMaskOn, Refugium_Light-1));
}
ReefAngel.Relay.Write();
// Tell the controller to cleanup and return to the main screen
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
// To return to the menu instead, comment out the above line and use
// this line instead
//ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry7()
{
// Clear the screen
ReefAngel.ClearScreen(DefaultBGColor);
// Display some text on the screen
ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 5, 10, "Powerhead On/Off");
// Determine whether the Powerhead is already on.
if (bitRead(ReefAngel.Relay.RelayData, Powerhead-1)) { // If relay is on.
// Toggle MaskOff for the powerhead
bitWrite(ReefAngel.Relay.RelayMaskOff, Powerhead-1, 1-bitRead(ReefAngel.Relay.RelayMaskOff, Powerhead-1));
} else {
// Toggle the MaskOn for the powerhead
bitWrite(ReefAngel.Relay.RelayMaskOn, Powerhead-1, 1-bitRead(ReefAngel.Relay.RelayMaskOn, Powerhead-1));
}
ReefAngel.Relay.Write();
// Tell the controller to cleanup and return to the main screen
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
// To return to the menu instead, comment out the above line and use
// this line instead
//ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8()
{
//ReefAngel.DisplayMenuEntry("Display Version");
ReefAngel.DisplayVersion();
}
////// Place global variable code above here
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
// Initialize the menu - Added 1-7-13
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port5Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port3Bit | Port4Bit | Port5Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port8Bit;
// 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;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 820 );
// Ports that are always on
ReefAngel.Relay.On( Powerhead ); // Tunze 6105 powerhead
}
////// Place additional initialization code below here
// Setup SMS alerts
void WifiSendAlert(byte id, boolean IsAlert)
{
static byte alert_status;
if (IsAlert) {
if ((alert_status & 1<<(id-1))==0) {
alert_status|=1<<(id-1);
Serial.print("GET /status/alert.asp?e=3141234567@vtext.com&id=");
Serial.println(alert_status,DEC);
Serial.println("\n\n");
}
}
else {
if (id==0) {
alert_status=0;
delay(900);
}
else {
alert_status&=~(1<<(id-1));
}
}
}
// Tunze short pulse functions
byte TunzeShortPulse(byte PulseMinSpeed, byte PulseMaxSpeed, int PulseDuration, boolean PulseSync)
{
byte tspeed=0;
PulseMinSpeed=constrain(PulseMinSpeed,0,100);
PulseMaxSpeed=constrain(PulseMaxSpeed,0,100);
tspeed=(millis()%(PulseDuration*2)<PulseDuration?PulseMinSpeed:PulseMaxSpeed);
if (PulseSync)
return tspeed;
else
return (tspeed==PulseMinSpeed)?PulseMaxSpeed:PulseMinSpeed;
}
// Tunze long pulse functions
byte TunzeLongPulse(byte PulseMinSpeed, byte PulseMaxSpeed, int PulseDuration, boolean PulseSync)
{
byte tspeed=0;
PulseMinSpeed=constrain(PulseMinSpeed,0,100);
PulseMaxSpeed=constrain(PulseMaxSpeed,0,100);
tspeed=(now()%(PulseDuration*2)<PulseDuration?PulseMinSpeed:PulseMaxSpeed);
if (PulseSync)
return tspeed;
else
return (tspeed==PulseMinSpeed)?PulseMaxSpeed:PulseMinSpeed;
}
////// Place additional initialization code above here
void loop()
{
//*** Heater *** added 12-27-12
ReefAngel.StandardHeater( Heater,755,765 );
//*** Refugium Light *** added 12-27-12 - turn light on at 8:00 pm and off at 8:00 am.
ReefAngel.StandardLights( Refugium_Light,20,0,8,0 );
////// Place your custom code below here
ReefAngel.CustomVar[0]=InternalMemory.read(Dose_Alk_Seconds);
ReefAngel.CustomVar[1]=InternalMemory.read(Dose_Ca_Seconds);
ReefAngel.CustomVar[2]=InternalMemory.read(Dose_Mg_Seconds);
ReefAngel.CustomVar[3]=ReefAngel.LowATO.IsActive();
ReefAngel.CustomVar[4]=ReefAngel.HighATO.IsActive();
ReefAngel.CustomVar[5]=InternalMemory.read(Tunze_ShortPulse);
ReefAngel.CustomVar[6]=InternalMemory.read(DTime_MaxSpeed);
ReefAngel.CustomVar[7]=InternalMemory.read(NTime_MaxSpeed);
// added buzzer 1-19-13
// Sound buzzer if any flag is set.
// buzzer = overheatflag + atoflag + iochannel0flag + iochannel1flag + iochannel2flag + iochannel3flag + iochannel4flag + iochannel5flag;
buzzer = overheatflag + atoflag;
if ( buzzer >= 1 ) buzzer = 100;
ReefAngel.PWM.SetActinic( buzzer );
/*
// Night mode for Tunze powerheads starts at 10:00 pm and stops at 8:00 am. ShortPulse creates more random length pulses.
if ( (hour() >= 22) || (hour() <= 8) ){
if ( Tunze_ShortPulse == 1 ){ // Determine which TunzePulse type has been selected.
ReefAngel.PWM.SetDaylight( TunzeShortPulse(30,50,3,false) );}
else {
ReefAngel.PWM.SetDaylight( TunzeLongPulse(30,50,3,false) );}
}
else {
// Day mode for Tunze powerheads
if (Tunze_ShortPulse == 1){ // Determine which TunzePulse type has been selected.
ReefAngel.PWM.SetDaylight( TunzeShortPulse(30,90,3,false) );}
else {
ReefAngel.PWM.SetDaylight( TunzeLongPulse(30,90,3,false) );}
}
*/
/*
// Night mode for Tunze powerheads LongPulse starts at 10:00 pm and stops at 8:00 am. LongPulse completely stops the pump between pulses.
if ( (hour() >= 22) || (hour() <= 8) ){
ReefAngel.PWM.SetDaylight( TunzeLongPulse(30,50,3,false) );
}
else {
// Day mode for Tunze powerheads
ReefAngel.PWM.SetDaylight( TunzeLongPulse(30,90,3,false) );
}
*/
// added 1-19-13
// Night mode for Tunze powerheads starts at 10:00 pm and stops at 8:00 am. ShortPulse creates more random length pulses.
// LongPulse completely stops the pump between pulses.
if ( (hour() >= InternalMemory.read(NTime_StartTime)) || (hour() <= InternalMemory.read(NTime_EndTime)) ){
if ( Tunze_ShortPulse == 1 ){ // Determine which Tunze Pulse type (Short or Long) has been selected.
ReefAngel.PWM.SetDaylight( TunzeShortPulse(InternalMemory.read(NTime_MinSpeed),InternalMemory.read(NTime_MaxSpeed),InternalMemory.read(NTime_Duration),false) );}
else {
ReefAngel.PWM.SetDaylight( TunzeLongPulse(InternalMemory.read(NTime_MinSpeed),InternalMemory.read(NTime_MaxSpeed),InternalMemory.read(NTime_Duration),false) );}
}
else {
// Day mode for Tunze powerheads
if ( Tunze_ShortPulse == 1 ){ // Determine which Tunze Pulse (Short or Long) type has been selected.
ReefAngel.PWM.SetDaylight( TunzeShortPulse(InternalMemory.read(DTime_MinSpeed),InternalMemory.read(DTime_MaxSpeed),InternalMemory.read(DTime_Duration),false) );}
else {
ReefAngel.PWM.SetDaylight( TunzeLongPulse(InternalMemory.read(DTime_MinSpeed),InternalMemory.read(DTime_MaxSpeed),InternalMemory.read(DTime_Duration),false) );}
}
/* **** DOSING ****
Future enhancement: Add code to set the dosing time from a variable in the web portal or android application, so I don't have to
upload code everytime I want to make slight adjustments to the amount I dose.
*/
// Dose Alk one time per hour between 8:00 pm and 5:00 am.
// Note: Because this dosing occurs for less than 5 minutes it will not be recorded in the Relay activity view in the web portal
if ( hour() >=20 || hour() <5) {
ReefAngel.DosingPumpRepeat( Dose_Alk,0,60,InternalMemory.read(Dose_Alk_Seconds)); } // Dose Alk for x number of seconds at the top of the hour.
else {
ReefAngel.Relay.Off( Dose_Alk );
}
// Dose Ca and Mg one time per hour between 9:00 am and 6:00 pm.
// Note: Because this dosing occurs for less than 5 minutes it will not be recorded in the Relay activity view in the web portal.
if ( hour() >=9 && hour() <18) {
ReefAngel.DosingPumpRepeat( Dose_Ca,0,60,InternalMemory.read(Dose_Ca_Seconds)); // Dose Ca for x number of seconds at the top of the hour.
ReefAngel.DosingPumpRepeat( Dose_Mg,10,60,InternalMemory.read(Dose_Mg_Seconds)); } // Dose Mg for x number of seconds 10 minutes after the top of the hour.
else {
ReefAngel.Relay.Off( Dose_Ca );
ReefAngel.Relay.Off( Dose_Mg );
}
/* **** SMS TEXT ALERTS ****
Future enhancement: Allow us to add custom text for SMS alerts.
List of the possible alert codes.
WifiSendAlert(0)="Nothing"
WifiSendAlert(1)="Auto top-off timeout"
WifiSendAlert(2)="Water temperature too high"
WifiSendAlert(3)="Water temperature too low"
WifiSendAlert(4)="Lights temperature too high"
WifiSendAlert(5)="PH too high"
WifiSendAlert(6)="PH too low Alert"
Let's say you would like to receive a high water temperature alert.
The line you have to add is:
if (ReefAngel.Params.Temp1>820) WifiSendAlert(2);
*/
// Send SMS text message alert if temp1 is less than 74.5 degrees.
if (ReefAngel.Params.Temp[1]<745 && ReefAngel.Params.Temp[1]>0) WifiSendAlert(3,true);
// Send SMS text message alert if temp1 is greater than 82 degrees.
if (ReefAngel.Params.Temp[1]>820 && ReefAngel.Params.Temp[1]<1850) WifiSendAlert(2,false);
//*** ATO *** added 12-29-12
// Shutoff ATO pump if the ATO reservoir is empty or if the sump is going to overflow.
if (!ReefAngel.LowATO.IsActive() || !ReefAngel.HighATO.IsActive()){
ReefAngel.Relay.Off (ATO_pump);}
/* added buzzer 1-19-13
// Determine which channel the buzzer is attached to (i.e. daylight or actinic) and uncomment the appropriate code below.
// Do not sound the buzzer for empty ATO reservior between 7:00 am and 10:00 pm.
if ( hour() >= 7 && hour() < 22) {
// Sound the buzzer on the actinic channel for 100ms every 30 seconds.
ReefAngel.PWM.SetActinic( buzzer );
// Sound the buzzer on the actinic channel for 1/2 second every 2 minutes.
// ReefAngel.PWM.SetActinic(millis()%120000<500?buzzer:0);
}
*/
else {
ReefAngel.Relay.On (ATO_pump);
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "mudcat1" );
ReefAngel.ShowInterface();
}
if ( Tunze_ShortPulse == 1 ){ // Determine which TunzePulse type has been selected.
I would appreciate any assistance you can provide to me.
Thanks,
John