Page 4 of 7

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 5:47 am
by DrewPalmer04
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:

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 7:31 am
by DrewPalmer04
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

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 9:32 am
by rimai
update the server and add change your code to try<10... else if (try>=10 && try<20).... else {// give up... failed 2 servers...}

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 9:59 am
by DrewPalmer04
I mean declaring a roller over server with IP. If try<10 "ok"... Else { roll over/back up NTP server IP address}??

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 10:02 am
by rimai
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.

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 10:04 am
by DrewPalmer04
Cool thanks.

Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 11:49 am
by lnevo
Run a local NTP server...let that sync to multiple external.

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 12:05 pm
by DrewPalmer04
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.

Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 12:11 pm
by lnevo
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.

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 12:11 pm
by DrewPalmer04
Then they will just have to adjust the off set for -6, -4 etc

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 12:23 pm
by DrewPalmer04
lnevo wrote: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.
Good plan. I'll see which is easier lol

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 2:39 pm
by DrewPalmer04
NTP primary and failover/backup server implemented. Edited code on page 12 of thread.

Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 3:54 pm
by lnevo
DrewPalmer04 wrote:Then they will just have to adjust the off set for -6, -4 etc
You could just split the difference...

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Jan 31, 2013 4:07 pm
by DrewPalmer04
I'm not sure anyone will even use this code or module. But I figured it was worth posting. I've got the backup NTP server in the code. Which reduces odds of NTP time failure. Might add a few more to completely remove the possibility

Re: Time for additional Ethernet add-on with PWM output

Posted: Wed Feb 13, 2013 10:03 am
by DrewPalmer04
Roberto: One last thing I would like to do...

Any way for the ethernet module to send a PWM percentage to make the portal "think" it is a Radion value? I would like the percentage to display on the portal under "Red" for PWM pin 9 value and "Green" for pin 6 value.

I've tried to think of ways to accomplish this, but I'm coming up short :(

Thanks as always!!

P.s. the code has change a bit versus page 12 of the thread..but it's basically still the same as what you see on page 12 at the top. :)

Re: Time for additional Ethernet add-on with PWM output

Posted: Wed Feb 13, 2013 12:15 pm
by rimai
You need to do that in the main unit for it to work.

Re: Time for additional Ethernet add-on with PWM output

Posted: Wed Feb 20, 2013 9:27 am
by DrewPalmer04
CODE UPDATE:

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...

Re: Time for additional Ethernet add-on with PWM output

Posted: Wed Feb 20, 2013 11:15 am
by DrewPalmer04
Also looking for suggestions/improvements/thoughts. If you have implemented this let me know too!!!

Re: Time for additional Ethernet add-on with PWM output

Posted: Fri Feb 22, 2013 7:29 am
by DrewPalmer04
I've been playing with the idea of how to send info from one arduino to the RA. I'll use the serial communications. I need to send a BYTE and then have the RA receive the byte incomingbyte incomingbyte=Serial.read();
But here is where I'm coming up short. What do I do with the byte once it is read? How do I get this to replace the "0" on RFR and RFG (radian values). of course I'll have different bytes of info for each.


Also, related to this thread:
I've gotten a Chinese version of the Uno/Ethernet combo. It is working great thus far and is a CHEAPER option for everyone at $25 (shipping included) versus $60(+or-) +shipping for the one I've been using so far. Super easy to patch the wifi cable into it FYI.

Time for additional Ethernet add-on with PWM output

Posted: Fri Feb 22, 2013 8:24 am
by lnevo
SetChannel(byte channel, byte value) seems to be the function to write your byte to whichever radion channel you want. The rest of the functions in the RF class are for setting slopes.

Re: Time for additional Ethernet add-on with PWM output

Posted: Fri Feb 22, 2013 8:47 am
by DrewPalmer04
hmmm...so in theory. I write the received byte to SetChannel() and it'll display on the portal? This is me trying to "fool" the portal after all to know my % of brightness off my ethernet module lol...I'd just prefer to know my % values at a glance versus Serial.print() I have to use now.

Time for additional Ethernet add-on with PWM output

Posted: Fri Feb 22, 2013 11:07 am
by lnevo
Yeah, it should set the channel even though nothing is written there.. Theoretically, there may be other code in the way that Im not aware of.

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Mar 14, 2013 8:40 am
by DrewPalmer04
Updated page 12 to include the link to the build list/materials needed. :)

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Mar 14, 2013 8:43 am
by lnevo

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Mar 14, 2013 8:47 am
by DrewPalmer04
Hey, thanks...it's been updated!

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Mar 28, 2013 10:39 am
by DrewPalmer04
Sorry losing my mind.... :lol:

Updated page 12 of thread.

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Mar 28, 2013 11:30 am
by lnevo
Which thread? what did you update?

Re: Time for additional Ethernet add-on with PWM output

Posted: Thu Mar 28, 2013 11:33 am
by DrewPalmer04
EDIT:
I should have been more clear...

Security option issue with the portal and Ethernet module. It must [<--Not 100% true] be disabled. That's all I added


I don't use security....but anyone can add this to the RA side of the code...

Use below for security option (IF needed):
ReefAngel SIDE
"key" must match on code and portal

Code: Select all

ReefAngel.Portal("username","key");

Re: Time for additional Ethernet add-on with PWM output

Posted: Tue Apr 09, 2013 5:07 pm
by topjimmy
I have been using this for a few weeks and it really does work well. I am having a problem with the pwm for my Leds. They light up fine, but they flash, it's so fast that I thought it was just glimmer at first. I am using steve's led drivers. They work fine straight off of the RA dimming. Any suggestions?

Re: Time for additional Ethernet add-on with PWM output

Posted: Tue Apr 09, 2013 6:10 pm
by DrewPalmer04
Sounds like you don't have enough LEDs in the string. The driver is "protecting" itself. Either reduce the mA output from the driver or add more LEDs. That's what it sounds like to me :)