Time for additional Ethernet add-on with PWM output

Expansion modules and attachments
User avatar
Posts: 818
Joined: Tue May 29, 2012 2:12 pm
Location: Christopher, IL
PostPosted: Thu Jan 31, 2013 5:47 am
The new code is available:
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);
      }
    }
  }

}


Don't forget to assign your static IP & input your MAC address into the code!
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:
Image

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");


ENJOY! :ugeek:
Last edited by DrewPalmer04 on Fri Mar 29, 2013 8:37 am, edited 17 times in total.
Out for now...but not over.

VISIT: Ethernet Module/Wifi Alternative
User avatar
Posts: 818
Joined: Tue May 29, 2012 2:12 pm
Location: Christopher, IL
PostPosted: Thu Jan 31, 2013 7:31 am
Roberto. On the try<10 ...else { } section would this be the best place to define a backup NTP server? How would I implement this? The reason I need this is the website states the server is available for Chicago but truly it's down. I'm using michigan NTP now but want a backup to chicago
Out for now...but not over.

VISIT: Ethernet Module/Wifi Alternative

Posts: 12877
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Thu Jan 31, 2013 9:32 am
update the server and add change your code to try<10... else if (try>=10 && try<20).... else {// give up... failed 2 servers...}
Roberto.
User avatar
Posts: 818
Joined: Tue May 29, 2012 2:12 pm
Location: Christopher, IL
PostPosted: Thu Jan 31, 2013 9:59 am
I mean declaring a roller over server with IP. If try<10 "ok"... Else { roll over/back up NTP server IP address}??
Out for now...but not over.

VISIT: Ethernet Module/Wifi Alternative

Posts: 12877
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Thu Jan 31, 2013 10:02 am
correct, but if you go to back up server, you need to still increment try and check if it also failed 10 more tries or you will be in eternal loop trying the second server if it fails too.
Roberto.
User avatar
Posts: 818
Joined: Tue May 29, 2012 2:12 pm
Location: Christopher, IL
PostPosted: Thu Jan 31, 2013 10:04 am
Cool thanks.
Out for now...but not over.

VISIT: Ethernet Module/Wifi Alternative
User avatar
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Thu Jan 31, 2013 11:49 am
Run a local NTP server...let that sync to multiple external.
User avatar
Posts: 818
Joined: Tue May 29, 2012 2:12 pm
Location: Christopher, IL
PostPosted: Thu Jan 31, 2013 12:05 pm
Now that's a thought! But for everyone else I wanted to make it where people could set their led/fan pins and upload. For those who don't know how to set up an NTP server. For myself I'll use your idea, but for everyone else I'll put two NTP IPs one for primary. One for roll over/backup.
Out for now...but not over.

VISIT: Ethernet Module/Wifi Alternative
User avatar
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Thu Jan 31, 2013 12:11 pm
Real NTP you give multiple nodes and both times are compared and sync'd accordingly. Maybe you should adapt that approach rather than primary / backup.
User avatar
Posts: 818
Joined: Tue May 29, 2012 2:12 pm
Location: Christopher, IL
PostPosted: Thu Jan 31, 2013 12:11 pm
Then they will just have to adjust the off set for -6, -4 etc
Out for now...but not over.

VISIT: Ethernet Module/Wifi Alternative
PreviousNext

Return to Addons

Who is online

Users browsing this forum: No registered users and 5 guests