Whenever someone visits a page on my website www.janhimself.de the cat waves it's arm for a while. At night though I need some silence. So I built in a RGB LED which changes its color whenever a new pageview happens.
All you need is:
a Lucky Cat
an arduino ethernet
a RGB LED
two small yellow LEDs
a light sensor
a servo
and a two digit seven segment display (I harvested mine from an old stereo and built a little circuit using some resistors and two shift registers)
Step 1: The Servo
(I coded something like a time delay into the software part, so that the servo does only swing the arm once every 20 seconds. So if there would be multiple pageviews in that time, the counter would count them, but the arm just moves every 20 seconds until the work is done)
Step 2: Buttons and LEDs
button one is connected to Ground (GND) and the reset pin of the arduino.
The second one is to manually start the RGB LED, because it's always fun to change the color of an LED. It's connected to Pin 7 and +5V. And to pull the pin low there's a resistor (10K) connected to GND.
The RGB LED is connected to Pin 17 to 19 on the arduino. (Would be better to connect them to the PWM pins)
The yellow LEDs are attached to Pin 16
The servo is attached to Pin 6 (and +5V and GND)
The display uses Pin 2 as LatchPin, Pin 3 as DataPin and Pin 4 as ClockPin. It's juice it gets from +5V and GND
The light resistor is attached to analogue pin 1 and +5V and to GND using some resitors (2.4K)
Choose the correct resistors for your leds for example by using ElectroDroid on your smartphone.
Step 3: The Cats Firmware
These counts are shown on the display. For the movements of the arm there's another counter so that multiple arm movements can be processed independent of the actual website-hits. That's because the arm swings a while after being hit by the servo.
The arduino checks the light so that at night, the servo won't work but the RGB LED will change it's color everytime a hit on the website happens (this part happens without a delay)
Here's the code:
/*
Web Server
Webserver listens to the web and moves a servo
LightSensor checks the light so that the servo isn't move when it's dark
A seven segment display works with the help of shiftregisters to show a counter
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 178, 188};
//for Digits:
int latchPin = 2;//muss noch angeschlossen werden
int clockPin = 4;
int dataPin = 3;
int yellowPin = 16;
int redPin = 18;
int bluePin = 17;
int greenPin = 19;
int btnPin = 7;
//colours
int red;
int green;
int blue;
int yellow;
int ydir; //direction of Yellow fade
//digit is the array for numbers 192 for 0, 249 for 1,... 255 for nothing and 191 for -
byte digit[] ={192, 249, 164, 176, 153, 146, 130, 248, 128, 144, 255, 191, 225, 163, 171, 198, 167, 123};
int dig1;
int dig2;
int number;
int light;
//light sensor:
int lightPin = 1;//light sensor
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
Servo myservo; //create servo object to control servo
int count = 0;
//time
unsigned long previousMillis = 0;
unsigned long currentMil = 0;
unsigned long previousMil = 0;
unsigned long mil = 0;
boolean timepassed = true;
void setup()
{
myservo.attach(6); // attaches the servo on pin 6
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(yellowPin, OUTPUT);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(btnPin, INPUT);//switch
Serial.begin(9600);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, digit[11]);//ones
shiftOut(dataPin, clockPin, MSBFIRST, digit[11]);//tens
digitalWrite(latchPin, HIGH);
number = 0;
red = 0;
green = 0;
blue = 0;
yellow = 250;
ydir = 1;
analogWrite(yellowPin, yellow);
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
myservo.write(0);
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop()
{
//randomSeed(analogRead(A0)); //Yellow random
//yellow = random(111, 256);
yellow = yellow + (1 * ydir); //kind of fade
if (yellow == 255) ydir= -1;
if (yellow == 110) ydir = 1;
//Serial.println(yellow);
analogWrite(yellowPin, yellow);//Eyes on
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
count = count +1;//there was a request
number = number+1;//Counter
SevenSegDis();//Display
if (number == 99) { //so the 100 is missing :( but who cares
//digitalWrite(yellowPin, HIGH); //not needed anymore because yellowPin is analogWrite all the time
number = 0;
}
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
randomSeed(analogRead(A0));
red = random(256);
randomSeed(analogRead(A0));
green = random(256);
randomSeed(analogRead(A0));
blue = random(256);
Serial.print("Servo: ");
Serial.println(myservo.read());
Serial.print("Timepassed: ");
Serial.println(timepassed);
Serial.print("Count: ");
Serial.println(count);
Serial.print("Number: ");
Serial.println(number);
Serial.print("Mil: ");
Serial.println(mil);
Serial.print("Licht: ");
Serial.println(light);
Serial.print("red: ");
Serial.println(red);
Serial.print("green: ");
Serial.println(green);
Serial.print("blue: ");
Serial.println(blue);
}
lightsens(); //checks the light
time();// checks the time
if (light <99 && timepassed == true && count >0 ){//so when its dark the servo doesn't work and
myservo.attach(6);//attaches Servo to Pin6 again
if (myservo.read()== 0 ) {
myservo.write(180); //arm up
timepassed = false;
count = count -1;
}
else if (myservo.read() == 180) {
myservo.write(0);//arm down
timepassed = false;
count = count -1;
}
delay(1000);
myservo.detach();//detaches Servo
//turn lights of if servo is running
analogWrite(redPin, 0);
analogWrite(greenPin, 0);
analogWrite(bluePin, 0);
}
else if (light >=99 && count >0){//so when its dark the light changes with every hit on the website
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
count = count-1;
timepassed = false;
}
if (digitalRead(btnPin) == HIGH){ //check if button is pressed
randomSeed(analogRead(A0));
red = random(256);
randomSeed(analogRead(A0));
green = random(256);
randomSeed(analogRead(A0));
blue = random(256);
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
}
//----Part two: Seven Segments Display
void SevenSegDis() {//controls display with two shift registers
number = constrain(number, 0, 99);//number >=0 and <99 because of display range
if (number<10){
dig1 = 10; //shows nothing
dig2 = number; //ones
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, digit[dig2]);//ones
shiftOut(dataPin, clockPin, MSBFIRST, digit[dig1]);//tens here nothing
digitalWrite(latchPin, HIGH);
}
else {
dig1 = number/10;// first digit tens
dig2 = number - dig1*10; //second digit ones
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, digit[dig2]);
shiftOut(dataPin, clockPin, MSBFIRST, digit[dig1]);
digitalWrite(latchPin, HIGH);
}
}
//---------Part Three: the light sensor part
void lightsens() {
light = analogRead(lightPin);
light /= 10;
}
//---------- Part Four: the time thingy
void time (){
currentMil = millis();
if (currentMil < previousMil) {// if millis overflows
mil += 34359738 - previousMil + currentMil;
}
else { // if millis has not overflown
mil += currentMil - previousMil;
if (mil >25000){//if 20 sec. passed
timepassed = true;//resets the timepassed to true for the servo
mil = mil-25000;
}
previousMil = currentMil;
}
}









































Visit Our Store »
Go Pro Today »




i love the idea of storing a .gif and counting the requests for it .Its a nice workaround for people who don't have a host that supports scripts such as google blogger.Could i request the sketch pls ? as i have a bell here waiting to ring when i get a hit on runawaybrainz.blogspot.com ,but till now it hasn't been possible .
Best Regards
Rupert
the only thing you have to include into your blog or website is a gif, pointing to the arduino. I used dyndns to get something like a "fixed" ip, so the url for the gif is like mywebsite.dyndns.org/192.168.178.188/counter.gif where 192.168.178.188 is the arduinos ip here in my homenetwork. Include the gifs url into your website and it will be directed to the arduino. On the arduino site you'll need to include the part of the sketch here in the instructable starting with // listen for incoming clients...
Nice blog you have there
Jan
thanks!
The ip of the arduino here in my homenetwork is determined within it's sketch. So whenenver a browser asks for that .gif it's directed right to the arduino. The arduino does recognize that and send's back an 200ok line to the browser so that the browser finishes loading the website. So there's never a real image send, it's just used to point the browser to the arduino.
Anyway cool idea!
The seven segment displays setup could be part of another instructable I think. basically its 14 LEDs which are controlled by the arduino. Normally one would have to use 14 pins on the arduino, but with using shift registers, you just have to use three arduino pins to control the LEDs. I'll search for my notes on that and jot it down in another instructable