Added interrupt driven state check(ping request) and signaling (blinky stuff)

This commit is contained in:
Romedius Weiss 2015-12-27 10:14:19 +01:00
parent 6bebb3dcda
commit a4e419ca26
3 changed files with 251 additions and 36 deletions

View file

@ -16,6 +16,7 @@ Based on the Ethernet to Thingspeak exaple by Hans Scharler
#include <Ethernet.h> #include <Ethernet.h>
#include "APIKey.h" #include "APIKey.h"
#include "TimerOne.h"
byte mac[] = { 0xD4, 0xBA, 0xD9, 0x9A, 0x7C, 0x95 }; // Must be unique on local network 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 hsopen;
int ethernetstatus; 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 //debug options
boolean debug = true; boolean debug = true;
@ -63,6 +75,10 @@ void setup()
// Start Ethernet on Arduino // Start Ethernet on Arduino
setEth(-1); setEth(-1);
setRoom(2); setRoom(2);
Timer1.initialize(100000); // 10 mal die Sekunde
Timer1.attachInterrupt(setLeds);
startEthernet(); startEthernet();
delay(1000); delay(1000);
@ -74,6 +90,7 @@ void setup()
void loop() void loop()
{ {
readButtons(); readButtons();
launchUpdate();
} }
@ -91,6 +108,13 @@ void readButtons(){
} }
} }
void launchUpdate(){
if(update==1){
RequestPing();
update = 0;
}
}
void startEthernet() void startEthernet()
{ {
client.stop(); client.stop();
@ -126,49 +150,91 @@ void startEthernet()
} }
void setLeds(){ void setLeds(){
switch(ethernetstatus){ if (pingtimer>=0)
case 0:{ // ethernet fail {
// should become blink red // blink like crazy
analogWrite(rlight, 63); if((pingtimer/2)%2 ==1){
analogWrite(glight, 0); analogWrite(rlight, 255);
break; analogWrite(glight, 255);
} }else{
case -1:{ // ethernet unknown
// should become fade green
analogWrite(rlight, 0); analogWrite(rlight, 0);
analogWrite(glight, 63); analogWrite(glight, 0);
break;
} }
case 1:{ // ethernet ok pingtimer--;
switch(hsopen){ }else{
case 0:{ // closed switch(ethernetstatus){
case 0:{ // ethernet fail
//blink red
if(ledtimer < (ledspan/2)){
analogWrite(rlight, 255); analogWrite(rlight, 255);
analogWrite(glight, 0); }else{
break;
}
case 1:{ // open
analogWrite(rlight, 0); 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;
} }
analogWrite(glight, 0);
break;
} }
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){ void setEth(int statuss){
@ -189,10 +255,16 @@ void setRoom(int statuss){
setLeds(); setLeds();
} }
void RequestState() { void RequestState() {
TriggerServerReq("/status-s.php",0); TriggerServerReq("/status-s.php",0);
} }
void RequestPing() {
TriggerServerReq("/ping-get.php?apikey="+pingAPIKey,1);
}
void TriggerServerReq(String s, int mode) { void TriggerServerReq(String s, int mode) {
// attempt to connect, and wait a millisecond: // attempt to connect, and wait a millisecond:
if(debug){Serial.println("connecting to server... Status req");} if(debug){Serial.println("connecting to server... Status req");}
@ -261,6 +333,7 @@ int readServerStatus(int mode) {
break; break;
case 1: case 1:
if(debug){Serial.println("Wink Wink");} if(debug){Serial.println("Wink Wink");}
pingtimer = pingspan;
break; break;
} }
// close the connection to the server: // close the connection to the server:

101
ITS_Open_direct_2fb/TimerOne.cpp Executable file
View file

@ -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;
}

41
ITS_Open_direct_2fb/TimerOne.h Executable file
View file

@ -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 <avr/io.h>
#include <avr/interrupt.h>
#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;