├── documentation ├── RFM69HCW_BOB.pdf └── RFM69HCW-V1.1.pdf ├── Libraries └── Arduino │ └── RFM69 │ ├── examples │ ├── LowPowerLab_examples │ │ ├── MotionMote │ │ │ ├── OLD │ │ │ │ ├── MotionMote.jpg │ │ │ │ ├── MotionMote.ino │ │ │ │ └── MotionMote_CC-BY-SA.svg │ │ │ └── MotionMote.ino │ │ ├── RandomNumbers │ │ │ └── RandomNumbers.ino │ │ ├── DeepSleep │ │ │ └── DeepSleep.ino │ │ ├── SonarMote │ │ │ ├── SonarMote_DistanceReader │ │ │ │ └── SonarMote_DistanceReader.ino │ │ │ └── SonarMote_DistanceTracker │ │ │ │ └── SonarMote_DistanceTracker.ino │ │ ├── Struct_send │ │ │ └── Struct_send.ino │ │ ├── Struct_receive │ │ │ └── Struct_receive.ino │ │ ├── GarageMote_base │ │ │ └── GarageMote_base.ino │ │ ├── PiGateway │ │ │ ├── PiGateway.ino │ │ │ └── PiGateway_withLCD.ino │ │ ├── WirelessProgramming_gateway │ │ │ └── WirelessProgramming_gateway.ino │ │ ├── Gateway │ │ │ └── Gateway.ino │ │ ├── Node │ │ │ └── Node.ino │ │ ├── WirelessProgramming_node │ │ │ └── WirelessProgramming_node.ino │ │ ├── MailboxNotifier │ │ │ └── MailboxNotifier4_sender.ino │ │ ├── TxRxBlinky │ │ │ └── TxRxBlinky.ino │ │ ├── DoorBellMote │ │ │ └── DoorBellMote.ino │ │ ├── OLEDMote │ │ │ └── OLEDMote.ino │ │ ├── PulseMeter │ │ │ └── PulseMeter.ino │ │ ├── WeatherNode │ │ │ └── WeatherNode.ino │ │ ├── MightyBoostControl │ │ │ └── MightyBoostControl.ino │ │ └── IOShield │ │ │ └── IOShield.ino │ └── SFE_RFM69HCW_example │ │ └── SFE_RFM69HCW_example.ino │ ├── library.json │ ├── keywords.txt │ ├── .travis.yml │ ├── RFM69_ATC.h │ ├── README.md │ └── RFM69.h ├── .gitignore └── README.md /documentation/RFM69HCW_BOB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/RFM69HCW_Breakout/HEAD/documentation/RFM69HCW_BOB.pdf -------------------------------------------------------------------------------- /documentation/RFM69HCW-V1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/RFM69HCW_Breakout/HEAD/documentation/RFM69HCW-V1.1.pdf -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/MotionMote/OLD/MotionMote.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/RFM69HCW_Breakout/HEAD/Libraries/Arduino/RFM69/examples/LowPowerLab_examples/MotionMote/OLD/MotionMote.jpg -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RFM69", 3 | "keywords": "rf, radio, wireless, spi", 4 | "description": "RFM69 library for RFM69W, RFM69HW, RFM69CW, RFM69HCW (semtech SX1231, SX1231H)", 5 | "repository": 6 | { 7 | "type": "git", 8 | "url": "https://github.com/LowPowerLab/RFM69.git" 9 | }, 10 | "frameworks": "arduino", 11 | "platforms": "atmelavr" 12 | } 13 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map for RFM69 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ####################################### 10 | # Instances (KEYWORD2) 11 | ####################################### 12 | RFM69 KEYWORD2 13 | RFM69_ATC KEYWORD2 14 | 15 | ####################################### 16 | # Methods and Functions (KEYWORD2) 17 | ####################################### 18 | initialize KEYWORD2 19 | setAddress KEYWORD2 20 | canSend KEYWORD2 21 | send KEYWORD2 22 | sendWithRetry KEYWORD2 23 | receiveDone KEYWORD2 24 | ACKReceived KEYWORD2 25 | sendACK KEYWORD2 26 | setFrequency KEYWORD2 27 | getFrequency KEYWORD2 28 | encrypt KEYWORD2 29 | setCS KEYWORD2 30 | readRSSI KEYWORD2 31 | promiscuous KEYWORD2 32 | setHighPower KEYWORD2 33 | sleep KEYWORD2 34 | readReg KEYWORD2 35 | writeReg KEYWORD2 36 | setNetwork KEYWORD2 37 | ACKRequested KEYWORD2 38 | setPowerLevel KEYWORD2 39 | readTemperature KEYWORD2 40 | rcCalibration KEYWORD2 41 | readAllRegs KEYWORD2 42 | enableAutoPower KEYWORD2 43 | 44 | ####################################### 45 | # Constants (LITERAL1) 46 | ####################################### 47 | RF69_315MHZ LITERAL1 48 | RF69_433MHZ LITERAL1 49 | RF69_868MHZ LITERAL1 50 | RF69_915MHZ LITERAL1 51 | ####################################### 52 | # Variables/Volatiles (LITERAL2) 53 | ####################################### 54 | DATA LITERAL2 55 | DATALEN LITERAL2 56 | SENDERID LITERAL2 57 | TARGETID LITERAL2 58 | PAYLOADLEN LITERAL2 59 | ACK_REQUESTED LITERAL2 60 | ACK_RECEIVED LITERAL2 61 | RSSI LITERAL2 62 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/MotionMote/OLD/MotionMote.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 sender/node sketch for motion sensor 2 | // PIR motion sensor connected to D3 (INT1) 3 | // When RISE happens on D3, the sketch transmits a "MOTION" msg to receiver Moteino and goes back to sleep 4 | // In sleep mode, Moteino + PIR motion sensor use about ~78uA 5 | // Library and code by Felix Rusu - felix@lowpowerlab.com 6 | // Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ 7 | 8 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 9 | #include //get it here: https://github.com/lowpowerlab/spiflash 10 | #include //get library from: https://github.com/LowPowerLab/LowPower 11 | 12 | #define NODEID 18 //unique for each node on same network 13 | #define NETWORKID 100 //the same on all nodes that talk to each other 14 | #define GATEWAYID 1 15 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 16 | //#define FREQUENCY RF69_433MHZ 17 | //#define FREQUENCY RF69_868MHZ 18 | #define FREQUENCY RF69_915MHZ 19 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 20 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 21 | #define ACK_TIME 30 // max # of ms to wait for an ack 22 | #define LED 9 // Moteinos have LEDs on D9 23 | #define SERIAL_BAUD 115200 24 | #define MOTIONPIN 1 //hardware interrupt 1 (D3) 25 | 26 | RFM69 radio; 27 | volatile boolean motionDetected=false; 28 | 29 | void setup() { 30 | Serial.begin(SERIAL_BAUD); 31 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 32 | #ifdef IS_RFM69HW 33 | radio.setHighPower(); //uncomment only for RFM69HW! 34 | #endif 35 | radio.encrypt(ENCRYPTKEY); 36 | attachInterrupt(MOTIONPIN, motionIRQ, RISING); 37 | char buff[50]; 38 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 39 | Serial.println(buff); 40 | } 41 | 42 | void motionIRQ() 43 | { 44 | motionDetected=true; 45 | } 46 | 47 | void loop() { 48 | if (motionDetected) 49 | { 50 | if (radio.sendWithRetry(GATEWAYID, "MOTION", 6)) 51 | { 52 | Serial.println(" ok!"); 53 | Blink(LED,3); 54 | } 55 | else Serial.println(" nothing..."); 56 | motionDetected=false; 57 | } 58 | radio.sleep(); 59 | LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 60 | } 61 | 62 | void Blink(byte PIN, int DELAY_MS) 63 | { 64 | pinMode(PIN, OUTPUT); 65 | digitalWrite(PIN,HIGH); 66 | delay(DELAY_MS); 67 | digitalWrite(PIN,LOW); 68 | } 69 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | 5 | # Cache PlatformIO packages using Travis CI container-based infrastructure 6 | sudo: false 7 | cache: 8 | directories: 9 | - "~/.platformio" 10 | 11 | env: 12 | - PLATFORMIO_CI_SRC=Examples/DeepSleep 13 | - PLATFORMIO_CI_SRC=Examples/DoorBellMote 14 | - PLATFORMIO_CI_SRC=Examples/GarageMote 15 | - PLATFORMIO_CI_SRC=Examples/GarageMote_base 16 | - PLATFORMIO_CI_SRC=Examples/Gateway 17 | - PLATFORMIO_CI_SRC=Examples/IOShield 18 | - PLATFORMIO_CI_SRC=Examples/MailboxNotifier 19 | - PLATFORMIO_CI_SRC=Examples/MightyBoostControl 20 | - PLATFORMIO_CI_SRC=Examples/MightyHat 21 | - PLATFORMIO_CI_SRC=Examples/MotionMote/MotionMote.ino 22 | - PLATFORMIO_CI_SRC=Examples/Node 23 | - PLATFORMIO_CI_SRC=Examples/OLEDMote 24 | - PLATFORMIO_CI_SRC=Examples/PiGateway/PiGateway.ino 25 | # - PLATFORMIO_CI_SRC=Examples/PiGateway/PiGateway_withLCD.ino 26 | - PLATFORMIO_CI_SRC=Examples/PulseMeter 27 | - PLATFORMIO_CI_SRC=Examples/RandomNumbers 28 | - PLATFORMIO_CI_SRC=Examples/SonarMote/SonarMote_DistanceReader/SonarMote_DistanceReader.ino 29 | - PLATFORMIO_CI_SRC=Examples/SonarMote/SonarMote_DistanceTracker/SonarMote_DistanceTracker.ino 30 | - PLATFORMIO_CI_SRC=Examples/SonarMote/SonarMote_Parking/SonarMote_Parking.ino 31 | - PLATFORMIO_CI_SRC=Examples/SonarMote/SonarMote_Parking_Sound_OLED/SonarMote_Parking_Sound_OLED.ino 32 | - PLATFORMIO_CI_SRC=Examples/Struct_receive 33 | - PLATFORMIO_CI_SRC=Examples/Struct_send 34 | - PLATFORMIO_CI_SRC=Examples/TxRxBlinky 35 | - PLATFORMIO_CI_SRC=Examples/WeatherNode 36 | - PLATFORMIO_CI_SRC=Examples/WirelessProgramming_gateway 37 | - PLATFORMIO_CI_SRC=Examples/WirelessProgramming_node 38 | 39 | install: 40 | - pip install -U platformio 41 | 42 | # 43 | # Libraries from PlatformIO Library Registry: 44 | # 45 | # http://platformio.org/#!/lib/show/7/U8glib 46 | # http://platformio.org/#!/lib/show/38/LowPower 47 | # http://platformio.org/#!/lib/show/125/SPIFlash 48 | # http://platformio.org/#!/lib/show/131/TimerOne 49 | # http://platformio.org/#!/lib/show/136/LiquidCrystal 50 | # http://platformio.org/#!/lib/show/176/NewPing 51 | # http://platformio.org/#!/lib/show/531/WirelessHEX69 52 | # http://platformio.org/#!/lib/show/532/BMP180 53 | # http://platformio.org/#!/lib/show/536/Si7021 54 | 55 | - platformio lib install 7 38 125 131 136 176 531 532 536 56 | 57 | #- wget https://bitbucket.org/fmalpartida/st7036-display-driver/downloads/LCD_%20ST7036_v1.2.0.zip -O /tmp/st7036_source.zip 58 | #- unzip /tmp/st7036_source.zip -d /tmp/ 59 | 60 | script: 61 | #- platformio ci --board=moteino --lib=. --lib="/tmp/LCD_C0220BIZ" 62 | - platformio ci --board=moteino --lib=. 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | 165 | # Eagle 166 | *.?#? 167 | eagle.epf -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/RandomNumbers/RandomNumbers.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 random temperature sender at fixed intervals (F) 2 | // Library and code by Felix Rusu - felix@lowpowerlab.com 3 | // Get the RFM69 library at: https://github.com/LowPowerLab/ 4 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 5 | #include 6 | 7 | #define NODEID 98 //unique for each node on same network 8 | #define NETWORKID 100 //the same on all nodes that talk to each other 9 | #define GATEWAYID 1 10 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 11 | #define FREQUENCY RF69_433MHZ 12 | #define FREQUENCY RF69_915MHZ 13 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 14 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 15 | #define ACK_TIME 30 // max # of ms to wait for an ack 16 | 17 | #ifdef __AVR_ATmega1284P__ 18 | #define LED 15 // Moteino MEGAs have LEDs on D15 19 | #define FLASH_SS 23 // and FLASH SS on D23 20 | #else 21 | #define LED 9 // Moteinos have LEDs on D9 22 | #define FLASH_SS 8 // and FLASH SS on D8 23 | #endif 24 | 25 | #define SERIAL_BAUD 115200 26 | 27 | int TRANSMITPERIOD = 10000; //transmit a packet to gateway so often (in ms) 28 | char buff[35]; 29 | byte sendSize=0; 30 | RFM69 radio; 31 | 32 | void setup() { 33 | Serial.begin(SERIAL_BAUD); 34 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 35 | #ifdef IS_RFM69HW 36 | radio.setHighPower(); //uncomment only for RFM69HW! 37 | #endif 38 | radio.encrypt(ENCRYPTKEY); 39 | 40 | char buff[50]; 41 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 42 | Serial.println(buff); 43 | } 44 | 45 | long lastPeriod = 0; 46 | long randNumber1 = 0; 47 | long randNumber2 = 0; 48 | void loop() { 49 | if (radio.receiveDone()) 50 | { 51 | Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 52 | for (byte i = 0; i < radio.DATALEN; i++) 53 | Serial.print((char)radio.DATA[i]); 54 | Serial.print(" [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]"); 55 | 56 | if (radio.ACKRequested()) 57 | { 58 | radio.sendACK(); 59 | Serial.print(" - ACK sent"); 60 | } 61 | Blink(LED,3); 62 | Serial.println(); 63 | } 64 | 65 | int currPeriod = millis()/TRANSMITPERIOD; 66 | if (currPeriod != lastPeriod) 67 | { 68 | lastPeriod=currPeriod; 69 | randNumber1 = random(99); 70 | randNumber2 = random(99); 71 | 72 | if (randNumber2 > 70) 73 | sprintf(buff, "F:%d.5", randNumber1); 74 | else 75 | sprintf(buff, "F:-%d.5", randNumber1); 76 | sendSize = strlen(buff); 77 | 78 | if (radio.sendWithRetry(GATEWAYID, buff, sendSize)) 79 | Serial.print(" ok!"); 80 | else Serial.print(" nothing..."); 81 | 82 | Serial.println(); 83 | Blink(LED,3); 84 | } 85 | } 86 | 87 | void Blink(byte PIN, int DELAY_MS) 88 | { 89 | pinMode(PIN, OUTPUT); 90 | digitalWrite(PIN,HIGH); 91 | delay(DELAY_MS); 92 | digitalWrite(PIN,LOW); 93 | } 94 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/DeepSleep/DeepSleep.ino: -------------------------------------------------------------------------------- 1 | //*********************************************************************************************************** 2 | // Sample sketch that achieves the lowest power on a Moteino of ~6.5uA 3 | // Everything is put to sleep including the MCU, the radio (if any) and the FlashMem chip 4 | //**** SETTINGS ********************************************************************************************* 5 | #define WITH_RFM69 //comment this line out if you don't have a RFM69 on your Moteino 6 | #define WITH_SPIFLASH //comment this line out if you don't have the FLASH-MEM chip on your Moteino 7 | //*********************************************************************************************************** 8 | 9 | #include // assumes Arduino IDE v1.0 or greater 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __AVR_ATmega1284P__ 15 | #define LED 15 // Moteino MEGAs have LEDs on D15 16 | #define FLASH_SS 23 // and FLASH SS on D23 17 | #else 18 | #define LED 9 // Moteinos have LEDs on D9 19 | #define FLASH_SS 8 // and FLASH SS on D8 20 | #endif 21 | 22 | #if defined(WITH_RFM69) || defined(WITH_SPIFLASH) 23 | #include //comes with Arduino IDE (www.arduino.cc) 24 | #if defined(WITH_RFM69) 25 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 26 | RFM69 radio; 27 | #define NETWORKID 100 28 | #define NODEID 123 29 | #define FREQUENCY RF69_915MHZ 30 | #endif 31 | #if defined(WITH_SPIFLASH) 32 | #include //get it here: https://www.github.com/lowpowerlab/spiflash 33 | SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond chip (W25X40CL) 34 | #endif 35 | #endif 36 | 37 | //watchdog interrupt 38 | ISR (WDT_vect) { 39 | wdt_disable(); 40 | } 41 | 42 | void setup () { 43 | for (uint8_t i=0; i<=A5; i++) 44 | { 45 | pinMode(i, OUTPUT); 46 | digitalWrite(i, LOW); 47 | } 48 | 49 | #if defined(WITH_RFM69) 50 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 51 | radio.sleep(); 52 | #endif 53 | 54 | #if defined(WITH_SPIFLASH) 55 | if (flash.initialize()) 56 | flash.sleep(); 57 | #endif 58 | 59 | power_timer1_disable(); 60 | power_timer2_disable(); 61 | power_twi_disable(); 62 | } 63 | 64 | void loop () 65 | { 66 | // disable ADC 67 | ADCSRA = 0; 68 | // clear various "reset" flags 69 | MCUSR = 0; 70 | // allow changes, disable reset 71 | WDTCSR = bit (WDCE) | bit (WDE); 72 | //set interrupt mode and an interval 73 | WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); //set WDIE, and 8 seconds delay 74 | wdt_reset(); //pat the dog... 75 | 76 | set_sleep_mode (SLEEP_MODE_PWR_DOWN); 77 | noInterrupts(); // timed sequence follows 78 | sleep_enable(); 79 | 80 | // turn off brown-out enable in software 81 | // BODS must be set to one and BODSE must be set to zero within four clock cycles 82 | MCUCR = bit (BODS) | bit (BODSE); 83 | // The BODS bit is automatically cleared after three clock cycles 84 | MCUCR = bit (BODS); 85 | interrupts(); 86 | sleep_cpu(); 87 | 88 | //cancel sleep as a precaution 89 | sleep_disable(); 90 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/SonarMote/SonarMote_DistanceReader/SonarMote_DistanceReader.ino: -------------------------------------------------------------------------------- 1 | // Sample sketch for the SonarMote - Simple distance reading 2 | // http://lowpowerlab.com/sonar 3 | // Ultrasonic sensor (HC-SR04) connected to D6 (Trig), D7 (Echo), and power enabled through D5 4 | // Make sure you adjust the settings in the configuration section below !!! 5 | // ********************************************************************************** 6 | // Copyright Felix Rusu, LowPowerLab.com 7 | // Library and code by Felix Rusu - felix@lowpowerlab.com 8 | // ********************************************************************************** 9 | // License 10 | // ********************************************************************************** 11 | // This program is free software; you can redistribute it 12 | // and/or modify it under the terms of the GNU General 13 | // Public License as published by the Free Software 14 | // Foundation; either version 3 of the License, or 15 | // (at your option) any later version. 16 | // 17 | // This program is distributed in the hope that it will 18 | // be useful, but WITHOUT ANY WARRANTY; without even the 19 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 20 | // PARTICULAR PURPOSE. See the GNU General Public 21 | // License for more details. 22 | // 23 | // You should have received a copy of the GNU General 24 | // Public License along with this program. 25 | // If not, see . 26 | // 27 | // Licence can be viewed at 28 | // http://www.gnu.org/licenses/gpl-3.0.txt 29 | // 30 | // Please maintain this license information along with authorship 31 | // and copyright notices in any redistribution of this code 32 | // ********************************************************************************** 33 | #define TRIG 6 34 | #define ECHO 7 35 | #define EN 5 36 | 37 | void setup() { 38 | pinMode (TRIG,OUTPUT);//attach pin 2 to vcc 39 | pinMode (ECHO,OUTPUT);//attach pin 2 to vcc 40 | pinMode (EN,OUTPUT);//attach pin 5 to GND 41 | pinMode (ECHO, INPUT);//attach pin 4 to Echo 42 | // initialize serial communication: 43 | Serial.begin(115200); 44 | digitalWrite(EN, LOW); 45 | } 46 | 47 | long cm; 48 | void loop() 49 | { 50 | cm = readDistanceCM(); 51 | Serial.print(cm); Serial.println("cm"); 52 | delay(500); 53 | } 54 | 55 | long readDistanceCM() 56 | { 57 | digitalWrite(EN, HIGH); 58 | delay(75); 59 | // The PING))) is triggered by a HIGH pulse of 2 or more microseconds. 60 | // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: 61 | digitalWrite(TRIG, LOW); 62 | delayMicroseconds(2); 63 | digitalWrite(TRIG, HIGH); 64 | delayMicroseconds(5); 65 | digitalWrite(TRIG, LOW); 66 | pulseIn(ECHO, HIGH); 67 | delay(16); 68 | digitalWrite(TRIG, LOW); 69 | delayMicroseconds(2); 70 | digitalWrite(TRIG, HIGH); 71 | delayMicroseconds(5); 72 | digitalWrite(TRIG, LOW); 73 | // The same pin is used to read the signal from the PING))): a HIGH 74 | // pulse whose duration is the time (in microseconds) from the sending 75 | // of the ping to the reception of its echo off of an object. 76 | long duration = pulseIn(ECHO, HIGH); 77 | digitalWrite(EN, LOW); 78 | return microsecondsToCentimeters(duration); 79 | } 80 | 81 | long microsecondsToInches(long microseconds) 82 | { 83 | // According to Parallax's datasheet for the PING))), there are 84 | // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per 85 | // second). This gives the distance travelled by the ping, outbound 86 | // and return, so we divide by 2 to get the distance of the obstacle. 87 | // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf 88 | return microseconds / 74 / 2; 89 | } 90 | 91 | long microsecondsToCentimeters(long microseconds) 92 | { 93 | // The speed of sound is 340 m/s or 29 microseconds per centimeter. 94 | // The ping travels out and back, so to find the distance of the 95 | // object we take half of the distance travelled. 96 | return microseconds / 29 / 2; 97 | } 98 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/Struct_send/Struct_send.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define NODEID 99 6 | #define NETWORKID 100 7 | #define GATEWAYID 1 8 | #define FREQUENCY RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 9 | #define KEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 10 | #define LED 9 11 | #define SERIAL_BAUD 115200 12 | #define ACK_TIME 30 // # of ms to wait for an ack 13 | 14 | int TRANSMITPERIOD = 300; //transmit a packet to gateway so often (in ms) 15 | byte sendSize=0; 16 | boolean requestACK = false; 17 | SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip 18 | RFM69 radio; 19 | 20 | typedef struct { 21 | int nodeId; //store this nodeId 22 | unsigned long uptime; //uptime in ms 23 | float temp; //temperature maybe? 24 | } Payload; 25 | Payload theData; 26 | 27 | void setup() { 28 | Serial.begin(SERIAL_BAUD); 29 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 30 | //radio.setHighPower(); //uncomment only for RFM69HW! 31 | radio.encrypt(KEY); 32 | char buff[50]; 33 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 34 | Serial.println(buff); 35 | 36 | if (flash.initialize()) 37 | Serial.println("SPI Flash Init OK!"); 38 | else 39 | Serial.println("SPI Flash Init FAIL! (is chip present?)"); 40 | } 41 | 42 | long lastPeriod = -1; 43 | void loop() { 44 | //process any serial input 45 | if (Serial.available() > 0) 46 | { 47 | char input = Serial.read(); 48 | if (input >= 48 && input <= 57) //[0,9] 49 | { 50 | TRANSMITPERIOD = 100 * (input-48); 51 | if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000; 52 | Serial.print("\nChanging delay to "); 53 | Serial.print(TRANSMITPERIOD); 54 | Serial.println("ms\n"); 55 | } 56 | 57 | if (input == 'r') //d=dump register values 58 | radio.readAllRegs(); 59 | //if (input == 'E') //E=enable encryption 60 | // radio.encrypt(KEY); 61 | //if (input == 'e') //e=disable encryption 62 | // radio.encrypt(null); 63 | 64 | if (input == 'd') //d=dump flash area 65 | { 66 | Serial.println("Flash content:"); 67 | int counter = 0; 68 | 69 | while(counter<=256){ 70 | Serial.print(flash.readByte(counter++), HEX); 71 | Serial.print('.'); 72 | } 73 | while(flash.busy()); 74 | Serial.println(); 75 | } 76 | if (input == 'e') 77 | { 78 | Serial.print("Erasing Flash chip ... "); 79 | flash.chipErase(); 80 | while(flash.busy()); 81 | Serial.println("DONE"); 82 | } 83 | if (input == 'i') 84 | { 85 | Serial.print("DeviceID: "); 86 | word jedecid = flash.readDeviceId(); 87 | Serial.println(jedecid, HEX); 88 | } 89 | } 90 | 91 | //check for any received packets 92 | if (radio.receiveDone()) 93 | { 94 | Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 95 | for (byte i = 0; i < radio.DATALEN; i++) 96 | Serial.print((char)radio.DATA[i]); 97 | Serial.print(" [RX_RSSI:");Serial.print(radio.readRSSI());Serial.print("]"); 98 | 99 | if (radio.ACKRequested()) 100 | { 101 | radio.sendACK(); 102 | Serial.print(" - ACK sent"); 103 | delay(10); 104 | } 105 | Blink(LED,5); 106 | Serial.println(); 107 | } 108 | 109 | int currPeriod = millis()/TRANSMITPERIOD; 110 | if (currPeriod != lastPeriod) 111 | { 112 | //fill in the struct with new values 113 | theData.nodeId = NODEID; 114 | theData.uptime = millis(); 115 | theData.temp = 91.23; //it's hot! 116 | 117 | Serial.print("Sending struct ("); 118 | Serial.print(sizeof(theData)); 119 | Serial.print(" bytes) ... "); 120 | if (radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData))) 121 | Serial.print(" ok!"); 122 | else Serial.print(" nothing..."); 123 | Serial.println(); 124 | Blink(LED,3); 125 | lastPeriod=currPeriod; 126 | } 127 | } 128 | 129 | void Blink(byte PIN, int DELAY_MS) 130 | { 131 | pinMode(PIN, OUTPUT); 132 | digitalWrite(PIN,HIGH); 133 | delay(DELAY_MS); 134 | digitalWrite(PIN,LOW); 135 | } 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RFM69HCW Breakout Board 2 | ================= 3 | The RFM69HCW is an inexpensive and versatile radio module that operates in the unlicensed ISM (Industry, Science, and Medicine) radio band. It's perfect for building inexpensive short-range wireless networks of sensors and actuators for home automation, citizen science, and more. 4 | 5 | [![alt text](https://cdn.sparkfun.com/assets/parts/9/6/6/5/12823-00.jpg)](https://cdn.sparkfun.com/assets/parts/9/6/6/5/12823-00.jpg) 6 | 7 | Specs 8 | ---------------- 9 | 10 | * Transmit power: -18dBm (0.016mW) to +20dBm (100mW) in 1dBm steps 11 | * Receive sensitivity: down to -120dBm at 1.2kbps 12 | * Modulation types: FSK GFSK MSK GMSK OOK 13 | * Bit rates (FSK): 1.2kbps to 300kbps 14 | * Voltage range: 1.8V to 3.6V 15 | * Current consumption: 0.1uA sleep, 1.25mA standby, 16mA receive, 16 | * 130mA transmit (max) 17 | * Encryption: AES 128-bit (optional) 18 | * Packet buffer (FIFO): 66 bytes 19 | * Dimensions: 0.8" x 1.1" 20 | 21 | Product Versions 22 | ---------------- 23 | 24 | The RFM69HCW modules transmit in the [ISM band](http://en.wikipedia.org/wiki/ISM_band), which is reserved for short-range, low-power communications. SparkFun sells the RFM69HCW Breakout Board in two frequencies: 25 | 26 | * [**RFM69HCW Breakout 915MHz (WRL-12775)**](https://www.sparkfun.com/products/12775) 27 | * [**RFM69HCW Breakout 433MHz (WRL-12823)**](https://www.sparkfun.com/products/12823) 28 | 29 | Broadly speaking, the 915MHz version is legal in [ITU region](http://en.wikipedia.org/wiki/ITU_region) 2 (North and South America, Australia, Greenland, Pacific Islands, Israel), and the 433MHz version is legal in [ITU region](http://en.wikipedia.org/wiki/ITU_region) 1 (Europe, Africa, Middle East, Russia). Other areas have mixed allocations; hobbyist use is not likely to be an issue, but if you're going to be deploying a lot of these or using them in a commercial product, check your local regulations. 30 | 31 | Documentation 32 | ------------------- 33 | 34 | * [**Hookup Guide**](https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide) 35 | * [**RFM69HCW Breakout Board Schematic**](https://github.com/sparkfun/RFM69HCW_Breakout/blob/master/documentation/RFM69HCW_BOB.pdf) 36 | * [**RFM69HCW datasheet**](https://github.com/sparkfun/RFM69HCW_Breakout/blob/master/documentation/RFM69HCW-V1.1.pdf) 37 | * [**HopeRF RFM69HCW product page (external link)**](http://www.hoperf.com/rf/fsk_module/RFM69HCW.htm) 38 | 39 | Repository Contents 40 | ------------------- 41 | * [**/Libraries/Arduino**](https://github.com/sparkfun/RFM69HCW_Breakout/tree/master/Libraries/Arduino) - Contains the [RFM69 library](https://github.com/LowPowerLab/RFM69) written by Felix Rusu of [LowPowerLab.com](lowpowerlab.com). See [https://github.com/LowPowerLab/RFM69](https://github.com/LowPowerLab/RFM69) for the most up-to-date version. 42 | 43 | * [**/Libraries/Arduino/RFM69/examples**](https://github.com/sparkfun/RFM69HCW_Breakout/tree/master/Libraries/Arduino/RFM69/examples) - Example Arduino sketch showing how to use the SparkFun RFM69HCW breakout board. See the hook-up guide at [https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide](https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide) for wiring and usage details. 44 | 45 | * [**/hardware**](https://github.com/sparkfun/RFM69HCW_Breakout/tree/master/hardware) - Eagle design files (.brd, .sch) 46 | 47 | * [**/documentation**](https://github.com/sparkfun/RFM69HCW_Breakout/tree/master/documentation) - Datasheets, schematic, etc. 48 | 49 | Attribution 50 | ----------- 51 | We gratefully acknowledge Felix Rusu of [LowPowerLab.com](lowpowerlab.com) for his terrific [RFM69 library](https://github.com/LowPowerLab/RFM69), which runs on his very cool [Moteino](http://lowpowerlab.com/moteino/) hardware. A version of his library is included here for the convenience of SparkFun customers. Please see his [GitHub repository](https://github.com/LowPowerLab/RFM69) for the latest version. 52 | 53 | License Information 54 | ------------------- 55 | The hardware design is released under the [Creative Commons Attribution-ShareAlike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/) license. 56 | 57 | Felix Rusu's RFM69 library is released under the [Creative Commons Attribution-ShareAlike 3.0](http://creativecommons.org/licenses/by-sa/3.0/) license. 58 | 59 | SparkFun's example code is based on Felix Rusu's work, and is thus released under the same [Creative Commons Attribution-ShareAlike 3.0](http://creativecommons.org/licenses/by-sa/3.0/) license. 60 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/RFM69_ATC.h: -------------------------------------------------------------------------------- 1 | // ********************************************************************************** 2 | // Automatic Transmit Power Control class derived from RFM69 library. 3 | // Discussion and details in this forum post: https://lowpowerlab.com/forum/index.php/topic,688.0.html 4 | // ********************************************************************************** 5 | // Copyright Thomas Studwell (2014,2015) 6 | // Adjustments by Felix Rusu, LowPowerLab.com 7 | // ********************************************************************************** 8 | // License 9 | // ********************************************************************************** 10 | // This program is free software; you can redistribute it 11 | // and/or modify it under the terms of the GNU General 12 | // Public License as published by the Free Software 13 | // Foundation; either version 3 of the License, or 14 | // (at your option) any later version. 15 | // 16 | // This program is distributed in the hope that it will 17 | // be useful, but WITHOUT ANY WARRANTY; without even the 18 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 19 | // PARTICULAR PURPOSE. See the GNU General Public 20 | // License for more details. 21 | // 22 | // You should have received a copy of the GNU General 23 | // Public License along with this program. 24 | // If not, see . 25 | // 26 | // Licence can be viewed at 27 | // http://www.gnu.org/licenses/gpl-3.0.txt 28 | // 29 | // Please maintain this license information along with authorship 30 | // and copyright notices in any redistribution of this code 31 | // ********************************************************************************** 32 | #ifndef RFM69_ATC_h 33 | #define RFM69_ATC_h 34 | #include 35 | 36 | #define RFM69_CTL_RESERVE1 0x20 37 | 38 | class RFM69_ATC: public RFM69 { 39 | public: 40 | static volatile uint8_t ACK_RSSI_REQUESTED; // new flag in CTL byte to request RSSI with ACK (could potentially be merged with ACK_REQUESTED) 41 | 42 | RFM69_ATC(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM) : 43 | RFM69(slaveSelectPin, interruptPin, isRFM69HW, interruptNum) { 44 | } 45 | 46 | bool initialize(uint8_t freqBand, uint8_t ID, uint8_t networkID=1); 47 | void sendACK(const void* buffer = "", uint8_t bufferSize=0); 48 | //void setHighPower(bool onOFF=true, uint8_t PA_ctl=0x60); //have to call it after initialize for RFM69HW 49 | //void setPowerLevel(uint8_t level); // reduce/increase transmit power level 50 | bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); // 40ms roundtrip req for 61byte packets 51 | void enableAutoPower(int16_t targetRSSI=-90); // TWS: New method to enable/disable auto Power control 52 | void setMode(uint8_t mode); // TWS: moved from protected to try to build block()/unblock() wrapper 53 | 54 | int16_t getAckRSSI(void); // TWS: New method to retrieve the ack'd RSSI (if any) 55 | uint8_t setLNA(uint8_t newReg); // TWS: function to control LNA reg for power testing purposes 56 | int16_t _targetRSSI; // if non-zero then this is the desired end point RSSI for our transmission 57 | uint8_t _transmitLevel; // saved powerLevel in case we do auto power adjustment, this value gets dithered 58 | 59 | protected: 60 | void interruptHook(uint8_t CTLbyte); 61 | void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); // Need this one to match the RFM69 prototype. 62 | void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK, bool sendACK, bool sendRSSI, int16_t lastRSSI); 63 | void receiveBegin(); 64 | //void setHighPowerRegs(bool onOff); 65 | 66 | int16_t _ackRSSI; // this contains the RSSI our destination Ack'd back to us (if we enabledAutoPower) 67 | //bool _powerBoost; // this controls whether we need to turn on the highpower regs based on the setPowerLevel input 68 | uint8_t _PA_Reg; // saved and derived PA control bits so we don't have to spend time reading back from SPI port 69 | }; 70 | 71 | #endif -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/Struct_receive/Struct_receive.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define NODEID 1 6 | #define NETWORKID 100 7 | #define FREQUENCY RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 8 | #define KEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 9 | #define LED 9 10 | #define SERIAL_BAUD 115200 11 | #define ACK_TIME 30 // # of ms to wait for an ack 12 | 13 | RFM69 radio; 14 | SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip 15 | bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network 16 | 17 | typedef struct { 18 | int nodeId; //store this nodeId 19 | unsigned long uptime; //uptime in ms 20 | float temp; //temperature maybe? 21 | } Payload; 22 | Payload theData; 23 | 24 | void setup() { 25 | Serial.begin(SERIAL_BAUD); 26 | delay(10); 27 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 28 | //radio.setHighPower(); //uncomment only for RFM69HW! 29 | radio.encrypt(KEY); 30 | radio.promiscuous(promiscuousMode); 31 | char buff[50]; 32 | sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 33 | Serial.println(buff); 34 | if (flash.initialize()) 35 | Serial.println("SPI Flash Init OK!"); 36 | else 37 | Serial.println("SPI Flash Init FAIL! (is chip present?)"); 38 | } 39 | 40 | byte ackCount=0; 41 | void loop() { 42 | //process any serial input 43 | if (Serial.available() > 0) 44 | { 45 | char input = Serial.read(); 46 | if (input == 'r') //d=dump all register values 47 | radio.readAllRegs(); 48 | if (input == 'E') //E=enable encryption 49 | radio.encrypt(KEY); 50 | if (input == 'e') //e=disable encryption 51 | radio.encrypt(null); 52 | if (input == 'p') 53 | { 54 | promiscuousMode = !promiscuousMode; 55 | radio.promiscuous(promiscuousMode); 56 | Serial.print("Promiscuous mode ");Serial.println(promiscuousMode ? "on" : "off"); 57 | } 58 | 59 | if (input == 'd') //d=dump flash area 60 | { 61 | Serial.println("Flash content:"); 62 | int counter = 0; 63 | 64 | while(counter<=256){ 65 | Serial.print(flash.readByte(counter++), HEX); 66 | Serial.print('.'); 67 | } 68 | while(flash.busy()); 69 | Serial.println(); 70 | } 71 | if (input == 'D') 72 | { 73 | Serial.print("Deleting Flash chip content... "); 74 | flash.chipErase(); 75 | while(flash.busy()); 76 | Serial.println("DONE"); 77 | } 78 | if (input == 'i') 79 | { 80 | Serial.print("DeviceID: "); 81 | word jedecid = flash.readDeviceId(); 82 | Serial.println(jedecid, HEX); 83 | } 84 | } 85 | 86 | if (radio.receiveDone()) 87 | { 88 | Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 89 | Serial.print(" [RX_RSSI:");Serial.print(radio.readRSSI());Serial.print("]"); 90 | if (promiscuousMode) 91 | { 92 | Serial.print("to [");Serial.print(radio.TARGETID, DEC);Serial.print("] "); 93 | } 94 | 95 | if (radio.DATALEN != sizeof(Payload)) 96 | Serial.print("Invalid payload received, not matching Payload struct!"); 97 | else 98 | { 99 | theData = *(Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else 100 | Serial.print(" nodeId="); 101 | Serial.print(theData.nodeId); 102 | Serial.print(" uptime="); 103 | Serial.print(theData.uptime); 104 | Serial.print(" temp="); 105 | Serial.print(theData.temp); 106 | } 107 | 108 | if (radio.ACKRequested()) 109 | { 110 | byte theNodeID = radio.SENDERID; 111 | radio.sendACK(); 112 | Serial.print(" - ACK sent."); 113 | 114 | // When a node requests an ACK, respond to the ACK 115 | // and also send a packet requesting an ACK (every 3rd one only) 116 | // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY 117 | if (ackCount++%3==0) 118 | { 119 | Serial.print(" Pinging node "); 120 | Serial.print(theNodeID); 121 | Serial.print(" - ACK..."); 122 | delay(3); //need this when sending right after reception .. ? 123 | if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0)) // 0 = only 1 attempt, no retries 124 | Serial.print("ok!"); 125 | else Serial.print("nothing"); 126 | } 127 | } 128 | Serial.println(); 129 | Blink(LED,3); 130 | } 131 | } 132 | 133 | void Blink(byte PIN, int DELAY_MS) 134 | { 135 | pinMode(PIN, OUTPUT); 136 | digitalWrite(PIN,HIGH); 137 | delay(DELAY_MS); 138 | digitalWrite(PIN,LOW); 139 | } 140 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/README.md: -------------------------------------------------------------------------------- 1 | # RFM69 Library [![Build Status](https://travis-ci.org/LowPowerLab/RFM69.svg)](https://travis-ci.org/LowPowerLab/RFM69) 2 | 3 | By Felix Rusu, [LowPowerLab.com](http://LowPowerLab.com) 4 |
5 | RFM69 library for RFM69W, RFM69HW, RFM69CW, RFM69HCW (semtech SX1231, SX1231H) 6 |
7 | The latest examples, new features and bug fixes are found in the [original repository](https://github.com/LowPowerLab/RFM69) of this library. 8 | 9 | ##License 10 | GPL 3.0, please see the [License.txt](https://github.com/LowPowerLab/RFM69/blob/master/License.txt) file for details. Be sure to include the same license with any fork or redistribution of this library. 11 | 12 | ##Features 13 | - easy to use API with a few simple functions for basic usage 14 | - 255 possible nodes on 256 possible networks 15 | - 61 bytes max message length (limited to 61 to support AES hardware encryption) 16 | - customizable transmit power (32 levels) for low-power transmission control 17 | - sleep function for power saving 18 | - automatic ACKs with the sendWithRetry() function 19 | - hardware 128bit AES encryption 20 | - hardware preamble, synch recognition and CRC check 21 | - digital RSSI can be read at any time with readRSSI() 22 | - interrupt driven 23 | - tested on [Moteino R3, R4, R4-USB (ATMega328p), MEGA (ATMega1284p)](https://lowpowerlab.com/shop/Moteino-R4) 24 | - works with RFM69W, RFM69HW, RFM69CW, RFM69HCW, Semtech SX1231/SX1231H transceivers 25 | - promiscuous mode allows any node to listen to any packet on same network 26 | 27 | ###Library Installation (Arduino IDE) 28 | Copy the content of this library in the "Arduino/libraries/RFM69" folder. 29 |
30 | To find your Arduino folder go to File>Preferences in the Arduino IDE. 31 |
32 | See [this tutorial](http://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-libraries) on Arduino libraries. 33 | 34 | ###Hardware & programming 35 | The easiest way to get started is with the well documented and supported [Moteino](http://moteino.com) microcontroller platform which is [easily programmable](https://lowpowerlab.com/programming) from the Arduino IDE. This includes the [Moteino, MoteinoUSB & MoteinoMEGA](https://lowpowerlab.com/shop/Moteino). RFM69 transceivers were extensively tested on Moteinos for the purpose of building internet of things (IoT) devices that can be controlled wirelessly. This platform has matured over time and there is now a [dedicated page](https://lowpowerlab.com/gateway) where you can review how these devices can interact with each other via a RaspberryPi gateway interface. Here's a video overview:
36 | https://www.youtube.com/watch?v=YUUZ6k0pBHg 37 |
38 | https://www.youtube.com/watch?v=I9MNZQgqKHA 39 |
40 | https://www.youtube.com/watch?v=F15dEqZ4pMM 41 | 42 | ###Basic sample usage 43 | - The [Gateway](https://github.com/LowPowerLab/RFM69/blob/master/Examples/Gateway/Gateway.ino) example listens for incoming data from remote nodes and responds to any ACK requests 44 | - The [Node](https://github.com/LowPowerLab/RFM69/blob/master/Examples/Node/Node.ino) example is a loop that sends increasingly longer packets to the gateway and waits for an ACK each time 45 | - More examples are added from time to time, check all the [examples](https://github.com/LowPowerLab/RFM69/tree/master/Examples), visit the [LowPowerLab blog](http://lowpowerlab.com) for latest news and projects, and check out the [LowPowerLab forums](https://lowpowerlab.com/forum) for projects and discussion 46 | 47 | ##Blog writeup 48 | See the [library release blog post](http://lowpowerlab.com/blog/2013/06/20/rfm69-library/) 49 | 50 | ##Why RFM69 51 | - I have spent a lot of time developing this library for RFM69W/HW transceivers. I made it open source because I believe a lot of people can benefit from this new powerful transceiver. I hope others will also contribute and build on my work 52 | - I have long researched alternative transceivers for RFM12B which is still an excellent transceiver but it is much lower output power and has limited built in features which need to be implemented in firmware (PREAMBLE, SYNC, CRC, packet engine, encryption etc). 53 | - I wanted a transceiver that could still be very small, easy to use, and have the longer range that I needed 54 | - RFM69 comes in 2 variants that have the same pinout layout: RFM69W (13dBm, 45mA TX) and RFM69HW (20dBm, 130mA TX). Other variants include the RFM69CW (up to 13dBm power) which is pin compatible with RFM12B, and RFM69HCW (20dBm output power). 55 | 56 | ##RFM69W range and antennas 57 | - I have tested open-air range on these transceivers in various combinations. 58 | - I am happy to say that a range of upwards of 350m can be achieved with the default settings provided in the library.Some users reported upwards of 500m by lowering the bitrate, and a forum user reported 1.5miles at 1.2Kbps: see [this forum post](http://lowpowerlab.com/forum/index.php/topic,112.msg288.html) and [this blog page](http://lowpowerlab.com/moteino/#antennas) 59 | - The caveat with these higher RF power units is that they need more DC power when they transmit. For battery powered motes, you will need to keep them powered down and only transmit periodically. Use the sleep() function to put the radios in low power mode and use the [LowPower](https://github.com/lowpowerlab/lowpower) or [Narcoleptic](https://code.google.com/p/narcoleptic/) libraries to power down your Moteino/Arduino 60 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/GarageMote_base/GarageMote_base.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************************************** 2 | // GarageMote garage door controller base receiver sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW 3 | // Can be adapted to use Moteinos using RFM12B 4 | // This is the sketch for the base, not the controller itself, and meant as another example on how to use a 5 | // Moteino as a gateway/base/receiver 6 | // 2013-09-13 (C) felix@lowpowerlab.com, http://www.LowPowerLab.com 7 | // ********************************************************************************************************** 8 | // Creative Commons Attrib Share-Alike License 9 | // You are free to use/extend this code/library but please abide with the CCSA license: 10 | // http://creativecommons.org/licenses/by-sa/3.0/ 11 | // ********************************************************************************************************** 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | //***************************************************************************************************************************** 18 | // ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! 19 | //***************************************************************************************************************************** 20 | #define NODEID 1 21 | #define GARAGENODEID 99 22 | #define NETWORKID 100 23 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 24 | //#define FREQUENCY RF69_433MHZ 25 | //#define FREQUENCY RF69_868MHZ 26 | #define FREQUENCY RF69_915MHZ 27 | #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 28 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 29 | #define LED 9 30 | #define SERIAL_BAUD 115200 31 | #define ACK_TIME 30 // # of ms to wait for an ack 32 | //***************************************************************************************************************************** 33 | 34 | RFM69 radio; 35 | SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip 36 | byte readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=50); 37 | 38 | void setup() { 39 | Serial.begin(SERIAL_BAUD); 40 | delay(10); 41 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 42 | #ifdef IS_RFM69HW 43 | radio.setHighPower(); //must include only for RFM69HW! 44 | #endif 45 | radio.encrypt(ENCRYPTKEY); 46 | char buff[50]; 47 | sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 48 | Serial.println(buff); 49 | if (flash.initialize()) 50 | Serial.println("SPI Flash Init OK!"); 51 | else 52 | Serial.println("SPI Flash Init FAIL! (is chip present?)"); 53 | } 54 | 55 | byte ackCount=0; 56 | byte inputLen=0; 57 | char input[64]; 58 | void loop() { 59 | //process any serial input 60 | inputLen = readSerialLine(input); 61 | 62 | if (inputLen >= 6) 63 | { 64 | if (input[0]=='G' && input[1]=='R' && input[2]=='G' && input[3]=='O' && input[4]=='P' && input[5]=='N') 65 | { 66 | Serial.print("OPN ... "); 67 | if (radio.sendWithRetry(GARAGENODEID, "OPN", 3)) 68 | Serial.println("ok ... "); 69 | else Serial.println("nothing ... "); 70 | } 71 | if (input[0]=='G' && input[1]=='R' && input[2]=='G' && input[3]=='C' && input[4]=='L' && input[5]=='S') 72 | { 73 | Serial.print("CLS ... "); 74 | if (radio.sendWithRetry(GARAGENODEID, "CLS", 3)) 75 | Serial.println("ok ... "); 76 | else Serial.println("nothing ... "); 77 | } 78 | if (input[0]=='G' && input[1]=='R' && input[2]=='G' && input[3]=='S' && input[4]=='T' && input[5]=='S') 79 | { 80 | Serial.print("STS ... "); 81 | if (radio.sendWithRetry(GARAGENODEID, "STS", 3)) 82 | Serial.println("ok ... "); 83 | else Serial.println("nothing ... "); 84 | } 85 | 86 | //if (input == 'i') 87 | //{ 88 | // Serial.print("DeviceID: "); 89 | // word jedecid = flash.readDeviceId(); 90 | // Serial.println(jedecid, HEX); 91 | //} 92 | } 93 | 94 | if (radio.receiveDone()) 95 | { 96 | Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 97 | for (byte i = 0; i < radio.DATALEN; i++) 98 | Serial.print((char)radio.DATA[i]); 99 | Serial.print(" [RSSI:");Serial.print(radio.RSSI);Serial.print("]"); 100 | 101 | if (radio.ACKRequested()) 102 | { 103 | byte theNodeID = radio.SENDERID; 104 | radio.sendACK(); 105 | Serial.print("[ACK-sent]"); 106 | } 107 | Serial.println(); 108 | Blink(LED,3); 109 | } 110 | } 111 | 112 | void Blink(byte PIN, int DELAY_MS) 113 | { 114 | pinMode(PIN, OUTPUT); 115 | digitalWrite(PIN,HIGH); 116 | delay(DELAY_MS); 117 | digitalWrite(PIN,LOW); 118 | } 119 | 120 | // reads a line feed (\n) terminated line from the serial stream 121 | // returns # of bytes read, up to 255 122 | // timeout in ms, will timeout and return after so long 123 | byte readSerialLine(char* input, char endOfLineChar, byte maxLength, uint16_t timeout) 124 | { 125 | byte inputLen = 0; 126 | Serial.setTimeout(timeout); 127 | inputLen = Serial.readBytesUntil(endOfLineChar, input, maxLength); 128 | input[inputLen]=0;//null-terminate it 129 | Serial.setTimeout(0); 130 | //Serial.println(); 131 | return inputLen; 132 | } 133 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/SFE_RFM69HCW_example/SFE_RFM69HCW_example.ino: -------------------------------------------------------------------------------- 1 | // RFM69HCW Example Sketch 2 | // Send serial input characters from one RFM69 node to another 3 | // Based on RFM69 library sample code by Felix Rusu 4 | // http://LowPowerLab.com/contact 5 | // Modified for RFM69HCW by Mike Grusin, 4/16 6 | 7 | // This sketch will show you the basics of using an 8 | // RFM69HCW radio module. SparkFun's part numbers are: 9 | // 915MHz: https://www.sparkfun.com/products/12775 10 | // 434MHz: https://www.sparkfun.com/products/12823 11 | 12 | // See the hook-up guide for wiring instructions: 13 | // https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide 14 | 15 | // Uses the RFM69 library by Felix Rusu, LowPowerLab.com 16 | // Original library: https://www.github.com/lowpowerlab/rfm69 17 | // SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout 18 | 19 | // Include the RFM69 and SPI libraries: 20 | 21 | #include 22 | #include 23 | 24 | // Addresses for this node. CHANGE THESE FOR EACH NODE! 25 | 26 | #define NETWORKID 0 // Must be the same for all nodes (0 to 255) 27 | #define MYNODEID 1 // My node ID (0 to 255) 28 | #define TONODEID 2 // Destination node ID (0 to 254, 255 = broadcast) 29 | 30 | // RFM69 frequency, uncomment the frequency of your module: 31 | 32 | //#define FREQUENCY RF69_433MHZ 33 | #define FREQUENCY RF69_915MHZ 34 | 35 | // AES encryption (or not): 36 | 37 | #define ENCRYPT true // Set to "true" to use encryption 38 | #define ENCRYPTKEY "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes 39 | 40 | // Use ACKnowledge when sending messages (or not): 41 | 42 | #define USEACK true // Request ACKs or not 43 | 44 | // Packet sent/received indicator LED (optional): 45 | 46 | #define LED 9 // LED positive pin 47 | #define GND 8 // LED ground pin 48 | 49 | // Create a library object for our RFM69HCW module: 50 | 51 | RFM69 radio; 52 | 53 | void setup() 54 | { 55 | // Open a serial port so we can send keystrokes to the module: 56 | 57 | Serial.begin(9600); 58 | Serial.print("Node "); 59 | Serial.print(MYNODEID,DEC); 60 | Serial.println(" ready"); 61 | 62 | // Set up the indicator LED (optional): 63 | 64 | pinMode(LED,OUTPUT); 65 | digitalWrite(LED,LOW); 66 | pinMode(GND,OUTPUT); 67 | digitalWrite(GND,LOW); 68 | 69 | // Initialize the RFM69HCW: 70 | // radio.setCS(10); //uncomment if using Pro Micro 71 | radio.initialize(FREQUENCY, MYNODEID, NETWORKID); 72 | radio.setHighPower(); // Always use this for RFM69HCW 73 | 74 | // Turn on encryption if desired: 75 | 76 | if (ENCRYPT) 77 | radio.encrypt(ENCRYPTKEY); 78 | } 79 | 80 | void loop() 81 | { 82 | // Set up a "buffer" for characters that we'll send: 83 | 84 | static char sendbuffer[62]; 85 | static int sendlength = 0; 86 | 87 | // SENDING 88 | 89 | // In this section, we'll gather serial characters and 90 | // send them to the other node if we (1) get a carriage return, 91 | // or (2) the buffer is full (61 characters). 92 | 93 | // If there is any serial input, add it to the buffer: 94 | 95 | if (Serial.available() > 0) 96 | { 97 | char input = Serial.read(); 98 | 99 | if (input != '\r') // not a carriage return 100 | { 101 | sendbuffer[sendlength] = input; 102 | sendlength++; 103 | } 104 | 105 | // If the input is a carriage return, or the buffer is full: 106 | 107 | if ((input == '\r') || (sendlength == 61)) // CR or buffer full 108 | { 109 | // Send the packet! 110 | 111 | 112 | Serial.print("sending to node "); 113 | Serial.print(TONODEID, DEC); 114 | Serial.print(": ["); 115 | for (byte i = 0; i < sendlength; i++) 116 | Serial.print(sendbuffer[i]); 117 | Serial.println("]"); 118 | 119 | // There are two ways to send packets. If you want 120 | // acknowledgements, use sendWithRetry(): 121 | 122 | if (USEACK) 123 | { 124 | if (radio.sendWithRetry(TONODEID, sendbuffer, sendlength)) 125 | Serial.println("ACK received!"); 126 | else 127 | Serial.println("no ACK received :("); 128 | } 129 | 130 | // If you don't need acknowledgements, just use send(): 131 | 132 | else // don't use ACK 133 | { 134 | radio.send(TONODEID, sendbuffer, sendlength); 135 | } 136 | 137 | sendlength = 0; // reset the packet 138 | Blink(LED,10); 139 | } 140 | } 141 | 142 | // RECEIVING 143 | 144 | // In this section, we'll check with the RFM69HCW to see 145 | // if it has received any packets: 146 | 147 | if (radio.receiveDone()) // Got one! 148 | { 149 | // Print out the information: 150 | 151 | Serial.print("received from node "); 152 | Serial.print(radio.SENDERID, DEC); 153 | Serial.print(": ["); 154 | 155 | // The actual message is contained in the DATA array, 156 | // and is DATALEN bytes in size: 157 | 158 | for (byte i = 0; i < radio.DATALEN; i++) 159 | Serial.print((char)radio.DATA[i]); 160 | 161 | // RSSI is the "Receive Signal Strength Indicator", 162 | // smaller numbers mean higher power. 163 | 164 | Serial.print("], RSSI "); 165 | Serial.println(radio.RSSI); 166 | 167 | // Send an ACK if requested. 168 | // (You don't need this code if you're not using ACKs.) 169 | 170 | if (radio.ACKRequested()) 171 | { 172 | radio.sendACK(); 173 | Serial.println("ACK sent"); 174 | } 175 | Blink(LED,10); 176 | } 177 | } 178 | 179 | void Blink(byte PIN, int DELAY_MS) 180 | // Blink an LED for a given number of ms 181 | { 182 | digitalWrite(PIN,HIGH); 183 | delay(DELAY_MS); 184 | digitalWrite(PIN,LOW); 185 | } 186 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/PiGateway/PiGateway.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************************************** 2 | // GarageMote garage door controller base receiver sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW 3 | // Can be adapted to use Moteinos using RFM12B 4 | // This is the sketch for the base, not the controller itself, and meant as another example on how to use a 5 | // Moteino as a gateway/base/receiver 6 | // 2014-07-14 (C) felix@lowpowerlab.com, http://www.LowPowerLab.com 7 | // ********************************************************************************************************** 8 | // Creative Commons Attrib Share-Alike License 9 | // You are free to use/extend this code/library but please abide with the CCSA license: 10 | // http://creativecommons.org/licenses/by-sa/4.0/ 11 | // ********************************************************************************** 12 | 13 | #include //get it here: http://github.com/lowpowerlab/rfm69 14 | #include //get it here: http://github.com/lowpowerlab/spiflash 15 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming 16 | #include //comes with Arduino IDE (www.arduino.cc) 17 | 18 | //***************************************************************************************************************************** 19 | // ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! 20 | //***************************************************************************************************************************** 21 | #define NODEID 1 22 | #define NETWORKID 200 23 | #define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 24 | #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 25 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 26 | #define LED 9 27 | #define FLASH_CS 8 28 | #define SERIAL_BAUD 115200 29 | #define SERIAL_EN //comment out if you don't want any serial verbose output 30 | #define ACK_TIME 30 // # of ms to wait for an ack 31 | //***************************************************************************************************************************** 32 | 33 | #ifdef SERIAL_EN 34 | #define DEBUG(input) {Serial.print(input); delay(1);} 35 | #define DEBUGln(input) {Serial.println(input); delay(1);} 36 | #else 37 | #define DEBUG(input); 38 | #define DEBUGln(input); 39 | #endif 40 | 41 | RFM69 radio; 42 | SPIFlash flash(FLASH_CS, 0xEF30); //EF40 for 16mbit windbond chip 43 | 44 | void setup() { 45 | Serial.begin(SERIAL_BAUD); 46 | delay(10); 47 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 48 | #ifdef IS_RFM69HW 49 | radio.setHighPower(); //uncomment only for RFM69HW! 50 | #endif 51 | radio.encrypt(ENCRYPTKEY); 52 | char buff[50]; 53 | sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 54 | DEBUGln(buff); 55 | if (flash.initialize()) 56 | { 57 | DEBUGln("SPI Flash Init OK!"); 58 | } 59 | else 60 | DEBUGln("SPI Flash Init FAIL! (is chip present?)"); 61 | } 62 | 63 | byte ackCount=0; 64 | byte inputLen=0; 65 | char input[64]; 66 | byte buff[61]; 67 | String inputstr; 68 | void loop() { 69 | inputLen = readSerialLine(input); 70 | inputstr = String(input); 71 | inputstr.toUpperCase(); 72 | 73 | if (inputLen > 0) 74 | { 75 | if (inputstr.equals("KEY?")) 76 | { 77 | DEBUG("ENCRYPTKEY:"); 78 | DEBUG(ENCRYPTKEY); 79 | } 80 | 81 | byte targetId = inputstr.toInt(); //extract ID if any 82 | byte colonIndex = inputstr.indexOf(":"); //find position of first colon 83 | if (targetId > 0) inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any 84 | if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0) 85 | { 86 | 87 | inputstr.getBytes(buff, 61); 88 | //DEBUGln((char*)buff); 89 | //DEBUGln(targetId); 90 | //DEBUGln(colonIndex); 91 | if (radio.sendWithRetry(targetId, buff, inputstr.length())) 92 | { 93 | DEBUGln("ACK:OK"); 94 | } 95 | else 96 | DEBUGln("ACK:NOK"); 97 | } 98 | } 99 | 100 | if (radio.receiveDone()) 101 | { 102 | int rssi = radio.RSSI; 103 | DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); 104 | if (radio.DATALEN > 0) 105 | { 106 | for (byte i = 0; i < radio.DATALEN; i++) 107 | DEBUG((char)radio.DATA[i]); 108 | DEBUG(" [RSSI:");DEBUG(rssi);DEBUG("]"); 109 | } 110 | 111 | CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG 112 | 113 | if (radio.ACKRequested()) 114 | { 115 | byte theNodeID = radio.SENDERID; 116 | radio.sendACK(); 117 | DEBUG("[ACK-sent]"); 118 | } 119 | DEBUGln(); 120 | Blink(LED,3); 121 | } 122 | } 123 | 124 | void Blink(byte PIN, int DELAY_MS) 125 | { 126 | pinMode(PIN, OUTPUT); 127 | digitalWrite(PIN,HIGH); 128 | delay(DELAY_MS); 129 | digitalWrite(PIN,LOW); 130 | } 131 | 132 | //readSerialLine already defined in WirelessHEX69 133 | // reads a line feed (\n) terminated line from the serial stream 134 | // returns # of bytes read, up to 255 135 | // timeout in ms, will timeout and return after so long 136 | //byte readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=10); 137 | //byte readSerialLine(char* input, char endOfLineChar, byte maxLength, uint16_t timeout) 138 | //{ 139 | // byte inputLen = 0; 140 | // Serial.setTimeout(timeout); 141 | // inputLen = Serial.readBytesUntil(endOfLineChar, input, maxLength); 142 | // input[inputLen]=0;//null-terminate it 143 | // Serial.setTimeout(0); 144 | // //Serial.println(); 145 | // return inputLen; 146 | //} 147 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************** 2 | // This sketch is an example of how wireless programming can be achieved with a Moteino 3 | // that was loaded with a custom 1k bootloader (DualOptiboot) that is capable of loading 4 | // a new sketch from an external SPI flash chip 5 | // This is the GATEWAY node, it does not need a custom Optiboot nor any external FLASH memory chip 6 | // (ONLY the target node will need those) 7 | // The sketch includes logic to receive the new sketch from the serial port (from a host computer) and 8 | // transmit it wirelessly to the target node 9 | // The handshake protocol that receives the sketch from the serial port 10 | // is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM69 library 11 | // These libraries and custom 1k Optiboot bootloader for the target node are at: http://github.com/lowpowerlab 12 | // ********************************************************************************** 13 | // Copyright Felix Rusu, LowPowerLab.com 14 | // Library and code by Felix Rusu - felix@lowpowerlab.com 15 | // ********************************************************************************** 16 | // License 17 | // ********************************************************************************** 18 | // This program is free software; you can redistribute it 19 | // and/or modify it under the terms of the GNU General 20 | // Public License as published by the Free Software 21 | // Foundation; either version 3 of the License, or 22 | // (at your option) any later version. 23 | // 24 | // This program is distributed in the hope that it will 25 | // be useful, but WITHOUT ANY WARRANTY; without even the 26 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 27 | // PARTICULAR PURPOSE. See the GNU General Public 28 | // License for more details. 29 | // 30 | // You should have received a copy of the GNU General 31 | // Public License along with this program. 32 | // If not, see . 33 | // 34 | // Licence can be viewed at 35 | // http://www.gnu.org/licenses/gpl-3.0.txt 36 | // 37 | // Please maintain this license information along with authorship 38 | // and copyright notices in any redistribution of this code 39 | // ********************************************************************************** 40 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 41 | #include 42 | #include //get it here: https://www.github.com/lowpowerlab/spiflash 43 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming/tree/master/WirelessHEX69 44 | 45 | #define NODEID 254 //this node's ID, should be unique among nodes on this NETWORKID 46 | #define NETWORKID 250 //what network this node is on 47 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 48 | //#define FREQUENCY RF69_433MHZ 49 | //#define FREQUENCY RF69_868MHZ 50 | #define FREQUENCY RF69_915MHZ 51 | #define ENCRYPTKEY "sampleEncryptKey" //(16 bytes of your choice - keep the same on all encrypted nodes) 52 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 53 | 54 | #define SERIAL_BAUD 115200 55 | #define ACK_TIME 50 // # of ms to wait for an ack 56 | #define TIMEOUT 3000 57 | 58 | #ifdef __AVR_ATmega1284P__ 59 | #define LED 15 // Moteino MEGAs have LEDs on D15 60 | #else 61 | #define LED 9 // Moteinos hsave LEDs on D9 62 | #endif 63 | 64 | RFM69 radio; 65 | char c = 0; 66 | char input[64]; //serial input buffer 67 | byte targetID=0; 68 | 69 | void setup(){ 70 | Serial.begin(SERIAL_BAUD); 71 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 72 | radio.encrypt(ENCRYPTKEY); //OPTIONAL 73 | #ifdef IS_RFM69HW 74 | radio.setHighPower(); //only for RFM69HW! 75 | #endif 76 | Serial.println("Start wireless gateway..."); 77 | } 78 | 79 | void loop(){ 80 | byte inputLen = readSerialLine(input, 10, 64, 100); //readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=1000); 81 | 82 | if (inputLen==4 && input[0]=='F' && input[1]=='L' && input[2]=='X' && input[3]=='?') { 83 | if (targetID==0) 84 | Serial.println("TO?"); 85 | else 86 | CheckForSerialHEX((byte*)input, inputLen, radio, targetID, TIMEOUT, ACK_TIME, false); 87 | } 88 | else if (inputLen>3 && inputLen<=6 && input[0]=='T' && input[1]=='O' && input[2]==':') 89 | { 90 | byte newTarget=0; 91 | for (byte i = 3; i=48 && input[i]<=57) 93 | newTarget = newTarget*10+input[i]-48; 94 | else 95 | { 96 | newTarget=0; 97 | break; 98 | } 99 | if (newTarget>0) 100 | { 101 | targetID = newTarget; 102 | Serial.print("TO:"); 103 | Serial.print(newTarget); 104 | Serial.println(":OK"); 105 | } 106 | else 107 | { 108 | Serial.print(input); 109 | Serial.print(":INV"); 110 | } 111 | } 112 | else if (inputLen>0) { //just echo back 113 | Serial.print("SERIAL IN > ");Serial.println(input); 114 | } 115 | 116 | if (radio.receiveDone()) 117 | { 118 | for (byte i = 0; i < radio.DATALEN; i++) 119 | Serial.print((char)radio.DATA[i]); 120 | 121 | if (radio.ACK_REQUESTED) 122 | { 123 | radio.sendACK(); 124 | Serial.print(" - ACK sent"); 125 | } 126 | 127 | Serial.println(); 128 | } 129 | Blink(LED,5); //heartbeat 130 | } 131 | 132 | void Blink(byte PIN, int DELAY_MS) 133 | { 134 | pinMode(PIN, OUTPUT); 135 | digitalWrite(PIN,HIGH); 136 | delay(DELAY_MS); 137 | digitalWrite(PIN,LOW); 138 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/MotionMote/OLD/MotionMote_CC-BY-SA.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/Gateway/Gateway.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 receiver/gateway sketch, with ACK and optional encryption, and Automatic Transmission Control 2 | // Passes through any wireless received messages to the serial port & responds to ACKs 3 | // It also looks for an onboard FLASH chip, if present 4 | // RFM69 library and sample code by Felix Rusu - http://LowPowerLab.com/contact 5 | // Copyright Felix Rusu (2015) 6 | 7 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 8 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 9 | #include //comes with Arduino IDE (www.arduino.cc) 10 | #include //get it here: https://www.github.com/lowpowerlab/spiflash 11 | 12 | //********************************************************************************************* 13 | //************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************* 14 | //********************************************************************************************* 15 | #define NODEID 1 //unique for each node on same network 16 | #define NETWORKID 100 //the same on all nodes that talk to each other 17 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 18 | #define FREQUENCY RF69_433MHZ 19 | //#define FREQUENCY RF69_868MHZ 20 | //#define FREQUENCY RF69_915MHZ 21 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 22 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 23 | #define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL 24 | //********************************************************************************************* 25 | 26 | #define SERIAL_BAUD 115200 27 | 28 | #ifdef __AVR_ATmega1284P__ 29 | #define LED 15 // Moteino MEGAs have LEDs on D15 30 | #define FLASH_SS 23 // and FLASH SS on D23 31 | #else 32 | #define LED 9 // Moteinos have LEDs on D9 33 | #define FLASH_SS 8 // and FLASH SS on D8 34 | #endif 35 | 36 | #ifdef ENABLE_ATC 37 | RFM69_ATC radio; 38 | #else 39 | RFM69 radio; 40 | #endif 41 | 42 | SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond chip (W25X40CL) 43 | bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network 44 | 45 | void setup() { 46 | Serial.begin(SERIAL_BAUD); 47 | delay(10); 48 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 49 | #ifdef IS_RFM69HW 50 | radio.setHighPower(); //only for RFM69HW! 51 | #endif 52 | radio.encrypt(ENCRYPTKEY); 53 | radio.promiscuous(promiscuousMode); 54 | //radio.setFrequency(919000000); //set frequency to some custom frequency 55 | char buff[50]; 56 | sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 57 | Serial.println(buff); 58 | if (flash.initialize()) 59 | { 60 | Serial.print("SPI Flash Init OK. Unique MAC = ["); 61 | flash.readUniqueId(); 62 | for (byte i=0;i<8;i++) 63 | { 64 | Serial.print(flash.UNIQUEID[i], HEX); 65 | if (i!=8) Serial.print(':'); 66 | } 67 | Serial.println(']'); 68 | 69 | //alternative way to read it: 70 | //byte* MAC = flash.readUniqueId(); 71 | //for (byte i=0;i<8;i++) 72 | //{ 73 | // Serial.print(MAC[i], HEX); 74 | // Serial.print(' '); 75 | //} 76 | } 77 | else 78 | Serial.println("SPI Flash MEM not found (is chip soldered?)..."); 79 | 80 | #ifdef ENABLE_ATC 81 | Serial.println("RFM69_ATC Enabled (Auto Transmission Control)"); 82 | #endif 83 | } 84 | 85 | byte ackCount=0; 86 | uint32_t packetCount = 0; 87 | void loop() { 88 | //process any serial input 89 | if (Serial.available() > 0) 90 | { 91 | char input = Serial.read(); 92 | if (input == 'r') //d=dump all register values 93 | radio.readAllRegs(); 94 | if (input == 'E') //E=enable encryption 95 | radio.encrypt(ENCRYPTKEY); 96 | if (input == 'e') //e=disable encryption 97 | radio.encrypt(null); 98 | if (input == 'p') 99 | { 100 | promiscuousMode = !promiscuousMode; 101 | radio.promiscuous(promiscuousMode); 102 | Serial.print("Promiscuous mode ");Serial.println(promiscuousMode ? "on" : "off"); 103 | } 104 | 105 | if (input == 'd') //d=dump flash area 106 | { 107 | Serial.println("Flash content:"); 108 | int counter = 0; 109 | 110 | while(counter<=256){ 111 | Serial.print(flash.readByte(counter++), HEX); 112 | Serial.print('.'); 113 | } 114 | while(flash.busy()); 115 | Serial.println(); 116 | } 117 | if (input == 'D') 118 | { 119 | Serial.print("Deleting Flash chip ... "); 120 | flash.chipErase(); 121 | while(flash.busy()); 122 | Serial.println("DONE"); 123 | } 124 | if (input == 'i') 125 | { 126 | Serial.print("DeviceID: "); 127 | word jedecid = flash.readDeviceId(); 128 | Serial.println(jedecid, HEX); 129 | } 130 | if (input == 't') 131 | { 132 | byte temperature = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient 133 | byte fTemp = 1.8 * temperature + 32; // 9/5=1.8 134 | Serial.print( "Radio Temp is "); 135 | Serial.print(temperature); 136 | Serial.print("C, "); 137 | Serial.print(fTemp); //converting to F loses some resolution, obvious when C is on edge between 2 values (ie 26C=78F, 27C=80F) 138 | Serial.println('F'); 139 | } 140 | } 141 | 142 | if (radio.receiveDone()) 143 | { 144 | Serial.print("#["); 145 | Serial.print(++packetCount); 146 | Serial.print(']'); 147 | Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 148 | if (promiscuousMode) 149 | { 150 | Serial.print("to [");Serial.print(radio.TARGETID, DEC);Serial.print("] "); 151 | } 152 | for (byte i = 0; i < radio.DATALEN; i++) 153 | Serial.print((char)radio.DATA[i]); 154 | Serial.print(" [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]"); 155 | 156 | if (radio.ACKRequested()) 157 | { 158 | byte theNodeID = radio.SENDERID; 159 | radio.sendACK(); 160 | Serial.print(" - ACK sent."); 161 | 162 | // When a node requests an ACK, respond to the ACK 163 | // and also send a packet requesting an ACK (every 3rd one only) 164 | // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY 165 | if (ackCount++%3==0) 166 | { 167 | Serial.print(" Pinging node "); 168 | Serial.print(theNodeID); 169 | Serial.print(" - ACK..."); 170 | delay(3); //need this when sending right after reception .. ? 171 | if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0)) // 0 = only 1 attempt, no retries 172 | Serial.print("ok!"); 173 | else Serial.print("nothing"); 174 | } 175 | } 176 | Serial.println(); 177 | Blink(LED,3); 178 | } 179 | } 180 | 181 | void Blink(byte PIN, int DELAY_MS) 182 | { 183 | pinMode(PIN, OUTPUT); 184 | digitalWrite(PIN,HIGH); 185 | delay(DELAY_MS); 186 | digitalWrite(PIN,LOW); 187 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/Node/Node.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 sender/node sketch, with ACK and optional encryption, and Automatic Transmission Control 2 | // Sends periodic messages of increasing length to gateway (id=1) 3 | // It also looks for an onboard FLASH chip, if present 4 | // RFM69 library and sample code by Felix Rusu - http://LowPowerLab.com/contact 5 | // Copyright Felix Rusu (2015) 6 | 7 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 8 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 9 | #include 10 | #include //get it here: https://www.github.com/lowpowerlab/spiflash 11 | 12 | //********************************************************************************************* 13 | //************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************* 14 | //********************************************************************************************* 15 | #define NODEID 2 //must be unique for each node on same network (range up to 254, 255 is used for broadcast) 16 | #define NETWORKID 100 //the same on all nodes that talk to each other (range up to 255) 17 | #define GATEWAYID 1 18 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 19 | #define FREQUENCY RF69_433MHZ 20 | //#define FREQUENCY RF69_868MHZ 21 | //#define FREQUENCY RF69_915MHZ 22 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 23 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 24 | #define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL 25 | //********************************************************************************************* 26 | 27 | #ifdef __AVR_ATmega1284P__ 28 | #define LED 15 // Moteino MEGAs have LEDs on D15 29 | #define FLASH_SS 23 // and FLASH SS on D23 30 | #else 31 | #define LED 9 // Moteinos have LEDs on D9 32 | #define FLASH_SS 8 // and FLASH SS on D8 33 | #endif 34 | 35 | #define SERIAL_BAUD 115200 36 | 37 | int TRANSMITPERIOD = 150; //transmit a packet to gateway so often (in ms) 38 | char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 39 | char buff[20]; 40 | byte sendSize=0; 41 | boolean requestACK = false; 42 | SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond chip (W25X40CL) 43 | 44 | #ifdef ENABLE_ATC 45 | RFM69_ATC radio; 46 | #else 47 | RFM69 radio; 48 | #endif 49 | 50 | void setup() { 51 | Serial.begin(SERIAL_BAUD); 52 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 53 | #ifdef IS_RFM69HW 54 | radio.setHighPower(); //uncomment only for RFM69HW! 55 | #endif 56 | radio.encrypt(ENCRYPTKEY); 57 | //radio.setFrequency(919000000); //set frequency to some custom frequency 58 | 59 | //Auto Transmission Control - dials down transmit power to save battery (-100 is the noise floor, -90 is still pretty good) 60 | //For indoor nodes that are pretty static and at pretty stable temperatures (like a MotionMote) -90dBm is quite safe 61 | //For more variable nodes that can expect to move or experience larger temp drifts a lower margin like -70 to -80 would probably be better 62 | //Always test your ATC mote in the edge cases in your own environment to ensure ATC will perform as you expect 63 | #ifdef ENABLE_ATC 64 | radio.enableAutoPower(-70); 65 | #endif 66 | 67 | char buff[50]; 68 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 69 | Serial.println(buff); 70 | 71 | if (flash.initialize()) 72 | { 73 | Serial.print("SPI Flash Init OK ... UniqueID (MAC): "); 74 | flash.readUniqueId(); 75 | for (byte i=0;i<8;i++) 76 | { 77 | Serial.print(flash.UNIQUEID[i], HEX); 78 | Serial.print(' '); 79 | } 80 | Serial.println(); 81 | } 82 | else 83 | Serial.println("SPI Flash MEM not found (is chip soldered?)..."); 84 | 85 | #ifdef ENABLE_ATC 86 | Serial.println("RFM69_ATC Enabled (Auto Transmission Control)\n"); 87 | #endif 88 | } 89 | 90 | void Blink(byte PIN, int DELAY_MS) 91 | { 92 | pinMode(PIN, OUTPUT); 93 | digitalWrite(PIN,HIGH); 94 | delay(DELAY_MS); 95 | digitalWrite(PIN,LOW); 96 | } 97 | 98 | long lastPeriod = 0; 99 | void loop() { 100 | //process any serial input 101 | if (Serial.available() > 0) 102 | { 103 | char input = Serial.read(); 104 | if (input >= 48 && input <= 57) //[0,9] 105 | { 106 | TRANSMITPERIOD = 100 * (input-48); 107 | if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000; 108 | Serial.print("\nChanging delay to "); 109 | Serial.print(TRANSMITPERIOD); 110 | Serial.println("ms\n"); 111 | } 112 | 113 | if (input == 'r') //d=dump register values 114 | radio.readAllRegs(); 115 | //if (input == 'E') //E=enable encryption 116 | // radio.encrypt(KEY); 117 | //if (input == 'e') //e=disable encryption 118 | // radio.encrypt(null); 119 | 120 | if (input == 'd') //d=dump flash area 121 | { 122 | Serial.println("Flash content:"); 123 | uint16_t counter = 0; 124 | 125 | Serial.print("0-256: "); 126 | while(counter<=256){ 127 | Serial.print(flash.readByte(counter++), HEX); 128 | Serial.print('.'); 129 | } 130 | while(flash.busy()); 131 | Serial.println(); 132 | } 133 | if (input == 'e') 134 | { 135 | Serial.print("Erasing Flash chip ... "); 136 | flash.chipErase(); 137 | while(flash.busy()); 138 | Serial.println("DONE"); 139 | } 140 | if (input == 'i') 141 | { 142 | Serial.print("DeviceID: "); 143 | word jedecid = flash.readDeviceId(); 144 | Serial.println(jedecid, HEX); 145 | } 146 | } 147 | 148 | //check for any received packets 149 | if (radio.receiveDone()) 150 | { 151 | Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 152 | for (byte i = 0; i < radio.DATALEN; i++) 153 | Serial.print((char)radio.DATA[i]); 154 | Serial.print(" [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]"); 155 | 156 | if (radio.ACKRequested()) 157 | { 158 | radio.sendACK(); 159 | Serial.print(" - ACK sent"); 160 | } 161 | Blink(LED,3); 162 | Serial.println(); 163 | } 164 | 165 | int currPeriod = millis()/TRANSMITPERIOD; 166 | if (currPeriod != lastPeriod) 167 | { 168 | lastPeriod=currPeriod; 169 | 170 | //send FLASH id 171 | if(sendSize==0) 172 | { 173 | sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId()); 174 | byte buffLen=strlen(buff); 175 | if (radio.sendWithRetry(GATEWAYID, buff, buffLen)) 176 | Serial.print(" ok!"); 177 | else Serial.print(" nothing..."); 178 | //sendSize = (sendSize + 1) % 31; 179 | } 180 | else 181 | { 182 | Serial.print("Sending["); 183 | Serial.print(sendSize); 184 | Serial.print("]: "); 185 | for(byte i = 0; i < sendSize; i++) 186 | Serial.print((char)payload[i]); 187 | 188 | if (radio.sendWithRetry(GATEWAYID, payload, sendSize)) 189 | Serial.print(" ok!"); 190 | else Serial.print(" nothing..."); 191 | } 192 | sendSize = (sendSize + 1) % 31; 193 | Serial.println(); 194 | Blink(LED,3); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/PiGateway/PiGateway_withLCD.ino: -------------------------------------------------------------------------------- 1 | // GarageMote garage door controller base receiver sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW 2 | // Can be adapted to use Moteinos using RFM12B 3 | // This is the sketch for the base, not the controller itself, and meant as another example on how to use a 4 | // Moteino as a gateway/base/receiver 5 | // 2014-07-14 (C) felix@lowpowerlab.com, http://www.LowPowerLab.com 6 | // ********************************************************************************************************** 7 | // Creative Commons Attrib Share-Alike License 8 | // You are free to use/extend this code/library but please abide with the CCSA license: 9 | // http://creativecommons.org/licenses/by-sa/4.0/ 10 | // ********************************************************************************** 11 | 12 | #include //get it here: http://github.com/lowpowerlab/rfm69 13 | #include //get it here: http://github.com/lowpowerlab/spiflash 14 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming 15 | #include //comes with Arduino IDE (www.arduino.cc) 16 | #include "ST7036.h" //get it from here: https://bitbucket.org/fmalpartida/st7036-display-driver/src/ 17 | #include "LCD_C0220BiZ.h" //get it from here: https://bitbucket.org/fmalpartida/st7036-display-driver/src/ 18 | #include //comes with Arduino 19 | 20 | //***************************************************************************************************************************** 21 | // ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! 22 | //***************************************************************************************************************************** 23 | #define NODEID 1 24 | #define NETWORKID 200 25 | #define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 26 | #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 27 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 28 | #define LED 9 29 | #define FLASH_CS 8 30 | #define SERIAL_BAUD 115200 31 | #define SERIAL_EN //comment out if you don't want any serial verbose output 32 | #define ACK_TIME 30 // # of ms to wait for an ack 33 | #define BACKLIGHTPIN 5 //3=R,5=G,6=B 34 | //***************************************************************************************************************************** 35 | 36 | #ifdef SERIAL_EN 37 | #define DEBUG(input) {Serial.print(input); delay(1);} 38 | #define DEBUGln(input) {Serial.println(input); delay(1);} 39 | #else 40 | #define DEBUG(input); 41 | #define DEBUGln(input); 42 | #endif 43 | 44 | RFM69 radio; 45 | SPIFlash flash(FLASH_CS, 0xEF30); //EF40 for 16mbit windbond chip 46 | 47 | //initialize LCD 48 | ST7036 lcd = ST7036(2, 20, 0x78, BACKLIGHTPIN); //row count, column count, I2C addr, pin for backlight PWM 49 | byte battChar[8] = {0b00000,0b01110,0b11111,0b11111,0b11111,0b11111,0b11111,0}; 50 | byte rssiChar[8] = {0b00000,0b00100,0b10101,0b01110,0b00100,0b00100,0b00100,0}; 51 | 52 | void setup() { 53 | Serial.begin(SERIAL_BAUD); 54 | delay(10); 55 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 56 | #ifdef IS_RFM69HW 57 | radio.setHighPower(); //uncomment only for RFM69HW! 58 | #endif 59 | radio.encrypt(ENCRYPTKEY); 60 | char buff[50]; 61 | sprintf(buff, "\nListening @ %dmhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 62 | DEBUGln(buff); 63 | if (flash.initialize()) 64 | { 65 | DEBUGln("SPI Flash Init OK!"); 66 | } 67 | else 68 | DEBUGln("SPI Flash Init FAIL! (is chip present?)"); 69 | 70 | lcd.init(); 71 | lcd.setContrast(10); 72 | lcd.clear(); 73 | lcd.load_custom_character(0, battChar); 74 | lcd.load_custom_character(1, rssiChar); 75 | lcd.setCursor(0,0); 76 | lcd.print(buff); 77 | } 78 | 79 | byte ackCount=0; 80 | byte inputLen=0; 81 | char input[64]; 82 | byte buff[61]; 83 | char LO[20]; 84 | char BAT[20]; 85 | char temp[25]; 86 | String inputstr; 87 | void loop() { 88 | inputLen = readSerialLine(input, 10, 64, 10); //readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=10); 89 | inputstr = String(input); 90 | inputstr.toUpperCase(); 91 | 92 | if (inputLen > 0) 93 | { 94 | if (inputstr.equals("KEY?")) 95 | { 96 | DEBUG("ENCRYPTKEY:"); 97 | DEBUG(ENCRYPTKEY); 98 | } 99 | 100 | byte targetId = inputstr.toInt(); //extract ID if any 101 | byte colonIndex = inputstr.indexOf(":"); //find position of first colon 102 | if (targetId > 0) inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any 103 | if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0) 104 | { 105 | 106 | inputstr.getBytes(buff, 61); 107 | //DEBUGln((char*)buff); 108 | //DEBUGln(targetId); 109 | //DEBUGln(colonIndex); 110 | if (radio.sendWithRetry(targetId, buff, inputstr.length())) 111 | { 112 | DEBUGln("ACK:OK"); 113 | } 114 | else 115 | DEBUGln("ACK:NOK"); 116 | } 117 | } 118 | 119 | if (radio.receiveDone()) 120 | { 121 | int rssi = radio.RSSI; 122 | DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); 123 | if (radio.DATALEN > 0) 124 | { 125 | for (byte i = 0; i < radio.DATALEN; i++) 126 | DEBUG((char)radio.DATA[i]); 127 | DEBUG(" [RSSI:");DEBUG(rssi);DEBUG("]"); 128 | } 129 | 130 | CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG 131 | 132 | if (radio.ACKRequested()) 133 | { 134 | byte theNodeID = radio.SENDERID; 135 | radio.sendACK(); 136 | DEBUG("[ACK-sent]"); 137 | } 138 | DEBUGln(); 139 | Blink(LED,3); 140 | 141 | lcd.clear(); 142 | lcd.setCursor(0,0); 143 | 144 | //if (radio.DATALEN < RF69_MAX_DATA_LEN) radio.DATA[radio.DATALEN]=0; 145 | byte matches = sscanf((const char*)radio.DATA, "%s BAT:%s", LO, BAT); 146 | if (matches==2) 147 | { 148 | lcd.print(LO); 149 | lcd.setCursor(0,14); 150 | lcd.print(char(0)); 151 | lcd.setCursor(0,15); 152 | lcd.print(BAT); 153 | } 154 | else lcd.print((const char*)radio.DATA); 155 | 156 | lcd.setCursor(1,14); 157 | lcd.print(char(1)); 158 | lcd.setCursor(1,16); 159 | lcd.print(rssi); 160 | } 161 | } 162 | 163 | void Blink(byte PIN, int DELAY_MS) 164 | { 165 | pinMode(PIN, OUTPUT); 166 | digitalWrite(PIN,HIGH); 167 | delay(DELAY_MS); 168 | digitalWrite(PIN,LOW); 169 | } 170 | 171 | //readSerialLine already defined in WirelessHEX69 172 | // reads a line feed (\n) terminated line from the serial stream 173 | // returns # of bytes read, up to 255 174 | // timeout in ms, will timeout and return after so long 175 | //byte readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=10); 176 | //byte readSerialLine(char* input, char endOfLineChar, byte maxLength, uint16_t timeout) 177 | //{ 178 | // byte inputLen = 0; 179 | // Serial.setTimeout(timeout); 180 | // inputLen = Serial.readBytesUntil(endOfLineChar, input, maxLength); 181 | // input[inputLen]=0;//null-terminate it 182 | // Serial.setTimeout(0); 183 | // //Serial.println(); 184 | // return inputLen; 185 | //} -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/WirelessProgramming_node/WirelessProgramming_node.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************** 2 | // This sketch is an example of how wireless programming can be achieved with a Moteino 3 | // that was loaded with a custom 1k bootloader (DualOptiboot) that is capable of loading 4 | // a new sketch from an external SPI flash chip 5 | // The sketch includes logic to receive the new sketch 'over-the-air' and store it in 6 | // the FLASH chip, then restart the Moteino so the bootloader can continue the job of 7 | // actually reflashing the internal flash memory from the external FLASH memory chip flash image 8 | // The handshake protocol that receives the sketch wirelessly by means of the RFM69 radio 9 | // is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM69 library 10 | // These libraries and custom 1k Optiboot bootloader are at: http://github.com/lowpowerlab 11 | // ********************************************************************************** 12 | // Copyright Felix Rusu, LowPowerLab.com 13 | // Library and code by Felix Rusu - felix@lowpowerlab.com 14 | // ********************************************************************************** 15 | // License 16 | // ********************************************************************************** 17 | // This program is free software; you can redistribute it 18 | // and/or modify it under the terms of the GNU General 19 | // Public License as published by the Free Software 20 | // Foundation; either version 3 of the License, or 21 | // (at your option) any later version. 22 | // 23 | // This program is distributed in the hope that it will 24 | // be useful, but WITHOUT ANY WARRANTY; without even the 25 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 26 | // PARTICULAR PURPOSE. See the GNU General Public 27 | // License for more details. 28 | // 29 | // You should have received a copy of the GNU General 30 | // Public License along with this program. 31 | // If not, see . 32 | // 33 | // Licence can be viewed at 34 | // http://www.gnu.org/licenses/gpl-3.0.txt 35 | // 36 | // Please maintain this license information along with authorship 37 | // and copyright notices in any redistribution of this code 38 | // ********************************************************************************** 39 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 40 | #include 41 | #include //get it here: https://www.github.com/lowpowerlab/spiflash 42 | #include 43 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming/tree/master/WirelessHEX69 44 | 45 | #define NODEID 123 // node ID used for this unit 46 | #define NETWORKID 250 47 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 48 | //#define FREQUENCY RF69_433MHZ 49 | //#define FREQUENCY RF69_868MHZ 50 | #define FREQUENCY RF69_915MHZ 51 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 52 | #define SERIAL_BAUD 115200 53 | #define ACK_TIME 30 // # of ms to wait for an ack 54 | #define ENCRYPTKEY "sampleEncryptKey" //(16 bytes of your choice - keep the same on all encrypted nodes) 55 | #define BLINKPERIOD 500 56 | 57 | #ifdef __AVR_ATmega1284P__ 58 | #define LED 15 // Moteino MEGAs have LEDs on D15 59 | #define FLASH_SS 23 // and FLASH SS on D23 60 | #else 61 | #define LED 9 // Moteinos hsave LEDs on D9 62 | #define FLASH_SS 8 // and FLASH SS on D8 63 | #endif 64 | 65 | RFM69 radio; 66 | char input = 0; 67 | long lastPeriod = -1; 68 | 69 | ///////////////////////////////////////////////////////////////////////////// 70 | // flash(SPI_CS, MANUFACTURER_ID) 71 | // SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) 72 | // MANUFACTURER_ID - OPTIONAL, 0x1F44 for adesto(ex atmel) 4mbit flash 73 | // 0xEF30 for windbond 4mbit flash 74 | // 0xEF40 for windbond 16/64mbit flash 75 | ///////////////////////////////////////////////////////////////////////////// 76 | SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for windbond 4mbit flash 77 | 78 | void setup(){ 79 | pinMode(LED, OUTPUT); 80 | Serial.begin(SERIAL_BAUD); 81 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 82 | radio.encrypt(ENCRYPTKEY); //OPTIONAL 83 | #ifdef IS_RFM69HW 84 | radio.setHighPower(); //only for RFM69HW! 85 | #endif 86 | Serial.print("Start node..."); 87 | 88 | if (flash.initialize()) 89 | Serial.println("SPI Flash Init OK!"); 90 | else 91 | Serial.println("SPI Flash Init FAIL!"); 92 | } 93 | 94 | void loop(){ 95 | // This part is optional, useful for some debugging. 96 | // Handle serial input (to allow basic DEBUGGING of FLASH chip) 97 | // ie: display first 256 bytes in FLASH, erase chip, write bytes at first 10 positions, etc 98 | if (Serial.available() > 0) { 99 | input = Serial.read(); 100 | if (input == 'd') //d=dump first page 101 | { 102 | Serial.println("Flash content:"); 103 | int counter = 0; 104 | 105 | while(counter<=256){ 106 | Serial.print(flash.readByte(counter++), HEX); 107 | Serial.print('.'); 108 | } 109 | 110 | Serial.println(); 111 | } 112 | else if (input == 'e') 113 | { 114 | Serial.print("Erasing Flash chip ... "); 115 | flash.chipErase(); 116 | while(flash.busy()); 117 | Serial.println("DONE"); 118 | } 119 | else if (input == 'i') 120 | { 121 | Serial.print("DeviceID: "); 122 | Serial.println(flash.readDeviceId(), HEX); 123 | } 124 | else if (input == 'r') 125 | { 126 | Serial.print("Rebooting"); 127 | resetUsingWatchdog(true); 128 | } 129 | else if (input == 'R') 130 | { 131 | Serial.print("RFM69 registers:"); 132 | radio.readAllRegs(); 133 | } 134 | else if (input >= 48 && input <= 57) //0-9 135 | { 136 | Serial.print("\nWriteByte("); Serial.print(input); Serial.print(")"); 137 | flash.writeByte(input-48, millis()%2 ? 0xaa : 0xbb); 138 | } 139 | } 140 | 141 | // Check for existing RF data, potentially for a new sketch wireless upload 142 | // For this to work this check has to be done often enough to be 143 | // picked up when a GATEWAY is trying hard to reach this node for a new sketch wireless upload 144 | if (radio.receiveDone()) 145 | { 146 | Serial.print("Got ["); 147 | Serial.print(radio.SENDERID); 148 | Serial.print(':'); 149 | Serial.print(radio.DATALEN); 150 | Serial.print("] > "); 151 | for (byte i = 0; i < radio.DATALEN; i++) 152 | Serial.print((char)radio.DATA[i], HEX); 153 | Serial.println(); 154 | CheckForWirelessHEX(radio, flash, true); 155 | Serial.println(); 156 | } 157 | //else Serial.print('.'); 158 | 159 | //////////////////////////////////////////////////////////////////////////////////////////// 160 | // Real sketch code here, let's blink the onboard LED 161 | if ((int)(millis()/BLINKPERIOD) > lastPeriod) 162 | { 163 | lastPeriod++; 164 | digitalWrite(LED, lastPeriod%2); 165 | } 166 | //////////////////////////////////////////////////////////////////////////////////////////// 167 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/RFM69.h: -------------------------------------------------------------------------------- 1 | // ********************************************************************************** 2 | // Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H 3 | // ********************************************************************************** 4 | // Copyright Felix Rusu (2014), felix@lowpowerlab.com 5 | // http://lowpowerlab.com/ 6 | // ********************************************************************************** 7 | // License 8 | // ********************************************************************************** 9 | // This program is free software; you can redistribute it 10 | // and/or modify it under the terms of the GNU General 11 | // Public License as published by the Free Software 12 | // Foundation; either version 3 of the License, or 13 | // (at your option) any later version. 14 | // 15 | // This program is distributed in the hope that it will 16 | // be useful, but WITHOUT ANY WARRANTY; without even the 17 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 18 | // PARTICULAR PURPOSE. See the GNU General Public 19 | // License for more details. 20 | // 21 | // You should have received a copy of the GNU General 22 | // Public License along with this program. 23 | // If not, see . 24 | // 25 | // Licence can be viewed at 26 | // http://www.gnu.org/licenses/gpl-3.0.txt 27 | // 28 | // Please maintain this license information along with authorship 29 | // and copyright notices in any redistribution of this code 30 | // ********************************************************************************** 31 | #ifndef RFM69_h 32 | #define RFM69_h 33 | #include // assumes Arduino IDE v1.0 or greater 34 | 35 | #define RF69_MAX_DATA_LEN 61 // to take advantage of the built in AES/CRC we want to limit the frame size to the internal FIFO size (66 bytes - 3 bytes overhead - 2 bytes crc) 36 | #define RF69_SPI_CS SS // SS is the SPI slave select pin, for instance D10 on ATmega328 37 | 38 | // INT0 on AVRs should be connected to RFM69's DIO0 (ex on ATmega328 it's D2, on ATmega644/1284 it's D2) 39 | #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) 40 | #define RF69_IRQ_PIN 2 41 | #define RF69_IRQ_NUM 0 42 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) 43 | #define RF69_IRQ_PIN 2 44 | #define RF69_IRQ_NUM 2 45 | #elif defined(__AVR_ATmega32U4__) 46 | #define RF69_IRQ_PIN 3 47 | #define RF69_IRQ_NUM 0 48 | #elif defined(__arm__)//Use pin 10 or any pin you want 49 | #define RF69_IRQ_PIN 10 50 | #define RF69_IRQ_NUM 10 51 | #else 52 | #define RF69_IRQ_PIN 2 53 | #define RF69_IRQ_NUM 0 54 | #endif 55 | 56 | 57 | #define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access 58 | #define RF69_MODE_SLEEP 0 // XTAL OFF 59 | #define RF69_MODE_STANDBY 1 // XTAL ON 60 | #define RF69_MODE_SYNTH 2 // PLL ON 61 | #define RF69_MODE_RX 3 // RX MODE 62 | #define RF69_MODE_TX 4 // TX MODE 63 | 64 | // available frequency bands 65 | #define RF69_315MHZ 31 // non trivial values to avoid misconfiguration 66 | #define RF69_433MHZ 43 67 | #define RF69_868MHZ 86 68 | #define RF69_915MHZ 91 69 | 70 | #define null 0 71 | #define COURSE_TEMP_COEF -90 // puts the temperature reading in the ballpark, user can fine tune the returned value 72 | #define RF69_BROADCAST_ADDR 255 73 | #define RF69_CSMA_LIMIT_MS 1000 74 | #define RF69_TX_LIMIT_MS 1000 75 | #define RF69_FSTEP 61.03515625 // == FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet) 76 | 77 | // TWS: define CTLbyte bits 78 | #define RFM69_CTL_SENDACK 0x80 79 | #define RFM69_CTL_REQACK 0x40 80 | 81 | class RFM69 { 82 | public: 83 | static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; // recv/xmit buf, including header & crc bytes 84 | static volatile uint8_t DATALEN; 85 | static volatile uint8_t SENDERID; 86 | static volatile uint8_t TARGETID; // should match _address 87 | static volatile uint8_t PAYLOADLEN; 88 | static volatile uint8_t ACK_REQUESTED; 89 | static volatile uint8_t ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request 90 | static volatile int16_t RSSI; // most accurate RSSI during reception (closest to the reception) 91 | static volatile uint8_t _mode; // should be protected? 92 | 93 | RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM) { 94 | _slaveSelectPin = slaveSelectPin; 95 | _interruptPin = interruptPin; 96 | _interruptNum = interruptNum; 97 | _mode = RF69_MODE_STANDBY; 98 | _promiscuousMode = false; 99 | _powerLevel = 31; 100 | _isRFM69HW = isRFM69HW; 101 | } 102 | 103 | bool initialize(uint8_t freqBand, uint8_t ID, uint8_t networkID=1); 104 | void setAddress(uint8_t addr); 105 | void setNetwork(uint8_t networkID); 106 | bool canSend(); 107 | virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); 108 | virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); // 40ms roundtrip req for 61byte packets 109 | virtual bool receiveDone(); 110 | bool ACKReceived(uint8_t fromNodeID); 111 | bool ACKRequested(); 112 | virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); 113 | uint32_t getFrequency(); 114 | void setFrequency(uint32_t freqHz); 115 | void encrypt(const char* key); 116 | void setCS(uint8_t newSPISlaveSelect); 117 | int16_t readRSSI(bool forceTrigger=false); 118 | void promiscuous(bool onOff=true); 119 | virtual void setHighPower(bool onOFF=true); // has to be called after initialize() for RFM69HW 120 | virtual void setPowerLevel(uint8_t level); // reduce/increase transmit power level 121 | void sleep(); 122 | uint8_t readTemperature(uint8_t calFactor=0); // get CMOS temperature (8bit) 123 | void rcCalibration(); // calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy] 124 | 125 | // allow hacking registers by making these public 126 | uint8_t readReg(uint8_t addr); 127 | void writeReg(uint8_t addr, uint8_t val); 128 | void readAllRegs(); 129 | 130 | protected: 131 | static void isr0(); 132 | void virtual interruptHandler(); 133 | virtual void interruptHook(uint8_t CTLbyte) {}; 134 | virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); 135 | 136 | static RFM69* selfPointer; 137 | uint8_t _slaveSelectPin; 138 | uint8_t _interruptPin; 139 | uint8_t _interruptNum; 140 | uint8_t _address; 141 | bool _promiscuousMode; 142 | uint8_t _powerLevel; 143 | bool _isRFM69HW; 144 | #if defined (SPCR) && defined (SPSR) 145 | uint8_t _SPCR; 146 | uint8_t _SPSR; 147 | #endif 148 | 149 | virtual void receiveBegin(); 150 | virtual void setMode(uint8_t mode); 151 | virtual void setHighPowerRegs(bool onOff); 152 | virtual void select(); 153 | virtual void unselect(); 154 | }; 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/MailboxNotifier/MailboxNotifier4_sender.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 sender/node sketch for mailbox motion sensor 2 | // http://www.lowpowerlab.com/mailbox 3 | // PIR motion sensor connected to D3 (INT1) 4 | // When RISE happens on D3, the sketch transmits a "MOTION" msg to receiver Moteino and goes back to sleep 5 | // It then wakes up every 32 seconds and sends a message indicating when the last 6 | // motion event happened (days, hours, minutes, seconds ago) and the battery level 7 | // In sleep mode, Moteino + PIR motion sensor use about ~78uA 8 | // Make sure you adjust the settings in the configuration section below !!! 9 | 10 | // ********************************************************************************** 11 | // Copyright Felix Rusu, LowPowerLab.com 12 | // Library and code by Felix Rusu - felix@lowpowerlab.com 13 | // Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ 14 | // ********************************************************************************** 15 | // License 16 | // ********************************************************************************** 17 | // This program is free software; you can redistribute it 18 | // and/or modify it under the terms of the GNU General 19 | // Public License as published by the Free Software 20 | // Foundation; either version 3 of the License, or 21 | // (at your option) any later version. 22 | // 23 | // This program is distributed in the hope that it will 24 | // be useful, but WITHOUT ANY WARRANTY; without even the 25 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 26 | // PARTICULAR PURPOSE. See the GNU General Public 27 | // License for more details. 28 | // 29 | // You should have received a copy of the GNU General 30 | // Public License along with this program. 31 | // If not, see . 32 | // 33 | // Licence can be viewed at 34 | // http://www.gnu.org/licenses/gpl-3.0.txt 35 | // 36 | // Please maintain this license information along with authorship 37 | // and copyright notices in any redistribution of this code 38 | // ********************************************************************************** 39 | 40 | #include //get it here: https://github.com/LowPowerLab/RFM69 41 | #include //get it here: https://github.com/LowPowerLab/SPIFlash 42 | #include //get library from: https://github.com/LowPowerLab/LowPower 43 | //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ 44 | 45 | //********************************************************************************************* 46 | // *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE ************* 47 | //********************************************************************************************* 48 | #define NODEID 55 //unique for each node on same network 49 | #define NETWORKID 250 //the same on all nodes that talk to each other 50 | #define GATEWAYID 1 51 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 52 | //#define FREQUENCY RF69_433MHZ 53 | //#define FREQUENCY RF69_868MHZ 54 | #define FREQUENCY RF69_915MHZ 55 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 56 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 57 | #define SENDEVERYXLOOPS 4 //each loop sleeps 8 seconds, so send status message every this many loops (default "4" = 32 seconds) 58 | //********************************************************************************************* 59 | 60 | #define MOTIONPIN 1 //hardware interrupt 1 (D3) 61 | #define BATTERYSENSE A7 //through 1Meg+470Kohm and 0.1uF cap from battery VCC - this ratio divides the voltage to bring it below 3.3V where it is scaled to a readable range 62 | #define LED 9 // Moteinos have LEDs on D9 63 | //#define BLINK_EN //uncomment to make LED flash when messages are sent, leave out if you want low power 64 | 65 | #define SERIAL_BAUD 115200 66 | //#define SERIAL_EN //uncomment this line to enable serial IO debug messages, leave out if you want low power 67 | #ifdef SERIAL_EN 68 | #define DEBUG(input) {Serial.print(input); delay(1);} 69 | #define DEBUGln(input) {Serial.println(input); delay(1);} 70 | #else 71 | #define DEBUG(input); 72 | #define DEBUGln(input); 73 | #endif 74 | 75 | RFM69 radio; 76 | volatile boolean motionDetected=false; 77 | 78 | void setup() { 79 | #ifdef SERIAL_EN 80 | Serial.begin(SERIAL_BAUD); 81 | #endif 82 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 83 | #ifdef IS_RFM69HW 84 | radio.setHighPower(); //uncomment only for RFM69HW! 85 | #endif 86 | radio.encrypt(ENCRYPTKEY); 87 | pinMode(MOTIONPIN, INPUT); 88 | attachInterrupt(MOTIONPIN, motionIRQ, RISING); 89 | char buff[50]; 90 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 91 | DEBUGln(buff); 92 | } 93 | 94 | void motionIRQ() 95 | { 96 | motionDetected=true; 97 | //DEBUGln("I"); 98 | } 99 | 100 | char sendBuf[32]; 101 | byte sendLen; 102 | byte sendLoops=0; 103 | unsigned long MLO=0; //MailLastOpen (ago, in ms) 104 | unsigned long now = 0, time=0, lastSend = 0, temp = 0; 105 | 106 | void loop() { 107 | now = millis(); 108 | int batteryReading = analogRead(BATTERYSENSE); 109 | if (motionDetected && time-MLO > 20000) //avoid duplicates in 20second intervals 110 | { 111 | MLO = time; //save timestamp of event 112 | sprintf(sendBuf, "MOTION BAT:%i", batteryReading); 113 | sendLen = strlen(sendBuf); 114 | if (radio.sendWithRetry(GATEWAYID, sendBuf, sendLen)) 115 | { 116 | DEBUGln(" ok!"); 117 | #ifdef BLINK_EN 118 | Blink(LED,3); 119 | #endif 120 | } 121 | else DEBUGln(" nothing..."); 122 | radio.sleep(); 123 | motionDetected=false; 124 | } 125 | else sendLoops++; 126 | 127 | //send readings every SENDEVERYXLOOPS 128 | if (sendLoops>=SENDEVERYXLOOPS) 129 | { 130 | sendLoops=0; 131 | 132 | char periodO='X', periodC='X'; 133 | unsigned long lastOpened = (time - MLO) / 1000; //get seconds 134 | unsigned long LO = lastOpened; 135 | char* MLOstr="LO:99d23h59m"; 136 | char* BATstr="BAT:1024"; 137 | char* BATactual="BATA:5.00v"; 138 | 139 | if (lastOpened <= 59) periodO = 's'; //1-59 seconds 140 | else if (lastOpened <= 3599) { periodO = 'm'; lastOpened/=60; } //1-59 minutes 141 | else if (lastOpened <= 259199) { periodO = 'h'; lastOpened/=3600; } // 1-71 hours 142 | else if (lastOpened >= 259200) { periodO = 'd'; lastOpened/=86400; } // >=3 days 143 | 144 | if (periodO == 'd') 145 | sprintf(MLOstr, "LO:%ldd%ldh", lastOpened, (LO%86400)/3600); 146 | else if (periodO == 'h') 147 | sprintf(MLOstr, "LO:%ldh%ldm", lastOpened, (LO%3600)/60); 148 | else sprintf(MLOstr, "LO:%ld%c", lastOpened, periodO); 149 | 150 | //sprintf(BATstr, "BAT:%i", batteryReading); 151 | float battV = ((float)batteryReading * 3.3 * 9)/(1023*2.976); 152 | dtostrf(battV, 3,2, BATactual); 153 | sprintf(sendBuf, "%s BAT:%sv", MLOstr, BATactual); 154 | sendLen = strlen(sendBuf); 155 | radio.send(GATEWAYID, sendBuf, sendLen); 156 | radio.sleep(); 157 | DEBUG(sendBuf); DEBUG(" ("); DEBUG(sendLen); DEBUGln(")"); 158 | lastSend = time; 159 | #ifdef BLINK_EN 160 | Blink(LED, 5); 161 | #endif 162 | delay(10); motionDetected=false; //fix PIR false positive glitch 163 | } 164 | 165 | DEBUGln("LOOP"); 166 | time = time + 8000 + millis()-now + 480; //correct millis() resonator drift, may need to be tweaked to be accurate 167 | LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 168 | } 169 | 170 | void Blink(byte PIN, int DELAY_MS) 171 | { 172 | pinMode(PIN, OUTPUT); 173 | digitalWrite(PIN,HIGH); 174 | delay(DELAY_MS); 175 | digitalWrite(PIN,LOW); 176 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/MotionMote/MotionMote.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 sender/node sketch for the MotionMote 2 | // http://lowpowerlab.com/motion 3 | // PIR motion sensor connected to D3 (INT1) 4 | // When RISE happens on D3, the sketch transmits a "MOTION" msg to receiver Moteino and goes back to sleep 5 | // In sleep mode, Moteino + PIR motion sensor use about ~78uA 6 | // Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ 7 | // Make sure you adjust the settings in the configuration section below !!! 8 | 9 | // ********************************************************************************** 10 | // Copyright Felix Rusu of LowPowerLab.com, 2015-11-10 11 | // RFM69 library and sample code by Felix Rusu - lowpowerlab.com/contact 12 | // ********************************************************************************** 13 | // License 14 | // ********************************************************************************** 15 | // This program is free software; you can redistribute it 16 | // and/or modify it under the terms of the GNU General 17 | // Public License as published by the Free Software 18 | // Foundation; either version 3 of the License, or 19 | // (at your option) any later version. 20 | // 21 | // This program is distributed in the hope that it will 22 | // be useful, but WITHOUT ANY WARRANTY; without even the 23 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 24 | // PARTICULAR PURPOSE. See the GNU General Public 25 | // License for more details. 26 | // 27 | // You should have received a copy of the GNU General 28 | // Public License along with this program. 29 | // If not, see . 30 | // 31 | // Licence can be viewed at 32 | // http://www.gnu.org/licenses/gpl-3.0.txt 33 | // 34 | // Please maintain this license information along with authorship 35 | // and copyright notices in any redistribution of this code 36 | // ********************************************************************************** 37 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 38 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 39 | #include //comes with Arduino IDE (www.arduino.cc) 40 | #include //get library from: https://github.com/lowpowerlab/lowpower 41 | //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ 42 | 43 | //********************************************************************************************* 44 | //************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************* 45 | //********************************************************************************************* 46 | #define NODEID 88 //unique for each node on same network 47 | #define NETWORKID 100 //the same on all nodes that talk to each other 48 | #define GATEWAYID 1 49 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 50 | //#define FREQUENCY RF69_433MHZ 51 | //#define FREQUENCY RF69_868MHZ 52 | #define FREQUENCY RF69_915MHZ 53 | #define IS_RFM69HW //uncomment only for RFM69HW! Remove/comment if you have RFM69W! 54 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 55 | #define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL 56 | #define ATC_RSSI -75 57 | //********************************************************************************************* 58 | #define ACK_TIME 30 // max # of ms to wait for an ack 59 | #define ONBOARDLED 9 // Moteinos have LEDs on D9 60 | #define LED 5 // MotionOLEDMote has an external LED on D5 61 | #define MOTION_PIN 3 // D3 62 | #define MOTION_IRQ 1 // hardware interrupt 1 (D3) - where motion sensors OUTput is connected, this will generate an interrupt every time there is MOTION 63 | #define BATT_MONITOR A7 // Sense VBAT_COND signal (when powered externally should read ~3.25v/3.3v (1000-1023), when external power is cutoff it should start reading around 2.85v/3.3v * 1023 ~= 883 (ratio given by 10k+4.7K divider from VBAT_COND = 1.47 multiplier) 64 | #define BATT_CYCLES 450 // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cyclesyou would get ~1 hour intervals 65 | #define BATT_FORMULA(reading) reading * 0.00322 * 1.49 // >>> fine tune this parameter to match your voltage when fully charged 66 | // details on how this works: https://lowpowerlab.com/forum/index.php/topic,1206.0.html 67 | //#define SERIAL_EN //comment this out when deploying to an installed SM to save a few KB of sketch size 68 | #define SERIAL_BAUD 115200 69 | #ifdef SERIAL_EN 70 | #define DEBUG(input) {Serial.print(input); delay(1);} 71 | #define DEBUGln(input) {Serial.println(input); delay(1);} 72 | #else 73 | #define DEBUG(input); 74 | #define DEBUGln(input); 75 | #endif 76 | 77 | #ifdef ENABLE_ATC 78 | RFM69_ATC radio; 79 | #else 80 | RFM69 radio; 81 | #endif 82 | volatile boolean motionDetected=false; 83 | float batteryVolts = 5; 84 | char BATstr[10]; //longest battery voltage reading message = 9chars 85 | char sendBuf[32]; 86 | byte sendLen; 87 | 88 | void motionIRQ(void); 89 | void checkBattery(void); 90 | 91 | void setup() { 92 | Serial.begin(SERIAL_BAUD); 93 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 94 | #ifdef IS_RFM69HW 95 | radio.setHighPower(); //uncomment only for RFM69HW! 96 | #endif 97 | radio.encrypt(ENCRYPTKEY); 98 | 99 | //Auto Transmission Control - dials down transmit power to save battery (-100 is the noise floor, -90 is still pretty good) 100 | //For indoor nodes that are pretty static and at pretty stable temperatures (like a MotionMote) -90dBm is quite safe 101 | //For more variable nodes that can expect to move or experience larger temp drifts a lower margin like -70 to -80 would probably be better 102 | //Always test your ATC mote in the edge cases in your own environment to ensure ATC will perform as you expect 103 | #ifdef ENABLE_ATC 104 | radio.enableAutoPower(ATC_RSSI); 105 | #endif 106 | 107 | pinMode(MOTION_PIN, INPUT); 108 | attachInterrupt(MOTION_IRQ, motionIRQ, RISING); 109 | char buff[50]; 110 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 111 | DEBUGln(buff); 112 | pinMode(ONBOARDLED, OUTPUT); 113 | pinMode(LED, OUTPUT); 114 | radio.sendWithRetry(GATEWAYID, "START", 5); 115 | 116 | #ifdef ENABLE_ATC 117 | DEBUGln("RFM69_ATC Enabled (Auto Transmission Control)\n"); 118 | #endif 119 | } 120 | 121 | void motionIRQ() 122 | { 123 | motionDetected=true; 124 | DEBUGln("IRQ"); 125 | } 126 | 127 | uint16_t batteryReportCycles=0; 128 | void loop() { 129 | checkBattery(); 130 | if (motionDetected) 131 | { 132 | digitalWrite(LED, HIGH); 133 | sprintf(sendBuf, "MOTION BAT:%sv", BATstr); 134 | sendLen = strlen(sendBuf); 135 | 136 | if (radio.sendWithRetry(GATEWAYID, sendBuf, sendLen)) 137 | { 138 | DEBUG("MOTION ACK:OK! RSSI:"); 139 | DEBUG(radio.RSSI); 140 | batteryReportCycles = 0; 141 | } 142 | else DEBUG("MOTION ACK:NOK..."); 143 | 144 | DEBUG(" VIN: "); 145 | DEBUGln(BATstr); 146 | 147 | radio.sleep(); 148 | digitalWrite(LED, LOW); 149 | } 150 | else if (batteryReportCycles == BATT_CYCLES) 151 | { 152 | sprintf(sendBuf, "BAT:%sv", BATstr); 153 | sendLen = strlen(sendBuf); 154 | radio.sendWithRetry(GATEWAYID, sendBuf, sendLen); 155 | radio.sleep(); 156 | batteryReportCycles=0; 157 | } 158 | motionDetected=false; //do NOT move this after the SLEEP line below or motion will never be detected 159 | LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 160 | batteryReportCycles++; 161 | } 162 | 163 | uint16_t cycleCount=BATT_CYCLES; 164 | void checkBattery() 165 | { 166 | if (cycleCount++ == BATT_CYCLES) //only read battery every BATT_CYCLES sleep cycles 167 | { 168 | unsigned int readings=0; 169 | for (byte i=0; i<10; i++) //take 10 samples, and average 170 | readings+=analogRead(BATT_MONITOR); 171 | batteryVolts = BATT_FORMULA(readings / 10.0); 172 | dtostrf(batteryVolts, 3,2, BATstr); //update the BATStr which gets sent every BATT_CYCLES or along with the MOTION message 173 | cycleCount = 0; 174 | } 175 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/TxRxBlinky/TxRxBlinky.ino: -------------------------------------------------------------------------------- 1 | // *************************************************************************************** 2 | // Sample RFM69 sketch for Moteino to illustrate sending and receiving, button interrupts 3 | // *************************************************************************************** 4 | // When you press the button on the SENDER Moteino, it will send a short message to the 5 | // RECEIVER Moteino and wait for an ACK (acknowledgement that message was received) from 6 | // the RECEIVER Moteino. If the ACK was received, the SENDER will blink the onboard LED 7 | // a few times. The RECEIVER listens to a specific token, and it alternates the onboard LED 8 | // state from HIGH to LOW or vice versa whenever this token is received. 9 | // *************************************************************************************** 10 | // Hardware setup: 11 | // *************************************************************************************** 12 | // On the sender, hook up a momentary tactile button to D3 like this: 13 | // __-__ 14 | // __| |___ 15 | // GND ----> BTN ----> D3 (D11 on MoteinoMEGA) 16 | // Load this sketch on the RECEIVER with NODEID=RECEIVER (adjust in config section below) 17 | // Load this sketch on the SENDER with NODEID=SENDER (adjust in config section below) 18 | // RFM69 library and code by Felix Rusu - felix@lowpowerlab.com 19 | // Get libraries at: https://github.com/LowPowerLab/ 20 | // Make sure you adjust the settings in the configuration section below !!! 21 | // ********************************************************************************** 22 | // Copyright Felix Rusu, LowPowerLab.com 23 | // Library and code by Felix Rusu - felix@lowpowerlab.com 24 | // ********************************************************************************** 25 | // License 26 | // ********************************************************************************** 27 | // This program is free software; you can redistribute it 28 | // and/or modify it under the terms of the GNU General 29 | // Public License as published by the Free Software 30 | // Foundation; either version 3 of the License, or 31 | // (at your option) any later version. 32 | // 33 | // This program is distributed in the hope that it will 34 | // be useful, but WITHOUT ANY WARRANTY; without even the 35 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 36 | // PARTICULAR PURPOSE. See the GNU General Public 37 | // License for more details. 38 | // 39 | // You should have received a copy of the GNU General 40 | // Public License along with this program. 41 | // If not, see . 42 | // 43 | // Licence can be viewed at 44 | // http://www.gnu.org/licenses/gpl-3.0.txt 45 | // 46 | // Please maintain this license information along with authorship 47 | // and copyright notices in any redistribution of this code 48 | // ********************************************************************************** 49 | 50 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 51 | #include 52 | #include //get library from: https://github.com/lowpowerlab/lowpower 53 | 54 | //********************************************************************************************* 55 | // *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE ************* 56 | //********************************************************************************************* 57 | #define NETWORKID 100 //the same on all nodes that talk to each other 58 | #define RECEIVER 1 //unique ID of the gateway/receiver 59 | #define SENDER 2 60 | #define NODEID RECEIVER //change to "SENDER" if this is the sender node (the one with the button) 61 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 62 | //#define FREQUENCY RF69_433MHZ 63 | //#define FREQUENCY RF69_868MHZ 64 | #define FREQUENCY RF69_915MHZ 65 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 66 | #define IS_RFM69HW //uncomment only for RFM69HW! Remove/comment if you have RFM69W! 67 | //********************************************************************************************* 68 | #define SERIAL_BAUD 115200 69 | #ifdef __AVR_ATmega1284P__ 70 | #define LED 15 // Moteino MEGAs have LEDs on D15 71 | #define BUTTON_INT 1 //user button on interrupt 1 (D3) 72 | #define BUTTON_PIN 11 //user button on interrupt 1 (D3) 73 | #else 74 | #define LED 9 // Moteinos have LEDs on D9 75 | #define BUTTON_INT 1 //user button on interrupt 1 (D3) 76 | #define BUTTON_PIN 3 //user button on interrupt 1 (D3) 77 | #endif 78 | 79 | #define LED_GREEN 4 //GREEN LED on the SENDER 80 | #define LED_RED 5 //RED LED on the SENDER 81 | #define RX_TOGGLE_PIN 7 //GPIO to toggle on the RECEIVER 82 | 83 | RFM69 radio; 84 | 85 | void setup() { 86 | Serial.begin(SERIAL_BAUD); 87 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 88 | #ifdef IS_RFM69HW 89 | radio.setHighPower(); //only for RFM69HW! 90 | #endif 91 | radio.encrypt(ENCRYPTKEY); 92 | char buff[50]; 93 | sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 94 | Serial.println(buff); 95 | Serial.flush(); 96 | pinMode(BUTTON_PIN, INPUT_PULLUP); 97 | pinMode(LED, OUTPUT); 98 | attachInterrupt(BUTTON_INT, handleButton, FALLING); 99 | 100 | pinMode(LED_GREEN, OUTPUT); 101 | pinMode(LED_RED, OUTPUT); 102 | pinMode(RX_TOGGLE_PIN, OUTPUT); 103 | digitalWrite(LED_GREEN, LOW); 104 | digitalWrite(LED_RED, HIGH); 105 | } 106 | 107 | //******** THIS IS INTERRUPT BASED DEBOUNCING FOR BUTTON ATTACHED TO D3 (INTERRUPT 1) 108 | #define FLAG_INTERRUPT 0x01 109 | volatile int mainEventFlags = 0; 110 | boolean buttonPressed = false; 111 | void handleButton() 112 | { 113 | mainEventFlags |= FLAG_INTERRUPT; 114 | } 115 | 116 | byte LEDSTATE=LOW; //LOW=0 117 | void loop() { 118 | //******** THIS IS INTERRUPT BASED DEBOUNCING FOR BUTTON ATTACHED TO D3 (INTERRUPT 1) 119 | if (mainEventFlags & FLAG_INTERRUPT) 120 | { 121 | LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_ON); 122 | mainEventFlags &= ~FLAG_INTERRUPT; 123 | if (!digitalRead(BUTTON_PIN)) { 124 | buttonPressed=true; 125 | } 126 | } 127 | 128 | if (buttonPressed) 129 | { 130 | Serial.println("Button pressed!"); 131 | buttonPressed = false; 132 | 133 | if(LEDSTATE==LOW) 134 | { 135 | LEDSTATE=HIGH; 136 | digitalWrite(LED_GREEN, HIGH); 137 | digitalWrite(LED_RED, LOW); 138 | } 139 | else 140 | { 141 | LEDSTATE=LOW; 142 | digitalWrite(LED_GREEN, LOW); 143 | digitalWrite(LED_RED, HIGH); 144 | } 145 | 146 | if (radio.sendWithRetry(RECEIVER, "Hi", 2)) //target node Id, message as string or byte array, message length 147 | Blink(LED, 40, 3); //blink LED 3 times, 40ms between blinks 148 | } 149 | 150 | //check if something was received (could be an interrupt from the radio) 151 | if (radio.receiveDone()) 152 | { 153 | //print message received to serial 154 | Serial.print('[');Serial.print(radio.SENDERID);Serial.print("] "); 155 | Serial.print((char*)radio.DATA); 156 | Serial.print(" [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]"); 157 | Serial.println(); 158 | 159 | //check if received message is 2 bytes long, and check if the message is specifically "Hi" 160 | if (radio.DATALEN==2 && radio.DATA[0]=='H' && radio.DATA[1]=='i') 161 | { 162 | if(LEDSTATE==LOW) 163 | LEDSTATE=HIGH; 164 | else LEDSTATE=LOW; 165 | digitalWrite(LED, LEDSTATE); 166 | digitalWrite(RX_TOGGLE_PIN, LEDSTATE); 167 | } 168 | 169 | //check if sender wanted an ACK 170 | if (radio.ACKRequested()) 171 | { 172 | radio.sendACK(); 173 | Serial.print(" - ACK sent"); 174 | } 175 | } 176 | 177 | radio.receiveDone(); //put radio in RX mode 178 | Serial.flush(); //make sure all serial data is clocked out before sleeping the MCU 179 | LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_ON); //sleep Moteino in low power mode (to save battery) 180 | } 181 | 182 | void Blink(byte PIN, byte DELAY_MS, byte loops) 183 | { 184 | for (byte i=0; i. 28 | // 29 | // Licence can be viewed at 30 | // http://www.gnu.org/licenses/gpl-3.0.txt 31 | // 32 | // Please maintain this license information along with authorship 33 | // and copyright notices in any redistribution of this code 34 | // ********************************************************************************** 35 | #include //get it here: http://github.com/lowpowerlab/rfm69 36 | #include //get it here: http://github.com/lowpowerlab/spiflash 37 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming 38 | #include //comes with Arduino IDE (www.arduino.cc) 39 | 40 | //***************************************************************************************************************************** 41 | // ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! 42 | //***************************************************************************************************************************** 43 | #define GATEWAYID 1 44 | #define NODEID 133 45 | #define NETWORKID 100 46 | //#define FREQUENCY RF69_433MHZ 47 | //#define FREQUENCY RF69_868MHZ 48 | #define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 49 | #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 50 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 51 | 52 | #define CHIMEPIN 4 // active HIGH chime signal from detector H11AA1 circuit 53 | #define RELAYPIN1 6 //for the bell ring relay we just need 2 digital pins together to activate the relay for a short pulse 54 | #define RELAYPIN2 7 //for the bell ring relay we just need 2 digital pins together to activate the relay for a short pulse 55 | #define DISABLE_RELAY 5 //for the bell disable relay we use a single digital pin through a transistor 56 | #define RELAY_PULSE_MS 250 //just enough that the doorbell chime will trigger 57 | #define RINGDELAY 3000 //time between rings (avoid fast repeated rings) 58 | //***************************************************************************************************************************** 59 | #define LED 9 //pin connected to onboard LED 60 | #define SERIAL_BAUD 115200 61 | #define SERIAL_EN //comment out if you don't want any serial output 62 | 63 | #ifdef SERIAL_EN 64 | #define DEBUG(input) Serial.print(input) 65 | #define DEBUGln(input) Serial.println(input) 66 | #else 67 | #define DEBUG(input) 68 | #define DEBUGln(input) 69 | #endif 70 | 71 | RFM69 radio; 72 | ///////////////////////////////////////////////////////////////////////////// 73 | // flash(SPI_CS, MANUFACTURER_ID) 74 | // SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) 75 | // MANUFACTURER_ID - OPTIONAL, 0xEF30 for windbond 4mbit flash (Moteino OEM) 76 | ///////////////////////////////////////////////////////////////////////////// 77 | SPIFlash flash(8, 0xEF30); //regular Moteinos have FLASH MEM on D8, MEGA has it on D4 78 | char buff[50]; 79 | 80 | void setup(void) 81 | { 82 | Serial.begin(SERIAL_BAUD); 83 | pinMode(CHIMEPIN, INPUT); 84 | pinMode(RELAYPIN1, OUTPUT); 85 | pinMode(RELAYPIN2, OUTPUT); 86 | pinMode(DISABLE_RELAY, OUTPUT); 87 | pinMode(LED, OUTPUT); 88 | 89 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 90 | #ifdef IS_RFM69HW 91 | radio.setHighPower(); //uncomment only for RFM69HW! 92 | #endif 93 | radio.encrypt(ENCRYPTKEY); 94 | 95 | sprintf(buff, "DoorBellMote : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 96 | DEBUGln(buff); 97 | 98 | if (flash.initialize()) 99 | DEBUGln("SPI Flash Init OK"); 100 | else 101 | DEBUGln("SPI Flash Init FAIL! (is chip present?)"); 102 | 103 | radio.sendWithRetry(GATEWAYID, "START", 6); 104 | Blink(LED, 100); 105 | Blink(LED, 100); 106 | Blink(LED, 100); 107 | } 108 | 109 | uint32_t doorPulseCount = 0; 110 | uint32_t lastStatusTimestamp=0; 111 | uint32_t LEDCYCLETIMER=0; 112 | byte LEDSTATE=LOW; 113 | char input; 114 | boolean ring=false; 115 | boolean disable=false; 116 | byte disableStatus=0; 117 | 118 | void loop() 119 | { 120 | if (Serial.available()) 121 | input = Serial.read(); 122 | 123 | if (input=='r') 124 | { 125 | DEBUGln("Relay test..."); 126 | pulseRelay(); 127 | input = 0; 128 | } 129 | 130 | if (millis()-(lastStatusTimestamp)>RINGDELAY) 131 | { 132 | if (digitalRead(CHIMEPIN) == HIGH) 133 | { 134 | lastStatusTimestamp = millis(); 135 | radio.sendWithRetry(GATEWAYID, "RING", 4); 136 | Blink(LED,20); 137 | Blink(LED,20); 138 | Blink(LED,20); 139 | } 140 | } 141 | 142 | if (radio.receiveDone()) 143 | { 144 | DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); 145 | for (byte i = 0; i < radio.DATALEN; i++) 146 | DEBUG((char)radio.DATA[i]); 147 | 148 | if (radio.DATALEN==4) 149 | if (radio.DATA[0]=='R' && radio.DATA[1]=='I' && radio.DATA[2]=='N' && radio.DATA[3]=='G') 150 | ring = true; 151 | 152 | if (radio.DATALEN==6) 153 | if (radio.DATA[0]=='B' && radio.DATA[1]=='E' && radio.DATA[2]=='L' && radio.DATA[3]=='L' && radio.DATA[4]==':') 154 | if (radio.DATA[5]=='0') 155 | { 156 | disableStatus = 1; 157 | disable = true; 158 | } 159 | else if (radio.DATA[5]=='1') 160 | { 161 | disableStatus = 0; 162 | disable = true; 163 | } 164 | 165 | // wireless programming token check 166 | // DO NOT REMOVE, or GarageMote will not be wirelessly programmable any more! 167 | CheckForWirelessHEX(radio, flash, true); 168 | 169 | //first send any ACK to request 170 | DEBUG(" [RX_RSSI:");DEBUG(radio.RSSI);DEBUG("]"); 171 | if (radio.ACKRequested()) 172 | { 173 | radio.sendACK(); 174 | DEBUG(" - ACK sent."); 175 | } 176 | 177 | if (ring) 178 | { 179 | //if other relay is ON we must temporarily turn it off while we pulse the RING relay, to avoid any rail collapse and reset 180 | if (disableStatus) digitalWrite(DISABLE_RELAY, 0); 181 | pulseRelay(); 182 | if (disableStatus) digitalWrite(DISABLE_RELAY, 1); 183 | radio.sendWithRetry(GATEWAYID, "RING OK", 4); 184 | ring = false; 185 | } 186 | 187 | if (disable) 188 | { 189 | digitalWrite(DISABLE_RELAY, disableStatus); //disable it 190 | sprintf(buff, "BELL:%d", disableStatus ? 0 : 1); 191 | radio.sendWithRetry(GATEWAYID, buff, 6); 192 | disable=false; 193 | } 194 | 195 | DEBUGln(); 196 | } 197 | 198 | if (millis() - LEDCYCLETIMER > 2000) //flip onboard LED state every so often to indicate activity 199 | { 200 | LEDCYCLETIMER = millis(); 201 | LEDSTATE = !LEDSTATE; 202 | digitalWrite(LED, LEDSTATE); 203 | } 204 | } 205 | 206 | void pulseRelay() 207 | { 208 | digitalWrite(RELAYPIN1, HIGH); 209 | digitalWrite(RELAYPIN2, HIGH); 210 | delay(RELAY_PULSE_MS); 211 | digitalWrite(RELAYPIN1, LOW); 212 | digitalWrite(RELAYPIN2, LOW); 213 | } 214 | 215 | void Blink(byte PIN, byte DELAY_MS) 216 | { 217 | pinMode(PIN, OUTPUT); 218 | digitalWrite(PIN,HIGH); 219 | delay(DELAY_MS/2); 220 | digitalWrite(PIN,LOW); 221 | delay(DELAY_MS/2); 222 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/OLEDMote/OLEDMote.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 sketch for the MotionOLED mote containing the OLED 2 | // Displays any messages on the network on the OLED display and beeps the buzzer every time a message is received 3 | // The side button will step through 10 past received messages 4 | // Library and code by Felix Rusu - felix@lowpowerlab.com 5 | // Get libraries at: https://github.com/LowPowerLab/ 6 | // Make sure you adjust the settings in the configuration section below !!! 7 | 8 | // ********************************************************************************** 9 | // Copyright Felix Rusu, LowPowerLab.com 10 | // Library and code by Felix Rusu - felix@lowpowerlab.com 11 | // ********************************************************************************** 12 | // License 13 | // ********************************************************************************** 14 | // This program is free software; you can redistribute it 15 | // and/or modify it under the terms of the GNU General 16 | // Public License as published by the Free Software 17 | // Foundation; either version 3 of the License, or 18 | // (at your option) any later version. 19 | // 20 | // This program is distributed in the hope that it will 21 | // be useful, but WITHOUT ANY WARRANTY; without even the 22 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 23 | // PARTICULAR PURPOSE. See the GNU General Public 24 | // License for more details. 25 | // 26 | // You should have received a copy of the GNU General 27 | // Public License along with this program. 28 | // If not, see . 29 | // 30 | // Licence can be viewed at 31 | // http://www.gnu.org/licenses/gpl-3.0.txt 32 | // 33 | // Please maintain this license information along with authorship 34 | // and copyright notices in any redistribution of this code 35 | // ********************************************************************************** 36 | 37 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 38 | #include 39 | #include //get library from: https://github.com/lowpowerlab/lowpower 40 | #include "U8glib.h" //get library from: https://code.google.com/p/u8glib/ 41 | 42 | //********************************************************************************************* 43 | // *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE ************* 44 | //********************************************************************************************* 45 | #define NODEID 122 //unique for each node on same network 46 | #define NETWORKID 100 //the same on all nodes that talk to each other 47 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 48 | //#define FREQUENCY RF69_433MHZ 49 | //#define FREQUENCY RF69_868MHZ 50 | #define FREQUENCY RF69_915MHZ 51 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 52 | #define IS_RFM69HW //uncomment only for RFM69HW! Remove/comment if you have RFM69W! 53 | //********************************************************************************************* 54 | 55 | #define SERIAL_BAUD 115200 56 | #define LED 5 // Moteinos have LEDs on D9, but for MotionMote we are using the external led on D5 57 | #define BUZZER 6 58 | #define BUTTON_INT 1 //user button on interrupt 1 59 | #define BUTTON_PIN 3 //user button on interrupt 1 60 | 61 | RFM69 radio; 62 | U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI SSD1306 OLED 128x64 63 | bool promiscuousMode = true; //set to 'true' to sniff all packets on the same network 64 | 65 | void setup() { 66 | Serial.begin(SERIAL_BAUD); 67 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 68 | #ifdef IS_RFM69HW 69 | radio.setHighPower(); //only for RFM69HW! 70 | #endif 71 | radio.encrypt(ENCRYPTKEY); 72 | radio.promiscuous(promiscuousMode); 73 | char buff[50]; 74 | sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 75 | Serial.println(buff); 76 | pinMode(BUZZER, OUTPUT); 77 | 78 | //configure OLED 79 | u8g.setRot180(); //flip screen 80 | // assign default color value 81 | if ( u8g.getMode() == U8G_MODE_R3G3B2 ) 82 | u8g.setColorIndex(255); // white 83 | else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) 84 | u8g.setColorIndex(3); // max intensity 85 | else if ( u8g.getMode() == U8G_MODE_BW ) 86 | u8g.setColorIndex(1); // pixel on 87 | else if ( u8g.getMode() == U8G_MODE_HICOLOR ) 88 | u8g.setHiColorByRGB(255,255,255); 89 | u8g.begin(); 90 | Serial.flush(); 91 | pinMode(BUTTON_PIN, INPUT_PULLUP); 92 | attachInterrupt(BUTTON_INT, handleButton, FALLING); 93 | } 94 | 95 | #define FLAG_INTERRUPT 0x01 96 | volatile int mainEventFlags = 0; 97 | boolean buttonPressed = false; 98 | void handleButton() 99 | { 100 | mainEventFlags |= FLAG_INTERRUPT; 101 | } 102 | 103 | byte ackCount=0; 104 | 105 | #define MSG_MAX_LEN 17 //OLED 1 line max # of chars (16 + EOL) 106 | #define HISTORY_LEN 10 //hold this many past messages 107 | typedef struct { 108 | char data[MSG_MAX_LEN]; 109 | int rssi; 110 | byte from; 111 | } Message; 112 | Message * messageHistory = new Message[HISTORY_LEN]; 113 | 114 | byte lastMessageIndex = HISTORY_LEN; 115 | byte currMessageIndex = HISTORY_LEN; 116 | byte historyLength = 0; 117 | void loop() { 118 | if (mainEventFlags & FLAG_INTERRUPT) 119 | { 120 | LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_ON); 121 | mainEventFlags &= ~FLAG_INTERRUPT; 122 | if (!digitalRead(BUTTON_PIN)) { 123 | buttonPressed=true; 124 | } 125 | } 126 | 127 | if (buttonPressed) 128 | { 129 | buttonPressed = false; 130 | Beep(10, false); 131 | 132 | //save non-ACK messages in a circular buffer 133 | if (!radio.ACK_RECEIVED && historyLength > 1) //only care if at least 2 messages saved. if only 1 message it should be displayed already 134 | { 135 | if (currMessageIndex==0) 136 | currMessageIndex=historyLength-1; 137 | else currMessageIndex--; 138 | 139 | //Serial.print("HIST currIndex/histLen=");Serial.print(currMessageIndex+1);Serial.print("/");Serial.print(historyLength); 140 | //Serial.print(" - "); 141 | //Serial.println(messageHistory[currMessageIndex].data); 142 | 143 | u8g.firstPage(); 144 | do { 145 | draw(messageHistory[currMessageIndex].data, messageHistory[currMessageIndex].rssi, messageHistory[currMessageIndex].from, true); 146 | } while(u8g.nextPage()); 147 | //delay(10); //give OLED time to draw? 148 | } 149 | } 150 | 151 | if (radio.receiveDone()) 152 | { 153 | Serial.print('[');Serial.print(radio.SENDERID);Serial.print("] "); 154 | if (promiscuousMode) 155 | Serial.print("to [");Serial.print(radio.TARGETID);Serial.print("] "); 156 | 157 | Serial.print((char*)radio.DATA); 158 | Serial.print(" [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]"); 159 | Serial.println(); 160 | 161 | saveToHistory((char *)radio.DATA, radio.RSSI, radio.SENDERID); 162 | Blink(LED,3); 163 | Beep(20, true); 164 | u8g.firstPage(); 165 | do { 166 | draw((char*)radio.DATA, radio.RSSI, radio.SENDERID, false); 167 | } while(u8g.nextPage()); 168 | //delay(10); //give OLED time to draw? 169 | } 170 | radio.receiveDone(); 171 | Serial.flush(); 172 | LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_ON); 173 | } 174 | 175 | float batteryVolts = 5; 176 | char* BATstr="BAT:5.00v"; 177 | void draw(char * data, int rssi, byte from, boolean isHist) { 178 | char buff[20]; 179 | // graphic commands to redraw the complete screen should be placed here 180 | u8g.setFont(u8g_font_unifont); 181 | u8g.drawStr( 0, 10, data); 182 | sprintf(buff, "ID:%d", from); 183 | u8g.drawStr( 0, 25, buff); 184 | sprintf(buff, "RSSI:%d", rssi); 185 | u8g.drawStr( 60, 25, buff); 186 | 187 | if (!isHist) 188 | { 189 | batteryVolts = analogRead(A7) * 0.00322 * 1.42; 190 | dtostrf(batteryVolts, 3,2, BATstr); 191 | sprintf(buff, "BAT:%sv", BATstr); 192 | u8g.drawStr( 0, 55, buff); 193 | } 194 | } 195 | 196 | void Beep(byte theDelay, boolean both) 197 | { 198 | if (theDelay > 20) theDelay = 20; 199 | tone(BUZZER, 4200); //4200 200 | delay(theDelay); 201 | noTone(BUZZER); 202 | LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_ON); 203 | if (both) 204 | { 205 | tone(BUZZER, 4500); //4500 206 | delay(theDelay); 207 | noTone(BUZZER); 208 | } 209 | } 210 | 211 | void Blink(byte PIN, int DELAY_MS) 212 | { 213 | pinMode(PIN, OUTPUT); 214 | digitalWrite(PIN,HIGH); 215 | delay(DELAY_MS); 216 | digitalWrite(PIN,LOW); 217 | } 218 | 219 | void saveToHistory(char * msg, int rssi, byte from) 220 | { 221 | byte length = strlen(msg); 222 | byte i = 0; 223 | if (lastMessageIndex >=9) lastMessageIndex = 0; 224 | else lastMessageIndex++; 225 | currMessageIndex = lastMessageIndex; 226 | if (historyLength < HISTORY_LEN) historyLength++; 227 | 228 | //Serial.print("HIST SAVE lastIndex=");Serial.print(lastMessageIndex);Serial.print(" strlen=");Serial.print(length); 229 | //Serial.print(" msg=["); 230 | 231 | for (; i<(MSG_MAX_LEN-1) && (i < length); i++) 232 | { 233 | messageHistory[lastMessageIndex].data[i] = msg[i]; 234 | Serial.print(msg[i]); 235 | } 236 | //Serial.print("] copied:"); 237 | messageHistory[lastMessageIndex].data[i] = '\0'; //terminate string 238 | //Serial.println((char*)messageHistory[lastMessageIndex].data); 239 | 240 | messageHistory[lastMessageIndex].rssi = rssi; 241 | messageHistory[lastMessageIndex].from = from; 242 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/PulseMeter/PulseMeter.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 sketch for PulseMote - reading an EE-SY310 based water/pulse meter 2 | // Example: https://lowpowerlab.com/blog/2013/02/02/meet-the-watermote-moteino-based-water-meter-reader-ee-sy310/ 3 | // Copyright (c) 2015 Felix Rusu (felix@lowpowerlab.com). All rights reserved. 4 | // ********************************************************************************** 5 | // License 6 | // ********************************************************************************** 7 | // This program is free software; you can redistribute it 8 | // and/or modify it under the terms of the GNU General 9 | // Public License as published by the Free Software 10 | // Foundation; either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // This program is distributed in the hope that it will 14 | // be useful, but WITHOUT ANY WARRANTY; without even the 15 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 16 | // PARTICULAR PURPOSE. See the GNU General Public 17 | // License for more details. 18 | // 19 | // You should have received a copy of the GNU General 20 | // Public License along with this program. 21 | // If not, see . 22 | // 23 | // Licence can be viewed at 24 | // http://www.gnu.org/licenses/gpl-3.0.txt 25 | // 26 | // Please maintain this license information along with authorship 27 | // and copyright notices in any redistribution of this code 28 | // *************************************************************************************************************************** 29 | #include //get it here: http://github.com/lowpowerlab/rfm69 30 | #include //get it here: http://github.com/lowpowerlab/spiflash 31 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming 32 | #include 33 | #include 34 | #include 35 | //********************************************************************************************* 36 | //************ IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE ************* 37 | //********************************************************************************************* 38 | #define NODEID 5 39 | #define GATEWAYID 1 40 | #define NETWORKID 250 41 | #define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 42 | #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 43 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 44 | #define PULSESPERGALLON 45 //how many pulses from sensor equal 1 gallon 45 | #define GPMTHRESHOLD 8000 // GPM will reset after this many MS if no pulses are registered 46 | #define XMITPERIOD 5000 // GPMthreshold should be less than 2*XMITPERIOD 47 | //********************************************************************************************* 48 | #ifdef __AVR_ATmega1284P__ 49 | #define LED 15 // Moteino MEGAs have LEDs on D15 50 | #define INTERRUPTPIN 1 //INT1 = digital pin 11 (must be a hardware interrupt pin!) 51 | #else 52 | #define LED 9 // Moteinos have LEDs on D9 53 | #define INTERRUPTPIN 1 //INT1 = digital pin 3 (must be a hardware interrupt pin!) 54 | #endif 55 | //********************************************************************************************* 56 | #define SERIAL_EN //uncomment this line to enable serial IO (when you debug Moteino and need serial output) 57 | #define SERIAL_BAUD 115200 58 | #ifdef SERIAL_EN 59 | #define DEBUG(input) {Serial.print(input);} 60 | #define DEBUGln(input) {Serial.println(input);} 61 | #else 62 | #define DEBUG(input); 63 | #define DEBUGln(input); 64 | #endif 65 | 66 | RFM69 radio; 67 | SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino) 68 | 69 | volatile byte ledState = LOW; 70 | volatile unsigned long PulseCounterVolatile = 0; // use volatile for shared variables 71 | unsigned long NOW = 0; 72 | unsigned long PulseCounter = 0; 73 | unsigned long LASTMINUTEMARK = 0; 74 | unsigned long PULSECOUNTLASTMINUTEMARK = 0; //keeps pulse count at the last minute mark 75 | 76 | byte COUNTEREEPROMSLOTS = 10; 77 | unsigned long COUNTERADDRBASE = 8; //address in EEPROM that points to the first possible slot for a counter 78 | unsigned long COUNTERADDR = 0; //address in EEPROM that points to the latest Counter in EEPROM 79 | byte secondCounter = 0; 80 | 81 | unsigned long TIMESTAMP_pulse_prev = 0; 82 | unsigned long TIMESTAMP_pulse_curr = 0; 83 | int pulseAVGInterval = 0; 84 | int pulsesPerXMITperiod = 0; 85 | float GPM=0, GLM=0, GAL=0, GALlast=0, GPMlast=0, GLMlast=0; 86 | byte sendLen; 87 | char buff[80]; 88 | char* GALstr="99999999999999.99"; //longest expected GAL message 89 | char* GPMstr="99999.99"; //longest expected GPM message 90 | char* GLMstr="9999999.99"; //longest expected GLM message 91 | boolean WPReady = false; 92 | 93 | void setup() { 94 | #ifdef SERIAL_EN 95 | Serial.begin(SERIAL_BAUD); 96 | #endif 97 | 98 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 99 | #ifdef IS_RFM69HW 100 | radio.setHighPower(); //uncomment only for RFM69HW! 101 | #endif 102 | radio.encrypt(ENCRYPTKEY); 103 | pinMode(LED, OUTPUT); 104 | 105 | //initialize counter from EEPROM 106 | unsigned long savedCounter = EEPROM_Read_Counter(); 107 | if (savedCounter <=0) savedCounter = 1; //avoid division by 0 108 | PulseCounterVolatile = PulseCounter = PULSECOUNTLASTMINUTEMARK = savedCounter; 109 | attachInterrupt(INTERRUPTPIN, pulseCounterInterrupt, RISING); 110 | Timer1.initialize(XMITPERIOD * 1000L); 111 | Timer1.attachInterrupt(XMIT); 112 | 113 | sprintf(buff, "\nTransmitting at %d Mhz, id:%d nid:%d gid:%d", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915, NODEID, NETWORKID, GATEWAYID); 114 | DEBUG(buff); 115 | for (byte i=0;i GPMTHRESHOLD) 153 | //more than 'GPMthreshold' seconds passed since last pulse... resetting GPM 154 | pulsesPerXMITperiod=pulseAVGInterval=0; 155 | else 156 | { 157 | pulsesPerXMITperiod++; 158 | pulseAVGInterval += TIMESTAMP_pulse_curr - TIMESTAMP_pulse_prev; 159 | } 160 | interrupts(); 161 | } 162 | 163 | void XMIT() 164 | { 165 | noInterrupts(); 166 | PulseCounter = PulseCounterVolatile; 167 | interrupts(); 168 | 169 | if (millis() - TIMESTAMP_pulse_curr >= 5000) 170 | { 171 | ledState = !ledState; 172 | digitalWrite(LED, ledState); 173 | } 174 | 175 | //calculate Gallons counter 176 | GAL = ((float)PulseCounter)/PULSESPERGALLON; 177 | DEBUG("PulseCounter:");DEBUG(PulseCounter);DEBUG(", GAL: "); DEBUGln(GAL); 178 | 179 | //calculate & output GPM 180 | GPM = pulseAVGInterval > 0 ? 60.0 * 1000 * (1.0/PULSESPERGALLON)/(pulseAVGInterval/pulsesPerXMITperiod) 181 | : 0; 182 | dtostrf(GAL,3,2, GALstr); 183 | dtostrf(GPM,3,2, GPMstr); 184 | 185 | pulsesPerXMITperiod = 0; 186 | pulseAVGInterval = 0; 187 | secondCounter += XMITPERIOD/1000; 188 | 189 | //once per minute, output a GallonsLastMinute count 190 | if (secondCounter>=60) 191 | { 192 | //DEBUG("60sec mark ... "); 193 | secondCounter=0; 194 | GLM = ((float)(PulseCounter - PULSECOUNTLASTMINUTEMARK))/PULSESPERGALLON; 195 | PULSECOUNTLASTMINUTEMARK = PulseCounter; 196 | EEPROM_Write_Counter(PulseCounter); 197 | dtostrf(GLM,3,2, GLMstr); 198 | sprintf(buff, "GAL:%s GPM:%s GLM:%s", GALstr, GPMstr, GLMstr); 199 | //DEBUGln("done"); 200 | } 201 | else 202 | { 203 | sprintf(buff, "GAL:%s GPM:%s", GALstr, GPMstr); 204 | } 205 | 206 | if (GPM!=GPMlast || GAL!=GALlast || GLM!=GLMlast) 207 | { 208 | sendLen = strlen(buff); 209 | radio.sendWithRetry(GATEWAYID, buff, sendLen); 210 | GALlast = GAL; 211 | GPMlast = GPM; 212 | GLMlast = GLM; 213 | } 214 | 215 | DEBUGln(buff); 216 | } 217 | 218 | unsigned long EEPROM_Read_Counter() 219 | { 220 | return EEPROM_Read_ULong(EEPROM_Read_ULong(COUNTERADDR)); 221 | } 222 | 223 | void EEPROM_Write_Counter(unsigned long counterNow) 224 | { 225 | if (counterNow == EEPROM_Read_Counter()) 226 | { 227 | DEBUG("{EEPROM-SKIP(no changes)}"); 228 | return; //skip if nothing changed 229 | } 230 | 231 | DEBUG("{EEPROM-SAVE("); 232 | DEBUG(EEPROM_Read_ULong(COUNTERADDR)); 233 | DEBUG(")="); 234 | DEBUG(PulseCounter); 235 | DEBUG("}"); 236 | 237 | unsigned long CounterAddr = EEPROM_Read_ULong(COUNTERADDR); 238 | if (CounterAddr == COUNTERADDRBASE+8*(COUNTEREEPROMSLOTS-1)) 239 | CounterAddr = COUNTERADDRBASE; 240 | else CounterAddr += 8; 241 | 242 | EEPROM_Write_ULong(CounterAddr, counterNow); 243 | EEPROM_Write_ULong(COUNTERADDR, CounterAddr); 244 | } 245 | 246 | unsigned long EEPROM_Read_ULong(int address) 247 | { 248 | unsigned long temp; 249 | for (byte i=0; i<8; i++) 250 | temp = (temp << 8) + EEPROM.read(address++); 251 | return temp; 252 | } 253 | 254 | void EEPROM_Write_ULong(int address, unsigned long data) 255 | { 256 | for (byte i=0; i<8; i++) 257 | { 258 | EEPROM.write(address+7-i, data); 259 | data = data >> 8; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/WeatherNode/WeatherNode.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************************************** 2 | // WeatherShield sketch that works with Moteinos equipped with RFM69W/RFM69HW and WeatherShield 3 | // It sends periodic highly accurate weather readings (temp, hum, atm pressure) from the 4 | // WeatherShield to the base node/gateway Moteino 5 | // Can be adapted to use Moteinos/Arduinos using RFM12B or other RFM69 variants (RFM69CW, RFM69HCW) 6 | // For use with MoteinoMEGA you will have to revisit the pin definitions defined below 7 | // http://www.LowPowerLab.com/WeatherShield 8 | // Used in this project: http://lowpowerlab.com/blog/2015/07/24/attic-fan-cooling-tests/ 9 | // 2015-07-23 (C) Felix Rusu of http://www.LowPowerLab.com/ 10 | // ********************************************************************************************************** 11 | // License 12 | // ********************************************************************************************************** 13 | // This program is free software; you can redistribute it 14 | // and/or modify it under the terms of the GNU General 15 | // Public License as published by the Free Software 16 | // Foundation; either version 3 of the License, or 17 | // (at your option) any later version. 18 | // 19 | // This program is distributed in the hope that it will 20 | // be useful, but WITHOUT ANY WARRANTY; without even the 21 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 22 | // PARTICULAR PURPOSE. See the GNU General Public 23 | // License for more details. 24 | // 25 | // You should have received a copy of the GNU General 26 | // Public License along with this program. 27 | // If not, see . 28 | // 29 | // Licence can be viewed at 30 | // http://www.gnu.org/licenses/gpl-3.0.txt 31 | // 32 | // Please maintain this license information along with authorship 33 | // and copyright notices in any redistribution of this code 34 | // *************************************************************************************************************************** 35 | #include //get it here: http://github.com/lowpowerlab/rfm69 36 | #include //get it here: http://github.com/lowpowerlab/spiflash 37 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming 38 | #include //comes with Arduino 39 | 40 | #include //get it here: https://github.com/LowPowerLab/SFE_BMP180 41 | #include //get it here: https://github.com/LowPowerLab/SI7021 42 | #include //comes with Arduino 43 | 44 | #include //get library from: https://github.com/lowpowerlab/lowpower 45 | //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ 46 | 47 | //***************************************************************************************************************************** 48 | // ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS 49 | //***************************************************************************************************************************** 50 | #define GATEWAYID 1 51 | #define NODEID 164 52 | #define NETWORKID 100 53 | //#define FREQUENCY RF69_433MHZ 54 | //#define FREQUENCY RF69_868MHZ 55 | #define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 56 | #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 57 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 58 | #define SEND_LOOPS 15 //send data this many sleep loops (15 loops of 8sec cycles = 120sec ~ 2 minutes) 59 | //********************************************************************************************* 60 | #define SLEEP_FASTEST SLEEP_15MS 61 | #define SLEEP_FAST SLEEP_250MS 62 | #define SLEEP_SEC SLEEP_1S 63 | #define SLEEP_LONG SLEEP_2S 64 | #define SLEEP_LONGER SLEEP_4S 65 | #define SLEEP_LONGEST SLEEP_8S 66 | period_t sleepTime = SLEEP_LONGEST; //period_t is an enum type defined in the LowPower library (LowPower.h) 67 | //********************************************************************************************* 68 | #define BATT_MONITOR_EN A3 //enables battery voltage divider to get a reading from a battery, disable it to save power 69 | #define BATT_MONITOR A7 //through 1Meg+470Kohm and 0.1uF cap from battery VCC - this ratio divides the voltage to bring it below 3.3V where it is scaled to a readable range 70 | #define BATT_CYCLES 2 //read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cyclesyou would get ~1 hour intervals 71 | #define BATT_FORMULA(reading) reading * 0.00322 * 1.475 // >>> fine tune this parameter to match your voltage when fully charged 72 | #define BATT_LOW 3.6 //(volts) 73 | #define BATT_READ_LOOPS SEND_LOOPS*10 // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cycles you would get ~1 hour intervals between readings 74 | //***************************************************************************************************************************** 75 | #define LED 9 //pin connected to onboard LED on regular Moteinos 76 | //#define BLINK_EN //uncomment to blink LED on every send 77 | #define SERIAL_EN //comment out if you don't want any serial output 78 | 79 | #ifdef SERIAL_EN 80 | #define SERIAL_BAUD 115200 81 | #define DEBUG(input) {Serial.print(input);} 82 | #define DEBUGln(input) {Serial.println(input);} 83 | #define SERIALFLUSH() {Serial.flush();} 84 | #else 85 | #define DEBUG(input); 86 | #define DEBUGln(input); 87 | #define SERIALFLUSH(); 88 | #endif 89 | //***************************************************************************************************************************** 90 | 91 | //global program variables 92 | SI7021 weatherShield_SI7021; 93 | SFE_BMP180 weatherShield_BMP180; 94 | RFM69 radio; 95 | char Pstr[10]; 96 | char buffer[50]; 97 | SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino) 98 | 99 | void setup(void) 100 | { 101 | #ifdef SERIAL_EN 102 | Serial.begin(SERIAL_BAUD); 103 | #endif 104 | pinMode(LED, OUTPUT); 105 | 106 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 107 | #ifdef IS_RFM69HW 108 | radio.setHighPower(); //uncomment only for RFM69HW! 109 | #endif 110 | radio.encrypt(ENCRYPTKEY); 111 | 112 | sprintf(buffer, "WeatherMote - transmitting at: %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 113 | DEBUGln(buffer); 114 | 115 | //initialize weather shield sensors 116 | weatherShield_SI7021.begin(); 117 | if (weatherShield_BMP180.begin()) 118 | { DEBUGln("BMP180 init success"); } 119 | else { DEBUGln("BMP180 init fail\n"); } 120 | 121 | radio.sendWithRetry(GATEWAYID, "START", 6); 122 | Blink(LED, 100);Blink(LED, 100);Blink(LED, 100); 123 | 124 | SERIALFLUSH(); 125 | readBattery(); 126 | } 127 | 128 | unsigned long doorPulseCount = 0; 129 | char input=0; 130 | double P; 131 | byte sendLoops=0; 132 | byte battReadLoops=0; 133 | float batteryVolts = 5; 134 | char* BATstr="BAT:5.00v"; //longest battery voltage reading message = 9chars 135 | byte sendLen; 136 | 137 | void loop() 138 | { 139 | if (battReadLoops--<=0) //only read battery every BATT_READ_LOOPS cycles 140 | { 141 | readBattery(); 142 | battReadLoops = BATT_READ_LOOPS-1; 143 | } 144 | 145 | if (sendLoops--<=0) //send readings every SEND_LOOPS 146 | { 147 | sendLoops = SEND_LOOPS-1; 148 | P = getPressure(); 149 | P*=0.0295333727; //transform to inHg 150 | dtostrf(P, 3,2, Pstr); 151 | sprintf(buffer, "BAT:%sv F:%d H:%d P:%s", BATstr, weatherShield_SI7021.getFahrenheitHundredths(), weatherShield_SI7021.getHumidityPercent(), Pstr); 152 | 153 | sendLen = strlen(buffer); 154 | radio.sendWithRetry(GATEWAYID, buffer, sendLen, 1); //retry one time 155 | DEBUG(buffer); DEBUG(" (packet length:"); DEBUG(sendLen); DEBUGln(")"); 156 | 157 | #ifdef BLINK_EN 158 | Blink(LED, 5); 159 | #endif 160 | } 161 | 162 | //When this sketch is on a node where you can afford the power to keep the radio awake all the time 163 | // you can make it receive messages and also make it wirelessly programmable 164 | // otherwise this section can be removed 165 | if (radio.receiveDone()) 166 | { 167 | boolean reportStatusRequest=false; 168 | DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); 169 | for (byte i = 0; i < radio.DATALEN; i++) 170 | DEBUG((char)radio.DATA[i]); 171 | 172 | // wireless programming token check - this only works when radio is kept awake to listen for WP tokens 173 | CheckForWirelessHEX(radio, flash, true); 174 | 175 | //first send any ACK to request 176 | DEBUG(" [RX_RSSI:");DEBUG(radio.RSSI);DEBUG("]"); 177 | if (radio.ACKRequested()) 178 | { 179 | radio.sendACK(); 180 | DEBUG(" - ACK sent."); 181 | } 182 | DEBUGln(); 183 | } 184 | 185 | SERIALFLUSH(); 186 | radio.sleep(); //you can comment out this line if you want this node to listen for wireless programming requests 187 | LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF); 188 | DEBUGln("WAKEUP"); 189 | } 190 | 191 | double getPressure() 192 | { 193 | char status; 194 | double T,P,p0,a; 195 | // If you want sea-level-compensated pressure, as used in weather reports, 196 | // you will need to know the altitude at which your measurements are taken. 197 | // We're using a constant called ALTITUDE in this sketch: 198 | 199 | // If you want to measure altitude, and not pressure, you will instead need 200 | // to provide a known baseline pressure. This is shown at the end of the sketch. 201 | // You must first get a temperature measurement to perform a pressure reading. 202 | // Start a temperature measurement: 203 | // If request is successful, the number of ms to wait is returned. 204 | // If request is unsuccessful, 0 is returned. 205 | status = weatherShield_BMP180.startTemperature(); 206 | if (status != 0) 207 | { 208 | // Wait for the measurement to complete: 209 | delay(status); 210 | 211 | // Retrieve the completed temperature measurement: 212 | // Note that the measurement is stored in the variable T. 213 | // Function returns 1 if successful, 0 if failure. 214 | status = weatherShield_BMP180.getTemperature(T); 215 | if (status != 0) 216 | { 217 | // Start a pressure measurement: 218 | // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait). 219 | // If request is successful, the number of ms to wait is returned. 220 | // If request is unsuccessful, 0 is returned. 221 | status = weatherShield_BMP180.startPressure(3); 222 | if (status != 0) 223 | { 224 | // Wait for the measurement to complete: 225 | delay(status); 226 | 227 | // Retrieve the completed pressure measurement: 228 | // Note that the measurement is stored in the variable P. 229 | // Note also that the function requires the previous temperature measurement (T). 230 | // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.) 231 | // Function returns 1 if successful, 0 if failure. 232 | status = weatherShield_BMP180.getPressure(P,T); 233 | if (status != 0) 234 | { 235 | return P; 236 | } 237 | } 238 | } 239 | } 240 | return 0; 241 | } 242 | 243 | void readBattery() 244 | { 245 | unsigned int readings=0; 246 | 247 | //enable battery monitor on WeatherShield (via mosfet controlled by A3) 248 | pinMode(BATT_MONITOR_EN, OUTPUT); 249 | digitalWrite(BATT_MONITOR_EN, LOW); 250 | 251 | for (byte i=0; i<5; i++) //take several samples, and average 252 | readings+=analogRead(BATT_MONITOR); 253 | 254 | //disable battery monitor 255 | pinMode(BATT_MONITOR_EN, INPUT); //highZ mode will allow p-mosfet to be pulled high and disconnect the voltage divider on the weather shield 256 | 257 | batteryVolts = BATT_FORMULA(readings / 5.0); 258 | dtostrf(batteryVolts,3,2, BATstr); //update the BATStr which gets sent every BATT_CYCLES or along with the MOTION message 259 | if (batteryVolts <= BATT_LOW) BATstr = "LOW"; 260 | } 261 | 262 | void Blink(byte PIN, byte DELAY_MS) 263 | { 264 | pinMode(PIN, OUTPUT); 265 | digitalWrite(PIN,HIGH); 266 | delay(DELAY_MS/2); 267 | digitalWrite(PIN,LOW); 268 | delay(DELAY_MS/2); 269 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/MightyBoostControl/MightyBoostControl.ino: -------------------------------------------------------------------------------- 1 | // ************************************************************************************************************* 2 | // MightyBoost control sample sketch 3 | // ************************************************************************************************************* 4 | // Copyright (2015) Felix Rusu of http://lowpowerlab.com 5 | // http://lowpowerlab.com/mightyboost 6 | // MightyBoost is a smart backup PSU controllable by Moteino, and this sketch is a sample control sketch to run 7 | // MightyBoost in this mode. 8 | // Be sure to check back for code updates and patches 9 | // ************************************************************************************************************* 10 | // This sketch will provide control over the essential features of MightyBoost: 11 | // - provide switched 5V power to a sensitive load like RaspberryPi which should not lose power instantly 12 | // - Control the "5V*" output via Moteino+PowerButton (momentary tactile) 13 | // - Monitor input supply and switch to battery backup when external power is lost 14 | // - Monitor battery voltage and issue a shutdown/reboot signal when battery runs low 15 | // This sketch may be extended to include integration with other LowPowerLab automation products 16 | // ************************************************************************************************************* 17 | // License 18 | // ************************************************************************************************************* 19 | // This program is free software; you can redistribute it 20 | // and/or modify it under the terms of the GNU General 21 | // Public License as published by the Free Software 22 | // Foundation; either version 2 of the License, or 23 | // (at your option) any later version. 24 | // 25 | // This program is distributed in the hope that it will 26 | // be useful, but WITHOUT ANY WARRANTY; without even the 27 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 28 | // PARTICULAR PURPOSE. See the GNU General Public 29 | // License for more details. 30 | // 31 | // You should have received a copy of the GNU General 32 | // Public License along with this program; if not, write 33 | // to the Free Software Foundation, Inc., 34 | // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 35 | // 36 | // Licence can be viewed at 37 | // http://www.fsf.org/licenses/gpl.txt 38 | // 39 | // Please maintain this license information along with authorship 40 | // and copyright notices in any redistribution of this code 41 | // ************************************************************************************************************* 42 | #define LED 5 // LED pin, should be analog for fading effect (PWM) 43 | #define BUTTON 3 // Power button pin 44 | #define SIG_SHUTOFF 6 // Signal to Pi to ask for a shutdown 45 | #define SIG_BOOTOK A0 // Signal from Pi that it's OK to cutoff power 46 | // !!NOTE!! Originally this was D7 but it was moved to A0 at least temporarily. 47 | // On MightyBoost R1 you need to connect D7 and A0 with a jumper wire. 48 | // The explanation for this is given here: http://lowpowerlab.com/mightyboost/#source 49 | #define OUTPUT_5V 4 // HIGH on this pin will switch the "5V*" output ON 50 | #define BATTERYSENSE A7 // Sense VBAT_COND signal (when powered externally should read ~3.25v/3.3v (1000-1023), when external power is cutoff it should start reading around 2.85v/3.3v * 1023 ~= 880 (ratio given by 10k+4.7K divider from VBAT_COND = 1.47 multiplier) 51 | // hence the actual input voltage = analogRead(A7) * 0.00322 (3.3v/1024) * 1.47 (10k+4.7k voltage divider ratio) 52 | // when plugged in this should be 4.80v, nothing to worry about 53 | // when on battery power this should decrease from 4.15v (fully charged Lipoly) to 3.3v (discharged Lipoly) 54 | // trigger a shutdown to the target device once voltage is around 3.4v to allow 30sec safe shutdown 55 | #define LOWBATTERYTHRESHOLD 3.5 // a shutdown will be triggered to the target device when battery voltage drops below this (Volts) 56 | 57 | #define RESETHOLDTIME 500 // Button must be hold this many mseconds before a reset is issued (should be much less than SHUTDOWNHOLDTIME) 58 | #define SHUTDOWNHOLDTIME 2000 // Button must be hold this many mseconds before a shutdown sequence is started (should be much less than ForcedShutoffDelay) 59 | #define ShutoffTriggerDelay 6000 // will start checking the SIG_BOOTOK line after this long 60 | #define RecycleTime 50000 // window of time in which SIG_BOOTOK is expected to go HIGH 61 | // should be at least 3000 more than Min 62 | // if nothing happens after this window, if button is 63 | // still pressed, force cutoff power, otherwise switch back to normal ON state 64 | #define RESETPULSETIME 500 // When reset is issued, the SHUTOFF signal is held HIGH this many ms 65 | #define ForcedShutoffDelay 7500 // when SIG_BOOTOK==0 (PI in unknown state): if button is held 66 | // for this long, force shutdown (this should be less than RecycleTime) 67 | #define ShutdownFinalDelay 4500 // after shutdown signal is received, delay for this long 68 | // to allow all PI LEDs to stop activity (pulse LED faster) 69 | 70 | #define PRINTPERIOD 10000 71 | 72 | int lastValidReading = 1; 73 | unsigned long lastValidReadingTime = 0; 74 | unsigned long NOW=0; 75 | int PowerState = 0; 76 | long lastPeriod = -1; 77 | float systemVoltage = 5; 78 | 79 | void setup() { 80 | Serial.begin(115200); 81 | pinMode(BUTTON, INPUT_PULLUP); 82 | pinMode(SIG_BOOTOK, INPUT); 83 | pinMode(SIG_SHUTOFF, OUTPUT); 84 | pinMode(LED, OUTPUT); 85 | pinMode(OUTPUT_5V, OUTPUT); 86 | pinMode(A7, INPUT); 87 | digitalWrite(SIG_SHUTOFF, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! 88 | digitalWrite(OUTPUT_5V, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! 89 | } 90 | 91 | void loop() { 92 | int reading = digitalRead(BUTTON); 93 | NOW = millis(); 94 | digitalWrite(SIG_SHUTOFF, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! 95 | boolean batteryLow = systemVoltage < LOWBATTERYTHRESHOLD; 96 | 97 | if (batteryLow || reading != lastValidReading && NOW - lastValidReadingTime > 200) 98 | { 99 | lastValidReading = reading; 100 | lastValidReadingTime = NOW; 101 | 102 | if (batteryLow || reading == 0) 103 | { 104 | //make sure the button is held down for at least 'RESETHOLDTIME' before taking action (this is to avoid accidental button presses and consequently Pi shutdowns) 105 | NOW = millis(); 106 | while (!batteryLow && (PowerState == 1 && millis()-NOW < RESETHOLDTIME)) { delay(10); if (digitalRead(BUTTON) != 0) return; } 107 | 108 | //RESETHOLDTIME is satisfied, now check if button still held until SHUTDOWNHOLDTIME is satisfied 109 | analogWrite(LED, 128); //dim the LED to show something's going on 110 | while (!batteryLow && (PowerState == 1 && millis()-NOW < SHUTDOWNHOLDTIME)) 111 | { 112 | if (digitalRead(BUTTON) != 0) 113 | { 114 | if (BOOTOK()) //SIG_BOOTOK is HIGH so Pi is running the shutdowncheck.sh script, ready to intercept the RESET PULSE 115 | { 116 | digitalWrite(SIG_SHUTOFF, HIGH); 117 | delay(RESETPULSETIME); 118 | digitalWrite(SIG_SHUTOFF, LOW); 119 | 120 | NOW = millis(); 121 | boolean recycleDetected=false; 122 | while (millis()-NOW < RecycleTime) //blink LED while waiting for BOOTOK to go high 123 | { 124 | //blink 3 times and pause 125 | digitalWrite(LED, LOW); 126 | delay(100); 127 | digitalWrite(LED, HIGH); 128 | delay(100); 129 | digitalWrite(LED, LOW); 130 | delay(100); 131 | digitalWrite(LED, HIGH); 132 | delay(100); 133 | digitalWrite(LED, LOW); 134 | delay(100); 135 | digitalWrite(LED, HIGH); 136 | delay(500); 137 | 138 | if (!BOOTOK()) recycleDetected = true; 139 | else if (BOOTOK() && recycleDetected) 140 | return; 141 | } 142 | return; //reboot pulse sent but it appears a reboot failed; exit all checks 143 | } 144 | else return; //ignore everything else (button was held for RESETHOLDTIME, but SIG_BOOTOK was LOW) 145 | } 146 | } 147 | 148 | //SIG_BOOTOK must be HIGH when Pi is ON. During boot, this will take a while to happen (till it executes the "shutdowncheck" script) 149 | //so I dont want to cutoff power before it had a chance to fully boot up 150 | if (batteryLow || (PowerState == 1 && BOOTOK())) 151 | { 152 | // signal Pi to shutdown 153 | digitalWrite(SIG_SHUTOFF, HIGH); 154 | 155 | //now wait for the Pi to signal back 156 | NOW = millis(); 157 | float in, out; 158 | boolean forceShutdown = true; 159 | 160 | while (millis()-NOW < RecycleTime) 161 | { 162 | if (in > 6.283) in = 0; 163 | in += .00628; 164 | 165 | out = sin(in) * 127.5 + 127.5; 166 | analogWrite(LED,out); 167 | delayMicroseconds(1500); 168 | 169 | //account for force-shutdown action (if button held for ForcedShutoffDelay, then force shutdown regardless) 170 | if (millis()-NOW <= (ForcedShutoffDelay-SHUTDOWNHOLDTIME) && digitalRead(BUTTON) != 0) 171 | forceShutdown = false; 172 | if (millis()-NOW >= (ForcedShutoffDelay-SHUTDOWNHOLDTIME) && forceShutdown) 173 | { 174 | PowerState = 0; 175 | digitalWrite(LED, PowerState); //turn off LED to indicate power is being cutoff 176 | digitalWrite(OUTPUT_5V, PowerState); 177 | break; 178 | } 179 | 180 | if (millis() - NOW > ShutoffTriggerDelay) 181 | { 182 | // Pi signaling OK to turn off 183 | if (!BOOTOK()) 184 | { 185 | PowerState = 0; 186 | digitalWrite(LED, PowerState); //turn off LED to indicate power is being cutoff 187 | NOW = millis(); 188 | while (millis()-NOW < ShutdownFinalDelay) 189 | { 190 | if (in > 6.283) in = 0; 191 | in += .00628; 192 | 193 | out = sin(in) * 127.5 + 127.5; 194 | analogWrite(LED,out); 195 | delayMicroseconds(300); 196 | } 197 | 198 | digitalWrite(OUTPUT_5V, PowerState); 199 | break; 200 | } 201 | } 202 | } 203 | 204 | // last chance: if power still on but button still pressed, force cutoff power 205 | if (PowerState == 1 && digitalRead(BUTTON) == 0) 206 | { 207 | PowerState = 0; 208 | digitalWrite(OUTPUT_5V, PowerState); 209 | } 210 | 211 | digitalWrite(SIG_SHUTOFF, LOW); 212 | } 213 | else if (PowerState == 1 && !BOOTOK()) 214 | { 215 | NOW = millis(); 216 | unsigned long NOW2 = millis(); 217 | int analogstep = 255 / ((ForcedShutoffDelay-SHUTDOWNHOLDTIME)/100); //every 500ms decrease LED intensity 218 | while (digitalRead(BUTTON) == 0) 219 | { 220 | if (millis()-NOW2 > 100) 221 | { 222 | analogWrite(LED, 255 - ((millis()-NOW)/100)*analogstep); 223 | NOW2 = millis(); 224 | } 225 | if (millis()-NOW > ForcedShutoffDelay-SHUTDOWNHOLDTIME) 226 | { 227 | //TODO: add blinking here to signal final shutdown delay 228 | PowerState = 0; 229 | digitalWrite(OUTPUT_5V, PowerState); 230 | break; 231 | } 232 | } 233 | } 234 | else if (PowerState == 0) 235 | { 236 | PowerState = 1; 237 | digitalWrite(OUTPUT_5V, PowerState); //digitalWrite(LED, PowerState); 238 | } 239 | } 240 | 241 | digitalWrite(LED, PowerState); 242 | } 243 | 244 | int currPeriod = millis()/PRINTPERIOD; 245 | if (currPeriod != lastPeriod) 246 | { 247 | lastPeriod=currPeriod; 248 | Serial.print("VIN: "); 249 | systemVoltage = analogRead(BATTERYSENSE) * 0.00322 * 1.47; 250 | Serial.print(systemVoltage); 251 | if (systemVoltage > 4.3) 252 | Serial.println(" (plugged in)"); 253 | else Serial.println(" (running from battery!)"); 254 | } 255 | } 256 | 257 | boolean BOOTOK() { 258 | return analogRead(SIG_BOOTOK) > 800; 259 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/SonarMote/SonarMote_DistanceTracker/SonarMote_DistanceTracker.ino: -------------------------------------------------------------------------------- 1 | // Sample RFM69 sender/node sketch for the SonarMote - Distance tracker 2 | // Can be used for inventory control - ex to measure distance in a multi lane cigarette pack rack 3 | // http://lowpowerlab.com/sonarmote 4 | // Ultrasonic sensor (HC-SR04) connected to D6 (Trig), D7 (Echo), and power enabled through D5 5 | // This sketch sleeps the Moteino and sensor most of the time. It wakes up every few seconds to take 6 | // a distance reading. If it detects an approaching object (car) it increases the sampling rate 7 | // and starts lighting up the LED (from green to yellow to red to blinking red). Once there is no more 8 | // motion the LED is turned off and the cycle is back to a few seconds in between sensor reads. 9 | // Button is connected on D3. Holding the button for a few seconds enters the "red zone adjust" mode (RZA). 10 | // By default the red zone limit is at 25cm (LED turns RED below this and starts blinking faster and faster). 11 | // In RZA, readings are taken for 5 seconds. In this time you have the chance to set a new red zone limit. 12 | // Valid new red zone readings are between the RED__LIMIT_UPPER (default 25cm) and MAX_ADJUST_DISTANCE (cm). 13 | // In RZA mode the BLU Led blinks fast to indicate new red limit distance. It blinks slow if the readings are invalid 14 | // If desired this value could be saved to EEPROM to persist if unit is turned off 15 | // Get the RFM69 at: https://github.com/LowPowerLab/ 16 | // Make sure you adjust the settings in the configuration section below !!! 17 | 18 | // ********************************************************************************** 19 | // Copyright Felix Rusu, LowPowerLab.com 20 | // Library and code by Felix Rusu - felix@lowpowerlab.com 21 | // ********************************************************************************** 22 | // License 23 | // ********************************************************************************** 24 | // This program is free software; you can redistribute it 25 | // and/or modify it under the terms of the GNU General 26 | // Public License as published by the Free Software 27 | // Foundation; either version 3 of the License, or 28 | // (at your option) any later version. 29 | // 30 | // This program is distributed in the hope that it will 31 | // be useful, but WITHOUT ANY WARRANTY; without even the 32 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 33 | // PARTICULAR PURPOSE. See the GNU General Public 34 | // License for more details. 35 | // 36 | // You should have received a copy of the GNU General 37 | // Public License along with this program. 38 | // If not, see . 39 | // 40 | // Licence can be viewed at 41 | // http://www.gnu.org/licenses/gpl-3.0.txt 42 | // 43 | // Please maintain this license information along with authorship 44 | // and copyright notices in any redistribution of this code 45 | // ********************************************************************************** 46 | #include 47 | #include //get it here: https://www.github.com/lowpowerlab/rfm69 48 | #include //get library from: https://github.com/lowpowerlab/lowpower 49 | //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ 50 | 51 | //********************************************************************************************* 52 | //************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************* 53 | //********************************************************************************************* 54 | #define NODEID 22 //unique for each node on same network 55 | #define GATEWAYID 1 //node Id of the receiver we are sending data to 56 | #define NETWORKID 100 //the same on all nodes that talk to each other including this node and the gateway 57 | #define FREQUENCY RF69_915MHZ //others: RF69_433MHZ, RF69_868MHZ (this must match the RFM69 freq you have on your Moteino) 58 | #define IS_RFM69HW //uncomment only for RFM69HW! Remove/comment if you have RFM69W! 59 | #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! 60 | #define SENDLOOPS 80 //default:80 //if no message was sent for this many sleep loops/cycles, then force a send 61 | #define READ_SAMPLES 3 62 | #define HISTERESIS 1.3 //(cm) only send a message when new reading is this many centimeters different 63 | #define DIST_READ_LOOPS 2 //read distance every this many sleeping loops (ie if sleep time is 8s then 2 loops => a read occurs every 16s) 64 | //********************************************************************************************* 65 | #define BUZZER_ENABLE //uncomment this line if you have the BUZZER soldered and want the sketch to make sounds 66 | //#define SERIAL_EN //uncomment if you want serial debugging output 67 | //********************************************************************************************* 68 | #define SLEEP_FASTEST SLEEP_15MS 69 | #define SLEEP_FAST SLEEP_250MS 70 | #define SLEEP_SEC SLEEP_1S 71 | #define SLEEP_LONG SLEEP_2S 72 | #define SLEEP_LONGER SLEEP_4S 73 | #define SLEEP_LONGEST SLEEP_8S 74 | period_t sleepTime = SLEEP_LONGEST; //period_t is an enum type defined in the LowPower library (LowPower.h) 75 | //********************************************************************************************* 76 | #ifdef __AVR_ATmega1284P__ 77 | #define LED 15 // Moteino MEGAs have LEDs on D15 78 | #define FLASH_SS 23 79 | #else 80 | #define LED 9 // Moteinos have LEDs on D9 81 | #define FLASH_SS 8 82 | #endif 83 | #define TRIG 6 // digital pin wired to TRIG pin of ultrasonic sensor 84 | #define ECHO 7 // digital pin wired to ECHO pin of ultrasonic sensor 85 | #define SENSOR_EN 5 // digital pin that enables power to ultrasonic sensor 86 | #define BUZZER 4 // digital pin that is connected to onboard buzzer 87 | #define MAX_DISTANCE 150 // maximum valid distance 88 | #define MIN_DISTANCE 2 // minimum valid distance 89 | #define MAX_ADJUST_DISTANCE (MAX_DISTANCE-GRN_LIMIT_UPPER) //this is the amount by which the RED_LIMIT_UPPER can by increased 90 | 91 | #ifdef SERIAL_EN 92 | #define SERIAL_BAUD 115200 93 | #define DEBUG(input) {Serial.print(input);} 94 | #define DEBUGln(input) {Serial.println(input);} 95 | #define SERIALFLUSH() {Serial.flush();} 96 | #else 97 | #define DEBUG(input); 98 | #define DEBUGln(input); 99 | #define SERIALFLUSH(); 100 | #endif 101 | 102 | #define BATT_MONITOR A7 // Sense VBAT_COND signal (when powered externally should read ~3.25v/3.3v (1000-1023), when external power is cutoff it should start reading around 2.85v/3.3v * 1023 ~= 883 (ratio given by 10k+4.7K divider from VBAT_COND = 1.47 multiplier) 103 | #define BATT_READ_LOOPS SENDLOOPS // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cycles you would get ~1 hour intervals between readings 104 | #define BATT_FORMULA(reading) reading * 0.00322 * 1.475 // >>> fine tune this parameter to match your voltage when fully charged 105 | #define BATT_LOW 3.55 106 | 107 | byte sendLen; 108 | byte sendLoops=0; 109 | byte distReadLoops=0; 110 | byte battReadLoops=0; 111 | float distance=0; 112 | float prevDistance=0; 113 | float batteryVolts = 5; 114 | char buff[50]; //this is just an empty string used as a buffer to place the payload for the radio 115 | char* BATstr="BAT:5.00v"; //longest battery voltage reading message = 9chars 116 | char* DISTstr="99999.99cm"; //longest distance reading message = 5chars 117 | float readDistance(byte samples=1); //take 1 samples by default 118 | RFM69 radio; 119 | 120 | void setup() { 121 | #ifdef SERIAL_EN 122 | Serial.begin(SERIAL_BAUD); // Open serial monitor at 115200 baud to see ping results. 123 | #endif 124 | 125 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 126 | #ifdef IS_RFM69HW 127 | radio.setHighPower(); //uncomment only for RFM69HW! 128 | #endif 129 | radio.encrypt(ENCRYPTKEY); 130 | //sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 131 | sprintf(buff, "\nTransmitting at %d Mhz, id:%d nid:%d gid:%d", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915, NODEID, NETWORKID, GATEWAYID); 132 | DEBUG(buff); 133 | for (byte i=0;i HISTERESIS || diff < -HISTERESIS) || (sendLoops--<=0)) //only send a new message if the distance has changed more than the HISTERESIS or if sendloops has expired 168 | { 169 | if (distance > MAX_DISTANCE || distance < MIN_DISTANCE) 170 | DISTstr = "0"; // zero, out of range 171 | else dtostrf(distance,3,2, DISTstr); 172 | 173 | if (diff > HISTERESIS || diff < -HISTERESIS) 174 | sprintf(buff, "%scm BAT:%s", DISTstr, BATstr); //send both distance and battery readings 175 | else 176 | sprintf(buff, "BAT:%s", BATstr); //distance has not changed significantly so only send last battery reading 177 | sendLen = strlen(buff); 178 | 179 | digitalWrite(LED, HIGH); 180 | DEBUG(buff); 181 | if (radio.sendWithRetry(GATEWAYID, buff, sendLen)) 182 | { 183 | prevDistance = distance; 184 | DEBUG(" - ACK:OK! RSSI:"); 185 | DEBUGln(radio.RSSI); 186 | } 187 | else DEBUGln(" - ACK:NOK..."); 188 | digitalWrite(LED, LOW); 189 | sendLoops = SENDLOOPS-1; //reset send loop counter 190 | } 191 | radio.sleep(); 192 | SERIALFLUSH(); 193 | 194 | LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF); //put microcontroller to sleep to save battery life 195 | } 196 | 197 | float readDistance(byte samples) 198 | { 199 | if (samples == 0) samples = 1; 200 | if (samples > 10) samples = 10; 201 | digitalWrite(SENSOR_EN, HIGH); 202 | //need about 60-75ms after power up before HC-SR04 will be usable, so just sleep in the meantime 203 | LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); 204 | LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); 205 | PING(); 206 | LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); 207 | 208 | unsigned long duration = 0; 209 | for (byte i=0; i 1) LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); 213 | } 214 | digitalWrite(SENSOR_EN, LOW); 215 | return microsecondsToCentimeters(duration / samples); 216 | } 217 | 218 | long PING() 219 | { 220 | digitalWrite(TRIG, LOW); 221 | delayMicroseconds(2); 222 | digitalWrite(TRIG, HIGH); 223 | delayMicroseconds(5); 224 | digitalWrite(TRIG, LOW); 225 | return pulseIn(ECHO, HIGH); 226 | } 227 | 228 | void readBattery() 229 | { 230 | unsigned int readings=0; 231 | for (byte i=0; i<5; i++) //take several samples, and average 232 | readings+=analogRead(BATT_MONITOR); 233 | batteryVolts = BATT_FORMULA(readings / 5.0); 234 | dtostrf(batteryVolts,3,2, BATstr); //update the BATStr which gets sent every BATT_CYCLES or along with the MOTION message 235 | if (batteryVolts <= BATT_LOW) BATstr = "LOW"; 236 | } 237 | 238 | float microsecondsToInches(long microseconds) 239 | { 240 | // According to Parallax's datasheet for the PING))), there are 241 | // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per 242 | // second). This gives the distance travelled by the ping, outbound 243 | // and return, so we divide by 2 to get the distance of the obstacle. 244 | // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf 245 | return microseconds / 74.0 / 2.0f; 246 | } 247 | 248 | float microsecondsToCentimeters(long microseconds) 249 | { 250 | // The speed of sound is 340 m/s or 29 microseconds per centimeter. 251 | // The ping travels out and back, so to find the distance of the 252 | // object we take half of the distance travelled. 253 | return (float)microseconds / 29.0f / 2.0f; 254 | } 255 | 256 | #ifdef BUZZER_ENABLE 257 | void buzzer(byte soundTime, byte repeats, byte repeatsDelay) 258 | { 259 | for (byte i=0;i<=repeats;i++) 260 | { 261 | tone(BUZZER, 4500); //4500hz makes a nice audible sound from a 3.3v Moteino digital pin 262 | delay(soundTime); 263 | noTone(BUZZER); 264 | if (repeats>0) delay(repeatsDelay); 265 | } 266 | } 267 | #endif 268 | 269 | void Blink(byte pin) 270 | { 271 | pinMode(pin, OUTPUT); 272 | digitalWrite(pin, HIGH); 273 | delay(2); 274 | digitalWrite(pin, LOW); 275 | } -------------------------------------------------------------------------------- /Libraries/Arduino/RFM69/examples/LowPowerLab_examples/IOShield/IOShield.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************** 2 | // IOShield sample sketch works with Moteinos equipped with RFM69W/RFM69HW 3 | // Can be adapted to use Moteinos/Arduinos using other RFM69 variants (RFM69CW, RFM69HCW) or even RFM12b 4 | // http://moteino.com 5 | // http://www.LowPowerLab.com/IOShield 6 | // 2015-03-13 (C) Felix Rusu of Low Power Lab LLC 7 | // ********************************************************************************** 8 | // It works with IOShield(s) that have 2 shift registers (74HC595) 9 | // You can daisy chain up to 16 IOShields for a total of 256 outputs/stations/zones 10 | // If you chain more than 2 IOShields be sure to adjust the REGISTERCOUNT setting below in the define section 11 | // Also you must adjust the radio settings: frequency/ HW setting, encryption key etc below in the define section 12 | // It listens for tokens like: 13 | // - 'ON:N' where N={1..16} - turns ON one output dictated by position N 14 | // - 'ALL' - turns ON all outputs 15 | // - 'OFF' turns off all outputs 16 | // - 'PRG A:n ... Z:m' - runs a program in sequence, first token is station/zone/output number, second is the number of seconds to turn it ON for 17 | // WARNING: there is no delay between switching zones, so beware of the frequency you switch the valves on/off 18 | // ********************************************************************************** 19 | // License 20 | // ********************************************************************************** 21 | // This program is free software; you can redistribute it 22 | // and/or modify it under the terms of the GNU General 23 | // Public License as published by the Free Software 24 | // Foundation; either version 3 of the License, or 25 | // (at your option) any later version. 26 | // 27 | // This program is distributed in the hope that it will 28 | // be useful, but WITHOUT ANY WARRANTY; without even the 29 | // implied warranty of MERCHANTABILITY or FITNESS FOR A 30 | // PARTICULAR PURPOSE. See the GNU General Public 31 | // License for more details. 32 | // 33 | // You should have received a copy of the GNU General 34 | // Public License along with this program. 35 | // If not, see . 36 | // 37 | // Licence can be viewed at 38 | // http://www.gnu.org/licenses/gpl-3.0.txt 39 | // 40 | // Please maintain this license information along with authorship 41 | // and copyright notices in any redistribution of this code 42 | // ********************************************************************************** 43 | #include //get it here: http://github.com/lowpowerlab/rfm69 44 | #include //get it here: http://github.com/lowpowerlab/spiflash 45 | #include //get it here: https://github.com/LowPowerLab/WirelessProgramming 46 | #include //comes with Arduino IDE (www.arduino.cc) 47 | //***************************************************************************************************************************** 48 | // ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! 49 | //***************************************************************************************************************************** 50 | #define GATEWAYID 1 51 | #define NODEID 121 52 | #define NETWORKID 250 53 | #define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) 54 | #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! 55 | //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 56 | 57 | #define LATCHPIN 5 58 | #define CLOCKPIN 6 59 | #define DATAPIN 7 60 | #define REGISTERCOUNT 2 //Moteino IOShield has 2 daisy chained registers, if you have more adjust this number 61 | //***************************************************************************************************************************** 62 | #define LED 9 //pin connected to onboard LED 63 | #define SERIAL_BAUD 115200 64 | #define SERIAL_EN //comment out if you don't want any serial output 65 | 66 | #ifdef SERIAL_EN 67 | #define DEBUG(input) Serial.print(input) 68 | #define DEBUGln(input) Serial.println(input) 69 | #else 70 | #define DEBUG(input) 71 | #define DEBUGln(input) 72 | #endif 73 | 74 | RFM69 radio; 75 | ///////////////////////////////////////////////////////////////////////////// 76 | // flash(SPI_CS, MANUFACTURER_ID) 77 | // SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) 78 | // MANUFACTURER_ID - OPTIONAL, 0xEF30 for windbond 4mbit flash (Moteino OEM) 79 | ///////////////////////////////////////////////////////////////////////////// 80 | SPIFlash flash(8, 0xEF30); //regular Moteinos have FLASH MEM on D8, MEGA has it on D4 81 | char buff[30]; //max radio DATA length = 61 82 | String str; 83 | String substr; 84 | 85 | void setup(void) 86 | { 87 | Serial.begin(SERIAL_BAUD); 88 | pinMode(LATCHPIN, OUTPUT); 89 | pinMode(DATAPIN, OUTPUT); 90 | pinMode(CLOCKPIN, OUTPUT); 91 | pinMode(LED, OUTPUT); 92 | 93 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 94 | #ifdef IS_RFM69HW 95 | radio.setHighPower(); //uncomment only for RFM69HW! 96 | #endif 97 | radio.encrypt(ENCRYPTKEY); 98 | 99 | //sprintf(buff, "IOShield : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 100 | //DEBUGln(buff); 101 | DEBUGln(F("START")); 102 | 103 | if (flash.initialize()) 104 | DEBUGln(F("SPI Flash Init OK")); 105 | else 106 | DEBUGln(F("SPI Flash Init FAIL! (is chip present?)")); 107 | 108 | radio.sendWithRetry(GATEWAYID, "START", 5); 109 | zonesOFF(); 110 | Blink(LED, 100); 111 | Blink(LED, 100); 112 | Blink(LED, 100); 113 | DEBUG("Free RAM:");DEBUGln(checkFreeRAM()); 114 | } 115 | 116 | byte LEDSTATE=LOW; 117 | uint32_t LEDCYCLETIMER=0; 118 | byte programZone[32]; //used to store program data 119 | unsigned int programSeconds[32]; //used to store program data 120 | byte programLength=0; //how many zones in this program 121 | byte programPointer=0; //keeps track of active zone (when >=0) 122 | unsigned int seconds=0; 123 | byte whichZone; 124 | int index; 125 | 126 | void loop() 127 | { 128 | if (radio.receiveDone()) 129 | { 130 | DEBUG(F("["));DEBUG(radio.SENDERID);DEBUG(F("] ")); 131 | DEBUG((char *)radio.DATA); 132 | DEBUG(F(" [RX_RSSI:"));DEBUG(radio.RSSI);DEBUGln("]"); 133 | 134 | // wireless programming token check 135 | // DO NOT REMOVE, or this node will not be wirelessly programmable any more! 136 | CheckForWirelessHEX(radio, flash, true); 137 | 138 | whichZone=0; 139 | str = String((char *)radio.DATA); 140 | str.trim(); 141 | if (str.equals(F("OFF"))) zonesOFF(); 142 | else if (str.equals(F("ALL"))) zonesAllON(); //for testing registers only, you should never turn ON all zones in a sprinkler system 143 | else if (str.length() >= 4 && str.startsWith("ON:")) //ON:zoneNumber 144 | { 145 | str = str.substring(3); //trim "ON:" 146 | whichZone = str.toInt(); //extract zone id 147 | if (whichZone > 0) { 148 | stopAndResetProgram();//this command forces any programs to stop and only set the requested zone/output ON 149 | zoneON(whichZone); 150 | } 151 | else DEBUG("Invalid ON"); 152 | } 153 | else if (str.length() >= 7 && str.startsWith("PRG ")) //PRG 1:5 2:5 3:10 4:5 .... zoneN:seconds 154 | { 155 | str = str.substring(4); //trim "PRG " 156 | while (str.length()>=3 && programPointer < 255) 157 | { 158 | whichZone = str.toInt(); //extract zone id 159 | index = str.indexOf(':'); 160 | if (index > 0 && str.length() > index) //make sure there's something after the colon 161 | { 162 | str = str.substring(index+1); //trim "zoneId:" 163 | seconds = str.toInt(); //extract seconds 164 | if (seconds > 0) 165 | { 166 | programZone[programLength] = whichZone; 167 | programSeconds[programLength] = seconds; 168 | programLength++; 169 | 170 | DEBUG("Extracted ZONE"); 171 | DEBUG(whichZone); 172 | DEBUG(":"); 173 | DEBUG(seconds); 174 | DEBUGln("s"); 175 | } 176 | else 177 | { 178 | programLength = 0; 179 | DEBUG("INVALID PRG"); 180 | break; 181 | } 182 | } 183 | else 184 | { 185 | programLength = 0; 186 | DEBUG("INVALID PRG"); 187 | break; 188 | } 189 | 190 | //trim current token and move to next one 191 | index = str.indexOf(' '); 192 | if (index > 0 && str.length() > index+3) //X X:X 193 | { 194 | str = str.substring(index+1); 195 | } 196 | else //EOS? 197 | { 198 | DEBUG( programLength>0 ? "DONE" : "INVALID PRG"); 199 | break; 200 | } 201 | } 202 | DEBUG(F("Found programs:"));DEBUGln(programLength); 203 | } 204 | 205 | //respond to any other ACKs 206 | if (radio.ACKRequested()) radio.sendACK(); 207 | DEBUGln(); 208 | DEBUG("Free RAM:");DEBUGln(checkFreeRAM()); 209 | } 210 | 211 | handleProgram(); 212 | 213 | if (millis() - LEDCYCLETIMER > 2000) //flip onboard LED state every so often to indicate activity 214 | { 215 | LEDCYCLETIMER = millis(); 216 | LEDSTATE = !LEDSTATE; 217 | digitalWrite(LED, LEDSTATE); 218 | } 219 | } 220 | 221 | unsigned long programZoneStart=0; 222 | void handleProgram() 223 | { 224 | if (programLength > 0) 225 | { 226 | if (programZoneStart == 0) 227 | { 228 | programZoneStart = millis(); //mark start time of a zone 229 | zoneON(programZone[programPointer]); 230 | DEBUG("Running zone "); 231 | DEBUG(programZone[programPointer]); 232 | DEBUG(" for "); 233 | DEBUG((((unsigned long)programSeconds[programPointer])*1000)); 234 | DEBUGln("ms..."); 235 | } 236 | else if (millis() - programZoneStart > (((unsigned long)programSeconds[programPointer])*1000)) //check if zone time expired, jump to next zone 237 | { 238 | programZoneStart=0; 239 | programLength--; 240 | if (programLength == 0) //finished 241 | zonesOFF(); 242 | else programPointer++; //skip to next zone in program 243 | } 244 | } 245 | } 246 | 247 | void stopAndResetProgram() 248 | { 249 | programLength=0; 250 | programPointer=0; 251 | programZoneStart=0; 252 | } 253 | 254 | //turns ON one zone only, all others off 255 | void zoneON(byte which) 256 | { 257 | //stopAndResetProgram(); //stop any running programs 258 | if (radio.ACKRequested()) radio.sendACK(); 259 | registersWriteBit(which-1); 260 | sprintf(buff, "ZONE:%d", which); 261 | if (radio.sendWithRetry(GATEWAYID, buff, strlen(buff))) 262 | {DEBUGln(F("..OK"));} 263 | else {DEBUGln(F("..NOK"));} 264 | } 265 | 266 | //all zones OFF 267 | void zonesOFF() 268 | { 269 | stopAndResetProgram(); //stop any running programs 270 | if (radio.ACKRequested()) radio.sendACK(); 271 | registersClear(); 272 | if (radio.sendWithRetry(GATEWAYID, "ZONES:OFF", 9)) 273 | {DEBUGln(F("..OK"));} 274 | else {DEBUGln(F("..NOK"));} 275 | } 276 | 277 | //all zones ON - for testing purposes only 278 | void zonesAllON() 279 | { 280 | stopAndResetProgram(); //stop any running programs 281 | registersAllOn(); 282 | } 283 | 284 | void registersClear() { 285 | digitalWrite(LATCHPIN, LOW); 286 | for(byte i=0;i