diff --git a/ITS_Open_direct_2fb/ITS_Open_direct_2fb.ino b/ITS_Open_direct_2fb/ITS_Open_direct_2fb.ino index e2c97db..703e99d 100644 --- a/ITS_Open_direct_2fb/ITS_Open_direct_2fb.ino +++ b/ITS_Open_direct_2fb/ITS_Open_direct_2fb.ino @@ -16,6 +16,7 @@ Based on the Ethernet to Thingspeak exaple by Hans Scharler #include #include "APIKey.h" +#include "TimerOne.h" byte mac[] = { 0xD4, 0xBA, 0xD9, 0x9A, 0x7C, 0x95 }; // Must be unique on local network @@ -32,6 +33,17 @@ String currentLine = ""; // string to hold the text from server int hsopen; int ethernetstatus; +int ledtimer =0; +const int ledspan =20; + +int pingtimer =-1; +const int pingspan =50; + +int checktimer = 0; +const int checkspan =200; + +int update = 0; + //debug options boolean debug = true; @@ -63,6 +75,10 @@ void setup() // Start Ethernet on Arduino setEth(-1); setRoom(2); + + Timer1.initialize(100000); // 10 mal die Sekunde + Timer1.attachInterrupt(setLeds); + startEthernet(); delay(1000); @@ -74,6 +90,7 @@ void setup() void loop() { readButtons(); + launchUpdate(); } @@ -91,6 +108,13 @@ void readButtons(){ } } +void launchUpdate(){ + if(update==1){ + RequestPing(); + update = 0; + } +} + void startEthernet() { client.stop(); @@ -126,49 +150,91 @@ void startEthernet() } void setLeds(){ - switch(ethernetstatus){ - case 0:{ // ethernet fail - // should become blink red - analogWrite(rlight, 63); - analogWrite(glight, 0); - break; - } - case -1:{ // ethernet unknown - // should become fade green + if (pingtimer>=0) + { + // blink like crazy + if((pingtimer/2)%2 ==1){ + analogWrite(rlight, 255); + analogWrite(glight, 255); + }else{ analogWrite(rlight, 0); - analogWrite(glight, 63); - break; + analogWrite(glight, 0); } - case 1:{ // ethernet ok - switch(hsopen){ - case 0:{ // closed + pingtimer--; + }else{ + switch(ethernetstatus){ + case 0:{ // ethernet fail + //blink red + if(ledtimer < (ledspan/2)){ analogWrite(rlight, 255); - analogWrite(glight, 0); - break; - } - case 1:{ // open + }else{ analogWrite(rlight, 0); - analogWrite(glight, 255); - break; } - case 2:{ // wait - // should become fade red and green - analogWrite(rlight, 127); - analogWrite(glight, 127); - break; - } - case -1:{ // unknown - // should become fade red - analogWrite(rlight, 63); - analogWrite(glight, 63); - break; - } - } - break; + analogWrite(glight, 0); + break; + } + case -1:{ // ethernet unknown + // fade green + if(ledtimer < (ledspan/2)){ + analogWrite(glight, (255/(ledspan/2)*ledtimer));//fade up + }else{ + analogWrite(glight, 255-(255/(ledspan/2)*(ledtimer-(ledspan/2))));//fade down + } + analogWrite(rlight, 0); + break; + } + case 1:{ // ethernet ok + switch(hsopen){ + case 0:{ // closed + //red + analogWrite(rlight, 255); + analogWrite(glight, 0); + break; + } + case 1:{ // open + // green + analogWrite(rlight, 0); + analogWrite(glight, 255); + break; + } + case 2:{ // wait + // fade red and green + if(ledtimer < (ledspan/2)){ + int tmp=(255/(ledspan/2)*ledtimer); + analogWrite(glight, tmp);//fade up + analogWrite(rlight, tmp);//fade up + + }else{ + int tmp = 255-(255/(ledspan/2)*(ledtimer-(ledspan/2))); + analogWrite(glight, tmp);//fade down + analogWrite(rlight, tmp);//fade down + } + break; + } + case -1:{ // unknown + // fade red + if(ledtimer < (ledspan/2)){ + analogWrite(rlight, (255/(ledspan/2)*ledtimer));//fade up + }else{ + analogWrite(rlight, 255-(255/(ledspan/2)*(ledtimer-(ledspan/2))));//fade down + } + analogWrite(glight, 0); + break; + } + } + break; + } + } + ledtimer++; + if ( ledtimer >= ledspan ) { + ledtimer = 0; } } - - + checktimer++; + if ( checktimer >= checkspan ) { + checktimer = 0; + update=1; + } } void setEth(int statuss){ @@ -189,10 +255,16 @@ void setRoom(int statuss){ setLeds(); } + void RequestState() { TriggerServerReq("/status-s.php",0); } + +void RequestPing() { + TriggerServerReq("/ping-get.php?apikey="+pingAPIKey,1); +} + void TriggerServerReq(String s, int mode) { // attempt to connect, and wait a millisecond: if(debug){Serial.println("connecting to server... Status req");} @@ -261,6 +333,7 @@ int readServerStatus(int mode) { break; case 1: if(debug){Serial.println("Wink Wink");} + pingtimer = pingspan; break; } // close the connection to the server: diff --git a/ITS_Open_direct_2fb/TimerOne.cpp b/ITS_Open_direct_2fb/TimerOne.cpp new file mode 100755 index 0000000..7a52ae0 --- /dev/null +++ b/ITS_Open_direct_2fb/TimerOne.cpp @@ -0,0 +1,101 @@ +/* + * Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328 + * Original code by Jesse Tane for http://labs.ideo.com August 2008 + * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support + * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop + * + * This is free software. You can redistribute it and/or modify it under + * the terms of Creative Commons Attribution 3.0 United States License. + * To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ + * or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. + * + */ + +#include "TimerOne.h" + +TimerOne Timer1; // preinstatiate + +ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt +{ + Timer1.isrCallback(); +} + +void TimerOne::initialize(long microseconds) +{ + TCCR1A = 0; // clear control register A + TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer + setPeriod(microseconds); +} + +void TimerOne::setPeriod(long microseconds) +{ + long cycles = (F_CPU * microseconds) / 2000000; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2 + if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal + else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 + else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 + else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 + else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 + else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum + ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode + TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); + TCCR1B |= clockSelectBits; // reset clock select register +} + +void TimerOne::setPwmDuty(char pin, int duty) +{ + unsigned long dutyCycle = pwmPeriod; + dutyCycle *= duty; + dutyCycle >>= 10; + if(pin == 1 || pin == 9) OCR1A = dutyCycle; + else if(pin == 2 || pin == 10) OCR1B = dutyCycle; +} + +void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024) +{ + if(microseconds > 0) setPeriod(microseconds); + if(pin == 1 || pin == 9) { + DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin + TCCR1A |= _BV(COM1A1); // activates the output pin + } + else if(pin == 2 || pin == 10) { + DDRB |= _BV(PORTB2); + TCCR1A |= _BV(COM1B1); + } + setPwmDuty(pin, duty); + start(); +} + +void TimerOne::disablePwm(char pin) +{ + if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1 + else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2 +} + +void TimerOne::attachInterrupt(void (*isr)(), long microseconds) +{ + if(microseconds > 0) setPeriod(microseconds); + isrCallback = isr; // register the user's callback with the real ISR + TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit + sei(); // ensures that interrupts are globally enabled + start(); +} + +void TimerOne::detachInterrupt() +{ + TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit +} + +void TimerOne::start() +{ + TCCR1B |= clockSelectBits; +} + +void TimerOne::stop() +{ + TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits +} + +void TimerOne::restart() +{ + TCNT1 = 0; +} diff --git a/ITS_Open_direct_2fb/TimerOne.h b/ITS_Open_direct_2fb/TimerOne.h new file mode 100755 index 0000000..385b5c6 --- /dev/null +++ b/ITS_Open_direct_2fb/TimerOne.h @@ -0,0 +1,41 @@ +/* + * Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328 + * Original code by Jesse Tane for http://labs.ideo.com August 2008 + * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support + * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop + * + * This is free software. You can redistribute it and/or modify it under + * the terms of Creative Commons Attribution 3.0 United States License. + * To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ + * or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. + * + */ + +#include +#include + +#define RESOLUTION 65536 // Timer1 is 16 bit + +class TimerOne +{ + public: + + // properties + unsigned int pwmPeriod; + unsigned char clockSelectBits; + + // methods + void initialize(long microseconds=1000000); + void start(); + void stop(); + void restart(); + void pwm(char pin, int duty, long microseconds=-1); + void disablePwm(char pin); + void attachInterrupt(void (*isr)(), long microseconds=-1); + void detachInterrupt(); + void setPeriod(long microseconds); + void setPwmDuty(char pin, int duty); + void (*isrCallback)(); +}; + +extern TimerOne Timer1;