// Ethernet connect christmas light controller
// Written by Brian Schulteis, Creative Commons License, 2011
// For use on an ENC28J60 ethernet chip with thiseldo's Ethershield library
// Written for use on a Teensy++ 2.0, using Arduino 1.0
#include "EtherShield.h"
static byte mymac[6] = {
0x54,0x55,0x58,0x10,0x00,0x25};
static byte myip[4] = {
192,168,1,1}; // This will be the IP address of the Arduino
static byte mynetmask[4] = {
255,255,255,0}; // Netmask used on my network
static byte gwip[4] = {
192,168,1,2}; // IP Address of my firewall on my LAN
#define MYNETPORT 6058 // I picked some random port number for this to answer on. Not exactly sure why.
#define BUFFER_SIZE 550 // default setting in the example sketch I grabbed for the ethershield
static byte buf[BUFFER_SIZE+1];
const int speeds[8] = {
64,96,128,192,256,320,400,512 }; // Array containing the speed settings.
byte currentMode = 1; // Start in mode 1
int currentSpeed = 64; // default to slow speed
byte lightVariable = 1; // initialize the counters
byte tempVariable = 1;
EtherShield es=EtherShield(); // Object oriented programming FTW.. I love libraries.
void changeMode(char* modeRequested) {
currentMode = atoi(modeRequested);
if ((currentMode > 8) or (currentMode < 1)) {
currentMode=1;
}
for (int i=9; i < 20; i++) {
digitalWrite(i, LOW); // It's best to turn all the lights off before starting a different mode.
}
lightVariable = 1;
tempVariable = 1;
tone(7, (100 * currentMode), 200); // Give a beep when the mode is changed, vary frequency based on requested mode.
}
void changeSpeed(char* speedRequested) {
if ((atoi(speedRequested) > 0) and (atoi(speedRequested) < 9)) {
currentSpeed = speeds[(atoi(speedRequested)-1)];
tone(7, (1200 * atoi(speedRequested)), 200); // Same deal, beep for speed changes, varied based on requested speed.
}
}
boolean checkEthernet() {
int plen, dat_p;
// read packet, handle ping and wait for a tcp packet:
dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
/* dat_p will be unequal to zero if there is a valid
* http get */
if (dat_p) {
if (buf[dat_p+5] == 'm') {
char temp = buf[dat_p+6];
changeMode(((char *)&temp));
dat_p=es.ES_fill_tcp_data_p(buf,0,PSTR(""));
es.ES_www_server_reply(buf,dat_p); // send web page data
dat_p=0;
return(true); // True meaning "yes, there was a mode change"
}
if (buf[dat_p+5] == 's') {
char temp = buf[dat_p+6];
changeSpeed(((char *)&temp));
dat_p=es.ES_fill_tcp_data_p(buf,0,PSTR(""));
es.ES_www_server_reply(buf,dat_p); // send web page data
dat_p=0;
return(false); // False, no mode change, speed change will get automatically rolled in to the main delay loop.
}
}
return(false); // False, nothing received from the ethernet chip.
}
void modeOne() { // This is a simple chasing pattern.
digitalWrite((lightVariable + 9), HIGH);
if (lightVariable < 10) { // there are actually two on at any one time, if we're at the end, we need to go back to the beginning.
digitalWrite((lightVariable + 10), HIGH);
}
else { // Pin 10 being the beginning.
digitalWrite(10, HIGH);
}
if (lightVariable == 1) { // Same kind of deal with turning them off, if we're at 1, the last light may still be on
digitalWrite(19, LOW); // so turn it off.
}
else {
digitalWrite((lightVariable + 8), LOW);
}
if (lightVariable == 10) {
lightVariable= 1;
}
else {
lightVariable++;
}
}
void modeTwo() { // Start at ends, light up towards middle, then start in middle and turn off towards ends.
if (lightVariable < 6) { // 1 - 5 turns them on
digitalWrite(lightVariable + 9, HIGH);
digitalWrite(20 - lightVariable, HIGH);
}
else { // 6 through 10 turns them off, like ships passing in the night.
digitalWrite(lightVariable + 9, LOW);
digitalWrite(20 - lightVariable, LOW);
}
if (lightVariable == 10) {
lightVariable= 1;
}
else {
lightVariable++;
}
}
void modeThree() { // The ever popular Knight Rider
if (lightVariable > 10) { // Go left
if (lightVariable == 11) {
tempVariable = 10; // I think this will get rewritten and not use tempVariable.
}
else {
tempVariable--;
}
if (tempVariable > 1) {
digitalWrite(tempVariable + 8, HIGH);
digitalWrite(tempVariable + 9, LOW);
}
else {
digitalWrite(tempVariable + 8, LOW);
}
if (tempVariable == 10) {
digitalWrite(tempVariable + 9, LOW);
}
}
else { // Go right
digitalWrite(lightVariable +9, HIGH);
if (lightVariable > 1) digitalWrite(lightVariable + 8, LOW);
}
if (lightVariable == 20) {
lightVariable= 2;
}
else {
lightVariable++;
}
}
void modeFour() { // Police light bar style
if (lightVariable < 6) {
if (lightVariable == 1) {
for (int h = 15; h < 20; h++) {
digitalWrite(h, LOW);
}
}
if ((lightVariable % 2) == 0) {
for (int h = 9; h < 15; h++) {
digitalWrite(h, HIGH);
}
}
else {
for (int h = 9; h < 15; h++) {
digitalWrite(h, LOW);
}
}
}
else {
if ((lightVariable % 2) == 0) {
for (int h = 15; h < 20; h++) {
digitalWrite(h, HIGH);
}
}
else {
for (int h = 15; h < 20; h++) {
digitalWrite(h, LOW);
}
}
}
if (lightVariable == 10) {
lightVariable= 1;
}
else {
lightVariable++;
}
}
void modeFive() { // All on, then all back off in a VU meter kind of way
if (lightVariable < 11) { // Turning them on
digitalWrite(lightVariable + 9, HIGH);
}
else { // Turn them back off
digitalWrite(30 - lightVariable, LOW);
}
if (lightVariable == 20) {
lightVariable= 1;
}
else {
lightVariable++;
}
}
void modeSix() { // double chaser mode
if (tempVariable == lightVariable) { // This can only happen when this mode is first engaged.
tempVariable = 5;
}
digitalWrite(lightVariable + 9, HIGH);
digitalWrite(tempVariable + 9, HIGH);
if (lightVariable > 1) {
digitalWrite(lightVariable + 8, LOW);
}
else {
digitalWrite(19, LOW);
}
if (tempVariable > 1) {
digitalWrite(tempVariable + 8, LOW);
}
else {
digitalWrite(19, LOW);
}
if (lightVariable == 10) {
lightVariable= 1;
}
else {
lightVariable++;
}
if (tempVariable == 10) {
tempVariable= 1;
}
else {
tempVariable++;
}
}
void modeSeven() { // Start at ends, light up towards middle, then start at ends and turn off towards middle
if (lightVariable < 6) { // 1 - 5 turns them on
digitalWrite(lightVariable + 9, HIGH);
digitalWrite(20 - lightVariable, HIGH);
}
else { // 6 through 10 turns them off, like ships passing in the night.
tempVariable=lightVariable-5;
digitalWrite(tempVariable + 9, LOW);
digitalWrite(20 - tempVariable, LOW);
}
if (lightVariable == 10) {
lightVariable= 1;
}
else {
lightVariable++;
}
}
void modeSevenb() { // Odd man out mode - No longer used
digitalWrite(lightVariable + 9, HIGH);
if (lightVariable<10) {
digitalWrite(lightVariable + 10, LOW);
}
if (lightVariable == 2) {
digitalWrite(lightVariable + 8, LOW); // When we're starting the evens, we need to make sure to turn the first one off.
}
if ((lightVariable==9) or (lightVariable==10)) {
if (lightVariable==9) { // We're either doing all odd
lightVariable = 2;
}
if (lightVariable==10) { // or all even
lightVariable = 1; // Do the opposite the next time around.
}
}
else {
lightVariable += 2;
}
}
void modeEight() { // binary mode 10 bit, 2047 total
if (!lightVariable) { // See what I did there? -- if we've come back around to 0
if (digitalRead(18)) { // if bit 9 is already on
if (digitalRead(19)) { // and if bit 10 is already on
digitalWrite(18, LOW); // we got here because they're both on. We've gone all the way around
digitalWrite(19, LOW);
}
else {
digitalWrite(19, HIGH); // we got here because only 18 was on, this is the first lap
digitalWrite(18, LOW);
}
}
else {
digitalWrite(18, HIGH); // if 9 wasn't on, it's time to turn it on, we're at 511 or 1535, doesn't really matter
}
PORTC = lightVariable; // this turns off all the other bits (1-8)
lightVariable++;
}
else {
PORTC = lightVariable;
lightVariable++; // lightVariable is a byte, so it goes 0-255, with automatic rollover..
}
}
void setup(){
for (int i=9; i < 20; i++) {
pinMode(i, OUTPUT);
}
es.ES_enc28j60SpiInit();
// initialize enc28j60
es.ES_enc28j60Init(mymac,20 );
// init the ethernet/ip layer:
es.ES_init_ip_arp_udp_tcp(mymac,myip, MYNETPORT);
// Serial.begin(9600);
}
void loop(){
unsigned long currentTime = millis();
while ((!checkEthernet()) and ((millis()-currentTime) < currentSpeed)) {
/* I think this is an elegant way to delay, while checking for incoming commands over ethernet.
any speed changes automatically get rolled it, a mode change will break it out of this delay
automatically without any more delay. After the appropriate delay has elapsed, or it otherwise
breaks out of this delay loop, it calls the proper routine which makes one step forward along
it's pattern's progression. It then returns to this delay. Totally elegant. */
}
switch (currentMode) {
case 1:
modeOne();
break;
case 2:
modeTwo();
break;
case 3:
modeThree();
break;
case 4:
modeFour();
break;
case 5:
modeFive();
break;
case 6:
modeSix();
break;
case 7:
modeSeven();
break;
case 8:
modeEight();
break;
}
}