FIRST VISIT: The link to the Build List/Materials Needed
* Completely stock Ethernet module needed. (With Serial pin-out)
Arduino Type Here *NO* POE (Power over Ethernet) needed
* This has (2) PWM outputs and (2) PWM fan outputs
* Fans follow the PWMParabola as a percentage of the PWMParabola (fully automated).
-Or the fans kick on once the input of the analog signal reaches 300+ when using potentiometers!
* NTP time incorporated
-NTP primary server and backup NTP server implemented
* RA control via portal/phone app included.
* Corrected code for potentiometers to override PWMParabola to allow for manual dimming of pin 9 and pin 6.
-Return both potentiometers to "0" to have PWMParabola take back over...
Code: Select all
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
int bval = 0; // Variable to store the blue read value
int wval = 0; // Variable to store the white read value
int analogPinb = A0; // Potentiometer connected to analog pin A0 for blue
int analogPinw = A1; // Potentiometer connected to analog pin A1 for white
int outputValueb = 0;
int outputValuew = 0;
int blue1 = 9; // blue LEDs connected to digital pin 9 (pwm)
int white1 = 6; // white LEDs connected to digital pin 6 (pwm)
int fan1 = 3; // Fanspeed digital pin 14 (pwm)
int fan2 = 5; // Fanspeed digital pin 15 (pwm)
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //YOUR MAC off sticker
IPAddress ip(192,168,1, 110); //YOUR STATIC IP HERE
IPAddress remoteserver(198,171,134,6); // forum.reefangel.com
EthernetClient clientout;
unsigned long lastmillisout=millis();
unsigned long lastmillisin=millis();
boolean sending=false;
char strout[400];
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
/* ******** NTP Server Settings NTP BEGIN ******** */
/* (Set to your time server of choice) */
IPAddress timeServer(50, 77, 217, 185);
IPAddress backupNTP(64, 113, 32, 5); // back up NTP sever
/* Set this to the offset (in seconds) to your local time
This example is GMT - 6 */
const long timeZoneOffset = -21600L; // CORRECT THIS FOR YOUR TIME ZONE
/* Syncs to NTP server every 15 seconds for testing,
set to 1 hour or more to be reasonable */
unsigned int ntpSyncTime = 3600; //3600 one hour
/* ALTER THESE VARIABLES AT YOUR OWN RISK */
// local port to listen for UDP packets
unsigned int localPort = 8888;
// NTP time stamp is in the first 48 bytes of the message
const int NTP_PACKET_SIZE= 48;
// Buffer to hold incoming and outgoing packets
byte packetBuffer[NTP_PACKET_SIZE];
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
// Keeps track of how long ago we updated the NTP server
unsigned long ntpLastUpdate = 0;
// Check last time clock displayed (Not in Production)
// Do not alter this function, it is used by the system
int getTimeAndDate() {
int flag=0;
Udp.begin(localPort);
sendNTPpacket(timeServer);
delay(1000);
if (Udp.parsePacket()){
Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
unsigned long highWord, lowWord, epoch;
highWord = word(packetBuffer[40], packetBuffer[41]);
lowWord = word(packetBuffer[42], packetBuffer[43]);
epoch = highWord << 16 | lowWord;
epoch = epoch - 2208988800 + timeZoneOffset;
flag=1;
setTime(epoch);
ntpLastUpdate = now();
}
return flag;
}
// Do not alter this function, it is used by the system
unsigned long sendNTPpacket(IPAddress& address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011;
packetBuffer[1] = 0;
packetBuffer[2] = 6;
packetBuffer[3] = 0xEC;
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.beginPacket(address, 123);
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
}
//NTP END
//PWM functions START
byte intlength(int intin)
{
if (intin>9999) return 5;
if (intin>999) return 4;
if (intin>99) return 3;
if (intin>9) return 2;
if (intin>=0 && intin<=9) return 1;
if (intin<0) return 2;
}
int NumMins(uint8_t ScheduleHour, uint8_t ScheduleMinute)
{
return (ScheduleHour*60) + ScheduleMinute;
}
bool IsLeapYear(int year)
{
if (year % 4 != 0)
{
return false;
}
else if (year % 400 == 0)
{
return true;
}
else if (year % 100 == 0)
{
return false;
}
return true;
}
byte PWMParabola(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, byte endPWM, byte oldValue)
{
int Now = NumMins(hour(), minute());
int Start = NumMins(startHour, startMinute);
int End = NumMins(endHour, endMinute);
byte PWMDelta = endPWM-startPWM;
byte ParabolaPhase=constrain(map(Now,Start,End,0,180),0,180);
if ( Now <= Start || Now >= End)
return oldValue;
else
{
return startPWM+(PWMDelta*sin(radians(ParabolaPhase)));
}
}
// PWM functions END
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ETHERNET MODULE |||||||||||||||||||||||||||||||||||||||||||||||*/
void ethernetmodule() //create ethernet function for loop
{
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
while (client.available()) {
char c = client.read();
if (sending==false) Serial.write(c);
lastmillisin=millis();
}
while (Serial.available()){
memset(strout,0,sizeof(strout));
int b=Serial.readBytesUntil('>',strout,sizeof(strout));
client.print(strout);
client.print(">");
if (millis()-lastmillisin>2000)
{
lastmillisin=millis();
client.stop();
}
}
if (millis()-lastmillisin>2000)
{
lastmillisin=millis();
client.stop();
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
}
else
{
if (Serial.available())
{
memset(strout,0,sizeof(strout));
int b=Serial.readBytesUntil('\n',strout,sizeof(strout));
if (b>10)
{
sending=true;
Serial.print(strout);
Serial.println(" HTTP/1.0");
Serial.println();
if (clientout.connect(remoteserver, 80))
{
clientout.print(strout);
clientout.println(" HTTP/1.0");
clientout.println();
lastmillisout=millis();
}
}
}
while (clientout.available()) {
char c = clientout.read();
Serial.print(c);
if (millis()-lastmillisout>8000)
{
lastmillisout=millis();
clientout.stop();
sending=false;
}
}
if (!clientout.connected())
{
clientout.stop();
sending=false;
}
}
if (millis()-lastmillisout>8000)
{
lastmillisout=millis();
clientout.stop();
sending=false;
}
//GET /status/submitp.aspx?t1=806&t2=0&t3=0&ph=441&id=test&em=0&rem=0&key=&atohigh=0&atolow=0&r=0&ron=0&roff=255 HTTP/1.0
//GET /status/submitp.asp?t1=806&t2=0&t3=0&ph=441&id=test&em=0&rem=0&key=&atohigh=0&atolow=0&r=0&ron=0&roff=255 HTTP/1.0
//Host: forum.reefangel.com
//
//GET /status/submitp.aspx?t1=806&t2=0&t3=0&ph=441&id=test&em=0&rem=0&key=&atohigh=0&atolow=0&r=0&ron=0&roff=255 HTTP/1.0
//Host: forum.reefangel.com
//Connection: Keep-Alive
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| END ETHERNET MODULE |||||||||||||||||||||||||||||||||||||||||||||||*/
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| NTP |||||||||||||||||||||||||||||||||||||||||||||||*/
void NTP()//loop NTP with one hour refresh
{
if(now()-ntpLastUpdate > ntpSyncTime) {
int trys=0;
while(!getTimeAndDate() && trys<10){
trys++;
}
if(trys<10)
{
// Serial.println("ntp server update success");
}
else if (trys>=10 && trys<20)
{
sendNTPpacket(backupNTP);
// Serial.println("backup success");
}
else
{
// Serial.println("ntp server update failed");
}
}
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| END NTP |||||||||||||||||||||||||||||||||||||||||||||||*/
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| S E T U P |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void setup() {
bitSet(TCCR1B, WGM12); //force fast PWM
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
// Ethernet connection ok and server started
//START NTP SET UP
//Try to get the date and time
int trys=0;
while(!getTimeAndDate() && trys<10) {
trys++;
}
//END NTP SET UP
pinMode(analogPinb, INPUT);
pinMode(analogPinw, INPUT);
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| L O O P |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void loop()
{
int b = ((PWMParabola(6,1,21,10,22,210,0)) / 1.2); //0-255 FAN CONTROL
int w = ((PWMParabola(8,0,18,30,22,230,0)) / 1.2); //0-255 FAN CONTROL
bval = analogRead(analogPinb); // read the input Analog pin 3 values go from 0 to 1023,
wval = analogRead(analogPinw); // read the input Analog pin 3 values go from 0 to 1023,
ethernetmodule();//loop the ethernet code
NTP(); //loop NTP with one hour refresh of time
if (hour() >= 6 && hour() <= 22)
{
//Serial.println(outputValuew);
if (bval >= 1 && wval >= 1)
{
bval = analogRead(analogPinb); // read the input Analog pin 3 values go from 0 to 1023,
wval = analogRead(analogPinw); // read the input Analog pin 3 values go from 0 to 1023,
outputValueb = map(bval, 0, 1023, 0, 255); //convert 0-1023 to 0-255 output
outputValuew = map(wval, 0, 1023, 0, 255); //convert 0-1023 to 0-255 output
if (wval >= 1)
{
analogWrite(blue1, outputValueb);
// Serial.println("blueON");
if (bval >= 300)
{
analogWrite(fan1, outputValueb);
// Serial.println("fan1");
}
}
else
{
outputValueb = 0;
//Serial.println("BlueOFF");
}
if (bval >= 1)
{
analogWrite(white1, outputValuew);
// Serial.println("whiteON");
if (wval >= 300)
{
analogWrite(fan2, outputValuew);
// Serial.println("fan2");
}
}
else
{
outputValuew = 0;
//Serial.println("WhiteOFF");
}
}
else
{
//Serial.println("Parabola");
analogWrite(blue1,2.55*PWMParabola(6,1,21,10,10,85,0)); //PERCENTAGE TO 0-255
analogWrite(white1,2.55*PWMParabola(8,0,18,30,10,80,0)); //PERCENTAGE TO 0-255
if (b >= 53) // Adjustment above for b value division formula
{
analogWrite(fan1, b);
}
if (w >= 60) //Adjustment above for w value division formula
{
analogWrite(fan2, w);
}
}
}
}
Also, skim the code for "//" to make adjustments to suite your tank!
FYI: PWM output limited to 0-5v.
0-5v will give an output of approximately 50% with most drivers.
Op-Amp can boost to 0-10v (compatible with most drivers)
Op-Amp pinout for LM358:
Use below for security option (IF needed):
"key" must match on code and portal
This applies to the ReefAngel side of code...
Code: Select all
ReefAngel.Portal("username","key");