Code: Alles auswählen
//- -----------------------------------------------------------------------------------------------------------------------
// AskSin++
// 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//- -----------------------------------------------------------------------------------------------------------------------
// define this to read the device id, serial and device type from bootloader section
// #define USE_OTA_BOOTLOADER
#define USE_WOR
#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>
#include <AskSinPP.h>
#include <LowPower.h>
#include <Switch.h>
// we use a Pro Mini
// Arduino pin for the LED
// D4 == PIN 4 on Pro Mini
#define LED_PIN 4
// Arduino pin for the config button
// B0 == PIN 8 on Pro Mini
#define CONFIG_BUTTON_PIN 8
#define RELAY1_PIN 17
#define RELAY2_PIN 16
#define LOW_ACTIVE 0x00
#define ENABLE_PIN 15 // A1
#define RELAY1_ON_PIN 6 // D6
#define RELAY1_OFF_PIN 3 // D3
#define RELAY2_ON_PIN 17 // A3
#define RELAY2_OFF_PIN 16 // A2
// number of available peers per channel
#define PEERS_PER_CHANNEL 8
// all library classes are placed in the namespace 'as'
using namespace as;
// define all device properties
const struct DeviceInfo PROGMEM devinfo = {
{0x12, 0x09, 0x02}, // Device ID
"GAR1251002", // Device Serial
{0x00,0x6c}, // Device Model
0x10, // Firmware Version
as::DeviceType::Switch, // Device Type
{0x01,0x00} // Info Bytes
};
/**
* Configure the used hardware
*/
typedef AvrSPI<10,11,12,13> RadioSPI;
typedef AskSin<StatusLed<LED_PIN>,BattSensor<AsyncMeter<InternalVCC>>,Radio<RadioSPI,2> > Hal;
DEFREGISTER(Reg0,DREG_INTKEY,DREG_LEDMODE,MASTERID_REGS,DREG_LOWBATLIMIT)
class SwList0 : public RegList0<Reg0> {
public:
SwList0(uint16_t addr) : RegList0<Reg0>(addr) {}
void defaults () {
clear();
lowBatLimit(22);
}
};
/*
DEFREGISTER(Reg1,DREG_INTKEY,DREG_LEDMODE,MASTERID_REGS,DREG_LOWBATLIMIT)
class SwList1 : public RegList1<Reg1> {
public:
SwList1(uint16_t addr) : RegList1<Reg1>(addr) {}
void defaults () {
clear();
}
};
*/
// this class controls the pin high/low sequence
class SwAlarm : public Alarm {
private:
uint8_t pin;
uint8_t time;
uint8_t state;
public:
SwAlarm () : Alarm(0), pin(0), time(0), state(0) {
async(true);
}
virtual ~SwAlarm () {}
virtual void trigger (AlarmClock& clock) {
switch(state) {
case 1:
set(millis2ticks(500));
digitalWrite(ENABLE_PIN,HIGH);
break;
case 2:
set(millis2ticks(time));
digitalWrite(pin,HIGH);
break;
case 3:
set(millis2ticks(100));
digitalWrite(pin,LOW);
break;
case 4:
digitalWrite(ENABLE_PIN,LOW);
state=0;
break;
}
if( state != 0 ) {
++state;
clock.add(*this);
}
}
bool press (uint8_t p,uint8_t t,AlarmClock& clock) {
// check that we are not running
if( state == 0 ) {
pin = p;
time = t;
state = 1;
trigger(clock);
return true;
}
return false;
}
};
class SwChannel : public SwitchChannel<Hal, PEERS_PER_CHANNEL, SwList0> {
protected:
uint8_t pinoff;
SwAlarm swalarm;
public:
typedef SwitchChannel<Hal, PEERS_PER_CHANNEL, SwList0> BaseChannel;
virtual ~SwChannel () {}
void init (uint8_t pon,uint8_t poff) {
DPRINTLN("### SwitchChannel - init");
BaseChannel::init(pon,false);
pinoff = poff;
pinMode(pinoff,OUTPUT);
}
// replace standard switch method - trigger alarm to start sequence
// virtual void switchState(__attribute__((unused)) uint8_t oldstate,uint8_t newstate) {
virtual void switchState(__attribute__((unused)) uint8_t oldstate,uint8_t newstate,__attribute__((unused)) uint32_t delay) {
DPRINTLN("### SwitchChannel - switchState");
bool pressed = false;
if( newstate == AS_CM_JT_ON ) {
pressed = swalarm.press(pin,250,sysclock);
}
else if ( newstate == AS_CM_JT_OFF ) {
pressed = swalarm.press(pinoff,62,sysclock);
}
if( pressed == true ) {
BaseChannel::changed(true);
}
}
};
// typedef MultiChannelDevice<Hal, SwChannel, 2> SwitchTypeX;
// setup the device with channel type and number of channels
// class SwitchType : public MultiChannelDevice<Hal,SwitchChannel<Hal,PEERS_PER_CHANNEL,SwList0>,2,SwList0> {
class SwitchType : public MultiChannelDevice<Hal,SwChannel,2,SwList0> {
public:
typedef MultiChannelDevice<Hal,SwitchChannel<Hal,PEERS_PER_CHANNEL,SwList0>,2,SwList0> DevType;
SwitchType (const DeviceInfo& i,uint16_t addr) : DevType(i,addr) {}
virtual ~SwitchType () {}
virtual void configChanged () {
DevType::configChanged();
uint8_t lowbat = this->getList0().lowBatLimit();
// DDECLN(lowbat);
if( lowbat > 0 ) {
battery().low(lowbat);
}
led().set(this->getList0().ledMode());
}
};
Hal hal;
SwitchType sdev(devinfo,0x20);
ConfigToggleButton<SwitchType> cfgBtn(sdev);
#ifndef USE_WOR
BurstDetector<Hal> bd(hal);
#endif
void initPeerings (bool first) {
// create internal peerings - CCU2 needs this
if( first == true ) {
HMID devid;
sdev.getDeviceID(devid);
for( uint8_t i=1; i<=sdev.channels(); ++i ) {
Peer ipeer(devid,i);
sdev.channel(i).peer(ipeer);
}
}
}
void setup () {
DINIT(57600,ASKSIN_PLUS_PLUS_IDENTIFIER);
bool first = sdev.init(hal);
sdev.channel(1).init(RELAY1_ON_PIN, RELAY1_OFF_PIN);
sdev.channel(2).init(RELAY2_ON_PIN, RELAY2_OFF_PIN);
buttonISR(cfgBtn,CONFIG_BUTTON_PIN);
initPeerings(first);
#ifndef USE_WOR
// start burst detection
bd.enable(sysclock);
#endif
// stay on for 15 seconds after start
hal.activity.stayAwake(seconds2ticks(15));
// measure battery every hour
hal.battery.init(seconds2ticks(60UL*60),sysclock);
sdev.initDone();
}
void loop() {
bool worked = hal.runready();
bool poll = sdev.pollRadio();
if( worked == false && poll == false ) {
hal.activity.savePower<Sleep<> >(hal);
}
}