├── todo ├── include ├── ntp.h ├── reconn.h ├── mqttpub.h ├── RFM69functions.h ├── settings.example.h └── RFM69registers.h ├── SparnasMqtt.png ├── SparsnasHass.png ├── .gitignore ├── refrence_doc ├── RFM69HCW_NodeMCU.png └── RFM69HC_D1mini.png ├── src ├── mqttpub.cpp ├── ntp.cpp ├── reconn.cpp ├── EspSparsnasGateway.cpp └── RFM69functions.cpp ├── test └── README ├── platformio.ini ├── LICENSE ├── lib └── README ├── .travis.yml └── README.md /todo: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/ntp.h: -------------------------------------------------------------------------------- 1 | void setup_NTP(); 2 | -------------------------------------------------------------------------------- /include/reconn.h: -------------------------------------------------------------------------------- 1 | void reconnect(); 2 | -------------------------------------------------------------------------------- /include/mqttpub.h: -------------------------------------------------------------------------------- 1 | void mqttpub(String topic, String subject, String mess, int size); 2 | -------------------------------------------------------------------------------- /SparnasMqtt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bphermansson/EspSparsnasGateway/HEAD/SparnasMqtt.png -------------------------------------------------------------------------------- /SparsnasHass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bphermansson/EspSparsnasGateway/HEAD/SparsnasHass.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .pioenvs/ 3 | .piolibdeps/ 4 | .clang* 5 | .gcc* 6 | .pio* 7 | include/settings.h 8 | 9 | -------------------------------------------------------------------------------- /refrence_doc/RFM69HCW_NodeMCU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bphermansson/EspSparsnasGateway/HEAD/refrence_doc/RFM69HCW_NodeMCU.png -------------------------------------------------------------------------------- /refrence_doc/RFM69HC_D1mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bphermansson/EspSparsnasGateway/HEAD/refrence_doc/RFM69HC_D1mini.png -------------------------------------------------------------------------------- /include/RFM69functions.h: -------------------------------------------------------------------------------- 1 | uint16_t readRSSI(); 2 | uint16_t crc16(volatile uint8_t *data, size_t n); 3 | bool receiveDone(); 4 | void writeReg(uint8_t addr, uint8_t value); 5 | uint8_t readReg(uint8_t addr); 6 | void setMode(uint8_t newMode); 7 | uint32_t getFrequency(); 8 | bool initialize(uint32_t frequency); 9 | -------------------------------------------------------------------------------- /src/mqttpub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern PubSubClient mClient; 6 | 7 | void mqttpub(String topic, String subject, String mess, int size) { 8 | const size_t capacity = JSON_OBJECT_SIZE(size); 9 | DynamicJsonDocument status(capacity); 10 | String mqttMess; 11 | status[subject] = mess; 12 | serializeJson(status, mqttMess); 13 | mClient.publish((char*) topic.c_str(),(char*) mqttMess.c_str()); 14 | } -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PIO Unit Testing and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PIO Unit Testing: 11 | - https://docs.platformio.org/page/plus/unit-testing.html 12 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:d1_mini_lite] 12 | platform = espressif8266@^2.6 13 | board = d1_mini_lite 14 | upload_port = /dev/ttyUSB0 15 | framework = arduino 16 | lib_deps = 17 | PubSubClient@^2.8.0 18 | ArduinoJson@>=6.11.3 19 | Ticker @ ^1.0 20 | #upload_protocol = espota 21 | #upload_port = 192.168.1.165 22 | ; Serial Monitor options 23 | monitor_speed = 115200 24 | build_flags = -DMQTT_MAX_PACKET_SIZE=256 25 | -------------------------------------------------------------------------------- /src/ntp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // time() ctime() 3 | #include // struct timeval 4 | #include // settimeofday_cb() 5 | #include "settings.h" 6 | 7 | #define TZ 1 // (utc+) TZ in hours 8 | #define DST_MN 60 // use 60mn for summer time in some countries 9 | #define TZ_MN ((TZ)*60) 10 | #define TZ_SEC ((TZ)*3600) 11 | #define DST_SEC ((DST_MN)*60) 12 | #define TIME_ZONE LOCALTZ 13 | #define NTP_SERVER NTPSERVERNAME 14 | 15 | timeval cbtime; // time set in callback 16 | bool cbtime_set = false; 17 | timeval tv; 18 | timespec tp; 19 | time_t now; 20 | int cnt; 21 | 22 | void timeSet_cb(void) 23 | { 24 | gettimeofday(&cbtime, NULL); 25 | cbtime_set = true; 26 | cnt++; 27 | } 28 | 29 | void setup_NTP() 30 | { 31 | cbtime_set = false; 32 | settimeofday_cb(timeSet_cb); 33 | configTime(0, 0, NTPSERVERNAME); 34 | 35 | timezone tz = {0, 0}; 36 | settimeofday(&tv, &tz); 37 | setenv("TZ", TIME_ZONE, 1); 38 | tzset(); 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Patrik Hermansson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /include/settings.example.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SETTINGS_H 3 | #define SETTINGS_H 4 | /* 5 | Uncomment the next line to enable debug mode. 6 | This gives much more info about what's happening 7 | to the serial port. 8 | */ 9 | //#define DEBUG 1 10 | 11 | // Set this to the value of your energy meter 12 | #define PULSES_PER_KWH 1000 13 | // The code from the Sparnas tranmitter. Under the battery lid there's a sticker with digits like '400 643 654'. 14 | // Set SENSOR_ID to the last six digits, ie '643654'. 15 | #define SENSOR_ID 643654 16 | #define FREQUENCY 867987500 17 | 18 | // Settings for the Mqtt broker: 19 | #define MQTT_USERNAME "YOUR_MQTT_USERNAME" 20 | #define MQTT_PASSWORD "YOUR_MQTT_PASSWORD" 21 | #define MQTT_SERVER "YOUR_MQTT_SERVER_IP" 22 | #define MQTT_PORT 1883 23 | #define MQTT_STATUS_TOPIC "EspSparsnasGateway/valuesV2" 24 | #define MQTT_DEBUG_TOPIC "EspSparsnasGateway/debugV2" 25 | #define DISCOVERY_PREFIX "homeassistant" 26 | 27 | // WiFi settings 28 | #define WIFISSID "YOUR_WIFI_SSID" 29 | #define WIFIPASSWORD "YOUR_WIFI_PASSWORD" 30 | 31 | #define APPNAME "EspSparsnasGateway" 32 | #define NTPSERVERNAME "pool.ntp.org" 33 | #define LOCALTZ "CET-1CEST,M3.5.0,M10.5.0/3" // Stockholm 34 | #define SERIALSPEED 115200 35 | 36 | #define LED_RED D0 37 | #define LED_GREEN D3 38 | #define LED_BLUE D2 39 | 40 | #define LED_RED_BRIGHTNESS 150 // 0-255 41 | #define LED_GREEN_BRIGHTNESS 25 // 0-255 42 | #define LED_BLUE_BRIGHTNESS 255 // 0-255 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < https://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < https://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < https://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choose one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # - platformio update 39 | # 40 | # script: 41 | # - platformio run 42 | 43 | 44 | # 45 | # Template #2: The project is intended to be used as a library with examples. 46 | # 47 | 48 | # language: python 49 | # python: 50 | # - "2.7" 51 | # 52 | # sudo: false 53 | # cache: 54 | # directories: 55 | # - "~/.platformio" 56 | # 57 | # env: 58 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 59 | # - PLATFORMIO_CI_SRC=examples/file.ino 60 | # - PLATFORMIO_CI_SRC=path/to/test/directory 61 | # 62 | # install: 63 | # - pip install -U platformio 64 | # - platformio update 65 | # 66 | # script: 67 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 68 | -------------------------------------------------------------------------------- /src/reconn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "settings.h" 5 | 6 | extern PubSubClient mClient; 7 | const String sensor_id = String(SENSOR_ID); 8 | const String availability_topic = APPNAME "/" + sensor_id + "/availability"; 9 | const String state_topic = APPNAME "/" + sensor_id + "/state"; 10 | const String discovery_topic = DISCOVERY_PREFIX "/sensor/" APPNAME "_" + sensor_id; 11 | 12 | bool send_discovery_message(const char* measurement, const char* value_template) { 13 | DynamicJsonDocument device(JSON_OBJECT_SIZE(12)); 14 | DynamicJsonDocument config(JSON_OBJECT_SIZE(30)); 15 | 16 | device["sw_version"] = __TIME__ " " __DATE__; 17 | device["name"] = String(APPNAME " ") + sensor_id; 18 | device["identifiers"] = String(APPNAME "") + sensor_id; 19 | device["model"] = APPNAME; 20 | device["manufacturer"] = "IKEA"; 21 | 22 | config["device"] = device; 23 | config["device_class"] = "power"; 24 | config["unit_of_measurement"] = measurement; 25 | config["name"] = String("ESP Sparsnäs ") + measurement; 26 | config["unique_id"] = (APPNAME "_") + sensor_id + "_" + measurement; 27 | config["state_topic"] = state_topic; 28 | config["json_attributes_topic"] = state_topic; 29 | config["availability_topic"] = availability_topic.c_str(); 30 | config["value_template"] = value_template; 31 | 32 | String ret; 33 | serializeJson(config, ret); 34 | 35 | mClient.beginPublish( 36 | (String(discovery_topic) + "/" + measurement + "/config").c_str(), 37 | ret.length(), 38 | true 39 | ); 40 | for (uint i=0; i 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define ARDUINOJSON_USE_LONG_LONG 1 // https://arduinojson.org/v6/api/config/use_long_long/ 14 | #include 15 | #include 16 | /*------------------------------*/ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | WiFiClient wClient; 25 | PubSubClient mClient(wClient); 26 | 27 | static const char* mqtt_status_topic = MQTT_STATUS_TOPIC; 28 | static const char* mqtt_debug_topic = MQTT_DEBUG_TOPIC; 29 | 30 | // Make it possible to read Vcc from code 31 | ADC_MODE(ADC_VCC); 32 | 33 | Ticker blinkerRed; 34 | Ticker blinkerGreen; 35 | 36 | unsigned long lastRecievedData = millis(); 37 | String mqttMess; 38 | String freq, sendid; 39 | uint32_t ifreq; 40 | uint32_t isendid; 41 | const char compile_date[] = __DATE__ " " __TIME__; 42 | 43 | void changeStateLED_RED(); 44 | void changeStateLED_GREEN(); 45 | 46 | /* ----------------------------------------------------*/ 47 | 48 | void setup() { 49 | ifreq = FREQUENCY; 50 | isendid = SENSOR_ID; 51 | Serial.begin(SERIALSPEED); 52 | Serial.println("Welcome to " + String(APPNAME)); 53 | 54 | pinMode (LED_RED, OUTPUT); 55 | pinMode (LED_GREEN, OUTPUT); 56 | pinMode (LED_BLUE, OUTPUT); 57 | 58 | // Test leds 59 | analogWrite(LED_RED, LED_RED_BRIGHTNESS); 60 | delay(500); 61 | analogWrite(LED_GREEN, LED_GREEN_BRIGHTNESS); 62 | delay(500); 63 | analogWrite(LED_BLUE, LED_BLUE_BRIGHTNESS); 64 | delay(1500); 65 | 66 | digitalWrite(LED_RED, LOW); 67 | digitalWrite(LED_GREEN, LOW); 68 | digitalWrite(LED_BLUE, HIGH); 69 | delay(500); 70 | 71 | blinkerGreen.attach(0.5, changeStateLED_GREEN); 72 | 73 | #ifdef SHOW_BAD_PACKETS 74 | Serial.println(F("SHOW_BAD_PACKETS on")); 75 | #else 76 | Serial.println(F("SHOW_BAD_PACKETS off")); 77 | #endif 78 | 79 | #ifdef DEBUG 80 | Serial.println(F("Debug on")); 81 | Serial.print (F("Vcc=")); 82 | Serial.println(ESP.getVcc()); 83 | Serial.println (F("Set up WiFi...")); 84 | #else 85 | Serial.println(F("Debug off")); 86 | #endif 87 | 88 | WiFi.mode(WIFI_STA); 89 | WiFi.begin(WIFISSID, WIFIPASSWORD); 90 | while (WiFi.waitForConnectResult() != WL_CONNECTED) { 91 | 92 | Serial.println(F("Connecting to " WIFISSID "...")); 93 | Serial.println(F("Connection failed, check your settings!")); 94 | Serial.println(F("Rebooting...")); 95 | 96 | blinkerRed.attach(0.5, changeStateLED_RED); 97 | delay(5000); 98 | ESP.restart(); 99 | } 100 | 101 | WiFi.hostname(APPNAME); 102 | 103 | // Setup Mqtt connection 104 | mClient.setServer(MQTT_SERVER, MQTT_PORT); 105 | reconnect(); 106 | 107 | mqttMess = "Welcome to EspSparsnasGateway, compiled at " + String(compile_date); 108 | mqttMess = mqttMess + ".\nMqtt topics: " + mqtt_status_topic + ", " + mqtt_debug_topic + "\nIP: " + WiFi.localIP()[0] + "." + WiFi.localIP()[1] + "." + WiFi.localIP()[2] + "." + WiFi.localIP()[3]; 109 | #ifdef DEBUG 110 | Serial.println(mqttMess); 111 | Serial.println(mqtt_status_topic); 112 | #endif 113 | mqttpub(String(mqtt_debug_topic), "Device", mqttMess, mqttMess.length()); 114 | 115 | // Hostname defaults to esp8266-[ChipID], change this 116 | ArduinoOTA.setHostname(APPNAME); 117 | 118 | ArduinoOTA.onStart([]() { 119 | Serial.println("Start"); 120 | }); 121 | ArduinoOTA.onEnd([]() { 122 | Serial.println("\nEnd"); 123 | }); 124 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 125 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 126 | }); 127 | ArduinoOTA.onError([](ota_error_t error) { 128 | Serial.printf("Error[%u]: ", error); 129 | if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); 130 | else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); 131 | else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); 132 | else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); 133 | else if (error == OTA_END_ERROR) Serial.println("End Failed"); 134 | }); 135 | ArduinoOTA.begin(); 136 | 137 | setup_NTP(); 138 | 139 | mqttMess = "Over The Air programming enabled, port: " + String(APPNAME); 140 | #ifdef DEBUG 141 | Serial.println(mqttMess); 142 | #endif 143 | mqttpub(String(mqtt_debug_topic), "Device", mqttMess, mqttMess.length()); 144 | 145 | mqttMess = "Settings: \nSenderid: " + String(isendid) + "\nFrequency: " + String(ifreq); 146 | #ifdef DEBUG 147 | Serial.println(mqttMess); 148 | #endif 149 | mqttpub(String(mqtt_debug_topic), "Device", mqttMess, mqttMess.length()); 150 | 151 | if (!initialize(ifreq)) { 152 | mqttMess = "Unable to initialize the radio. Exiting."; 153 | blinkerRed.attach(0.3, changeStateLED_RED); 154 | #ifdef DEBUG 155 | Serial.println(mqttMess); 156 | #endif 157 | mqttpub(String(mqtt_debug_topic), "Radio", mqttMess, mqttMess.length()); 158 | while (1) { 159 | yield(); 160 | } 161 | } 162 | else { 163 | mqttMess = "Radio initialized.\nListening on " + String(getFrequency()) + "hz. Done in setup."; 164 | #ifdef DEBUG 165 | Serial.println(mqttMess); 166 | #endif 167 | mqttpub(String(mqtt_debug_topic), "Radio", mqttMess, mqttMess.length()); 168 | } 169 | 170 | // All ok 171 | blinkerGreen.detach(); 172 | analogWrite(LED_GREEN, LED_GREEN_BRIGHTNESS); 173 | } 174 | 175 | void loop() { 176 | ArduinoOTA.handle(); 177 | if (!mClient.connected()) { 178 | reconnect(); 179 | } 180 | mClient.loop(); 181 | //delay(10); 182 | // Note! This routine is necessary, don't remove it! 183 | if (receiveDone()) { 184 | } 185 | } 186 | void changeStateLED_RED() 187 | { 188 | digitalWrite(LED_RED, !(digitalRead(LED_RED))); //Invert Current State of LED 189 | } 190 | void changeStateLED_GREEN() 191 | { 192 | digitalWrite(LED_GREEN, !(digitalRead(LED_GREEN))); //Invert Current State of LED 193 | } 194 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EspSparsnasGateway 2 | 3 | This is a MQTT Gateway for Ikeas energy monitor Sparsnas. The monitor 4 | sends encoded data by radio to a control panel. This device collects the data 5 | and sends it to MQTT-enabled receivers in json-format. 6 | 7 | The data is also printed to the serial port. If the reception is bad, the received data can be bad. 8 | This gives a CRC-error, the data is in this case not sent via MQTT but printed via the serial port. 9 | 10 | The data sent via MQTT is in json format and looks like this: 11 | 12 | ```json 13 | { 14 | "error": "", 15 | "seq": 28767, 16 | "timestamp": 1592040611, 17 | "watt": 1920, 18 | "total": 15016, 19 | "battery": 100, 20 | "rssi": -123, 21 | "power": 80, 22 | "pulse": 150160049 23 | } 24 | ``` 25 | 26 | The device uses two Mqtt topics to publish, `EspSparsnasGateway//valuesV2` and `EspSparsnasGateway/debugV2'. The latter can be ignored if you not are interrested in bad packets, just listen on topic 'EspSparsnasGateway/valuesV2'. 27 | 28 | ## Dependencies 29 | 30 | This requires the following packages: 31 | 32 | - ArduinoJson (5.x) 33 | - PubSubClient (2.7) 34 | - SPIFlash_LowPowerLabs (101.1) 35 | - RFM69_LowPowerLabs (1.2.0) 36 | 37 | Packages can be installed using the Arduino libs, see the [docs](https://www.arduino.cc/en/guide/libraries) for more info 38 | 39 | ## Using 40 | Load the project files in Atom/VS Code with PlatformIO. Then copy the file `include/settings.example.h` to `include/settings.h`. Adjust the values in `settings.h` to fit your environment and save it. Upload to your hardware and enjoy :) 41 | 42 | ## Hardware 43 | The hardware used is a ESP8266-based wifi-enabled MCU. You can use different devices like a Wemos D1mini or a NodeMCU, but take care of the GPIO labels that can differ. The receiver is a RFM69HCW radio transciever (the RFMCW also works but note that it have a different [pinout](https://github.com/bphermansson/EspSparsnasGateway/raw/master/refrence_doc/RFM69HC_D1mini.png)). I use a 868MHz device, but a 900MHz should work as well. To this a simple antenna is connected, I use a straight wire, 86 millimeters long connected to the RFM's Ant-connection. The wire shall be vertical, standing up. You can also add a similar wire to the GND-connection next to the antenna connection, pointing down, opposite to the first wire. 44 | 45 | The connection for the RFM69 is hardcoded. This is standard SPI connections set in the SPI-library that can't be changed. See https://learn.sparkfun.com/tutorials/esp8266-thing-hookup-guide/using-the-arduino-addon. 46 | 47 | The schematic shows a NodeMCU, but you can use another ESP8266-based device if you want (except the Esp-01). Use these pin mappings: 48 | 49 | | RFM69 | RFM69**H**CW | RFM69**CW** | D1mini/
NodeMCU | ESP8266/
ESP12/
ESP32 | 50 | |--------|:--:|:-:|:--:|:------:| 51 | | DIO0 | 14 | 9 | D1 | Gpio05 | 52 | | SCK | 4 | 6 | D5 | Gpio14 | 53 | | MISO | 2 | 8 | D6 | Gpio12 | 54 | | MOSI | 3 | 5 | D7 | Gpio13 | 55 | | EN/NSS | 5 | 7 | D8 | Gpio15 | 56 | | ANT | 9| 1 | - | - | 57 | 58 | ![Wiring diagram](https://github.com/bphermansson/EspSparsnasGateway/raw/master/refrence_doc/RFM69HCW_NodeMCU.png) 59 | 60 | Note! Adafruit modules requires a connection from RST to GND! (Ref: https://www.mysensors.org/build/connect_radio#wiring-the-rfm69-radio). 61 | 62 | ### LEDs 63 | 64 | The code also supports three optional LEDs indicating status connected as follows: 65 | 66 | | LED | D1mini/
NodeMCU | Usage | 67 | |:-|:-:|:-| 68 | | RED | D0 | Error (typically CRC errors) | 69 | | GREEN | D3 | Used during boot | 70 | | BLUE | D2 | Indicates successfully recieved package| 71 | 72 | It is possible to use the onboard (blue) LED on the D1mini by changing `#define LED_BLUE D2` to `#define LED_BLUE D4`. 73 | 74 | ### Parts 75 | You can build your own device using these parts: (To see the language specific page make sure to select the language at the top of the page or it will give a 404.) 76 | 77 | U1 - NodeMCU V3 78 | https://www.lawicel-shop.se/microkontroller/esp8266-esp32/nodemcu-v3-with-esp-12e-ch340 79 | 80 | Part1 - RFM69HCW 81 | https://www.lawicel-shop.se/rfm69hcw-transceiver-bob 82 | 83 | #### Optional (but highly recommended) 84 | C2 - Capacitor 100nF 85 | se: https://www.lawicel-shop.se/elektronik/komponenter/kondensatorer/capacitor-100nf-10-pack 86 | en: https://www.lawicel-shop.se/components/komponenter/capacitors/capacitor-100nf-10-pack 87 | 88 | C1 - Capacitor 1000uF 89 | se: https://www.lawicel-shop.se/components/komponenter/capacitors/capacitor-1000uf-50v 90 | en: https://www.lawicel-shop.se/elektronik/komponenter/kondensatorer/capacitor-1000uf-50v 91 | 92 | Also add two capacitors, 330-470uF and 100nF, to Vin in and Gnd for stability. 93 | 94 | ### Hardware hacks to ensure good RF performance. 95 | Keep the wires between the RFM69 module and the NodeMCU as short as possible and DO NOT make them 8 cm long hence that calculates into 1/4 wavelength of 868 MHz. 96 | You will experience interference and very poor performance if the above is not applied and followed. 97 | 98 | If you want to learn more about the RFM69 and get some tips & tricks, look at https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide. 99 | 100 | ### If it doesn't work 101 | As usual, check your connections one more time. If possible, solder the connections. Also make sure to use a good power supply, both the ESP and the RFM69 want's that. 102 | 103 | ### Connect to computer 104 | You can use the device with a simple USB power supply and get data via MQTT. The device also puts out more information via the serial port. You can connect it to a computer and look at the messages with a serial monitor, for example the one in the Arduino IDE or Minicom. The baudrate is 115200. 105 | 106 | ### Enable debug 107 | Further more information is given by the device if debug is activated: 108 | 109 | ```c++ 110 | #define DEBUG 1 111 | ``` 112 | 113 | ### Change the channel filter width 114 | With some RFM's a software adjustment can be tested if the code doesn't work. Line 213 in RFM69functions.cpp looks like this: 115 | 116 | ```c++ 117 | /* 0x19 */ {REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_4}, // p26 in datasheet, filters out noise 118 | ``` 119 | 120 | You can try to change this to: 121 | 122 | ```c++ 123 | /* 0x19 */ {REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_3}, // p26 in datasheet, filters out noise 124 | ``` 125 | 126 | This makes the channel filter wider, 62.5khz instead of 31.3khz. 127 | 128 | ## Home Assistant integration 129 | Sensors for power (Watt) and energy (kWh) will be created automatically if Home Assistant is configured to support [discovery](https://www.home-assistant.io/docs/mqtt/discovery/#discovery). 130 | The MQTT data can however be used anywhere, here's an example for the Home Automation software Home Assistant. 131 | In Home Assistant the sensors can look like this: 132 | 133 | ### Home assistant version 2022.9 and newer 134 | configuration.yaml 135 | ```yaml 136 | mqtt: !include mqtt.yaml 137 | ``` 138 | mqtt.yaml 139 | ```yaml 140 | sensor: 141 | - state_topic: "EspSparsnasGateway/valuesV2" 142 | name: "House power usage" 143 | unit_of_measurement: "W" 144 | value_template: "{{ float(value_json.watt) | round(0) }}" 145 | icon: mdi:flash-circle 146 | state_class: measurement 147 | device_class: power 148 | 149 | - state_topic: "EspSparsnasGateway/valuesV2" 150 | name: "House energy usage" 151 | unit_of_measurement: "kWh" 152 | value_template: "{{ float(value_json.total) | round(0) }}" 153 | icon: mdi:flash-circle 154 | state_class: measurement 155 | device_class: energy 156 | 157 | - state_topic: "EspSparsnasGateway/valuesV2" 158 | name: "House energy meter batt" 159 | unit_of_measurement: "%" 160 | value_template: "{{ float(value_json.battery) }}" 161 | icon: mdi:battery-outline 162 | 163 | - state_topic: "EspSparsnasGateway/valuesV2" 164 | name: "House energy meter power" 165 | value_template: "{{ float(value_json.power) }}" 166 | icon: mdi:power-socket-eu 167 | state_class: measurement 168 | 169 | - state_topic: "EspSparsnasGateway/valuesV2" 170 | name: "House energy meter signal" 171 | unit_of_measurement: "dBm" 172 | value_template: "{{ float(value_json.rssi) }}" 173 | icon: mdi:antenna 174 | 175 | ``` 176 | 177 | ### Home assistant version 2022.9 and older 178 | Since 2022.9 the platform mqtt yaml configuration is depricated and a notification warning is shown since [2022.6](https://www.home-assistant.io/blog/2022/06/01/release-20226/) 179 | If you are running a home assistant version before 2022.9 you can use this 180 | ```yaml 181 | - platform: mqtt 182 | state_topic: "EspSparsnasGateway/+/state" 183 | name: "House power usage" 184 | unit_of_measurement: "W" 185 | value_template: '{{ float(value_json.watt) | round(0) }}' 186 | 187 | - platform: mqtt 188 | state_topic: "EspSparsnasGateway/+/state" 189 | name: "House energy usage" 190 | unit_of_measurement: "kWh" 191 | value_template: '{{ float(value_json.total) | round(0) }}' 192 | 193 | - platform: mqtt 194 | state_topic: "EspSparsnasGateway/+/state" 195 | name: "House energy meter batt" 196 | unit_of_measurement: "%" 197 | value_template: '{{ float(value_json.battery) }}' 198 | ``` 199 | ### Sensor result 200 | The above results in these sensors: 201 | 202 | ```yaml 203 | - sensor.house_energy_meter_batt 204 | - sensor.house_energy_usage 205 | - sensor.house_power_usage 206 | ``` 207 | 208 | The result can be seen in SparsnasHass.png. 209 | 210 | ![alt text](https://github.com/bphermansson/EspSparsnasGateway/blob/master/SparsnasHass.png "Sparsnas in Home Assistant") 211 | 212 | ## Protocol analysis 213 | For much more information about the hardware, the protocol and how to analyse the transmission, see 214 | Kodarn's Github, https://github.com/kodarn/Sparsnas. 215 | 216 | ## Thanks! 217 | The code is based on Sommarlovs version of Ludvig Strigeus code: 218 | http://elektronikforumet.com/forum/viewtopic.php?f=2&t=85006&start=255 219 | Strigeus original code for use with a DVB-T Usb dongle: 220 | https://github.com/strigeus/sparsnas_decoder 221 | -------------------------------------------------------------------------------- /src/RFM69functions.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define ARDUINOJSON_USE_LONG_LONG 1 // https://arduinojson.org/v6/api/config/use_long_long/ 8 | #include 9 | #include 10 | 11 | #define RF69_MODE_SLEEP 0 // XTAL OFF 12 | #define RF69_MODE_STANDBY 1 // XTAL ON 13 | #define RF69_MODE_SYNTH 2 // PLL ON 14 | #define RF69_MODE_RX 3 // RX MODE 15 | #define RF69_MODE_TX 4 // TX MODE 16 | #define _interruptNum 5 17 | 18 | static volatile uint8_t DATA[21]; 19 | static volatile uint8_t TEMPDATA[21]; 20 | static volatile uint8_t DATALEN; 21 | 22 | static const char* mqtt_status_topic = MQTT_STATUS_TOPIC; 23 | static const char* mqtt_debug_topic = MQTT_DEBUG_TOPIC; 24 | 25 | static String mqttMess; 26 | const String sensor_id = String(SENSOR_ID); 27 | const String state_topic = APPNAME "/" + sensor_id + "/state"; 28 | 29 | extern PubSubClient mClient; 30 | 31 | //#define _interruptNum 5 32 | static volatile bool inInterrupt = false; // Fake Mutex 33 | 34 | uint32_t FXOSC = 32000000; 35 | uint32_t TwoPowerToNinteen = 524288; // 2^19 36 | float RF69_FSTEP = (1.0 * FXOSC) / TwoPowerToNinteen; // p13 in datasheet 37 | uint16_t BITRATE = FXOSC / 40000; // 40kBps 38 | uint16_t FREQUENCYDEVIATION = 10000 / RF69_FSTEP; // 10kHz 39 | uint16_t SYNCVALUE = 0xd201; 40 | uint8_t RSSITHRESHOLD = 0xE4; // must be set to dBm = (-Sensitivity / 2), default is 0xE4 = 228 so -114dBm 41 | uint8_t PAYLOADLENGTH = 20; 42 | 43 | static volatile uint8_t _mode; 44 | uint8_t enc_key[5]; 45 | 46 | extern timeval tv; 47 | extern timespec tp; 48 | extern time_t now; 49 | extern "C" int clock_gettime(clockid_t unused, struct timespec *tp); 50 | 51 | extern void publish_mqtt(String, String); 52 | 53 | int16_t readRSSI(); 54 | 55 | void ICACHE_RAM_ATTR interruptHandler(); 56 | 57 | // select the RFM69 transceiver (save SPI settings, set CS low) 58 | void select() { 59 | // noInterrupts(); 60 | digitalWrite(SS, LOW); 61 | } 62 | 63 | // unselect the RFM69 transceiver (set CS high, restore SPI settings) 64 | void unselect() { 65 | digitalWrite(SS, HIGH); 66 | // interrupts(); 67 | } 68 | 69 | uint8_t readReg(uint8_t addr) { 70 | select(); 71 | SPI.transfer(addr & 0x7F); 72 | uint8_t regval = SPI.transfer(0); 73 | unselect(); 74 | return regval; 75 | } 76 | 77 | void writeReg(uint8_t addr, uint8_t value) { 78 | select(); 79 | SPI.transfer(addr | 0x80); 80 | SPI.transfer(value); 81 | unselect(); 82 | } 83 | 84 | void setMode(uint8_t newMode) { 85 | 86 | /* This floods the serial output, uncomment for more debugging. 87 | #ifdef DEBUG 88 | Serial.println(F("In setMode")); 89 | #endif 90 | */ 91 | 92 | if (newMode == _mode) { 93 | return; 94 | } 95 | 96 | uint8_t val = readReg(REG_OPMODE); 97 | switch (newMode) { 98 | case RF69_MODE_TX: 99 | writeReg(REG_OPMODE, (val & 0xE3) | RF_OPMODE_TRANSMITTER); 100 | break; 101 | case RF69_MODE_RX: 102 | writeReg(REG_OPMODE, (val & 0xE3) | RF_OPMODE_RECEIVER); 103 | break; 104 | case RF69_MODE_SYNTH: 105 | writeReg(REG_OPMODE, (val & 0xE3) | RF_OPMODE_SYNTHESIZER); 106 | break; 107 | case RF69_MODE_STANDBY: 108 | writeReg(REG_OPMODE, (val & 0xE3) | RF_OPMODE_STANDBY); 109 | break; 110 | case RF69_MODE_SLEEP: 111 | writeReg(REG_OPMODE, (val & 0xE3) | RF_OPMODE_SLEEP); 112 | break; 113 | default: 114 | return; 115 | } 116 | 117 | // we are using packet mode, so this check is not really needed but waiting for mode ready is necessary when 118 | // going from sleep because the FIFO may not be immediately available from previous mode. 119 | unsigned long start = millis(); 120 | uint16_t timeout = 500; 121 | while (_mode == RF69_MODE_SLEEP && millis() - start < timeout && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) { 122 | // wait for ModeReady 123 | yield(); 124 | } 125 | if (millis() - start >= timeout) { 126 | //Timeout when waiting for getting out of sleep 127 | } 128 | _mode = newMode; 129 | } 130 | 131 | uint32_t getFrequency() { 132 | return RF69_FSTEP * (((uint32_t)readReg(REG_FRFMSB) << 16) + ((uint16_t)readReg(REG_FRFMID) << 8) + readReg(REG_FRFLSB)); 133 | } 134 | void receiveBegin() { 135 | DATALEN = 0; 136 | if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) { 137 | uint8_t val = readReg(REG_PACKETCONFIG2); 138 | // avoid RX deadlocks 139 | writeReg(REG_PACKETCONFIG2, (val & 0xFB) | RF_PACKET2_RXRESTART); 140 | } 141 | setMode(RF69_MODE_RX); 142 | } 143 | 144 | // get the received signal strength indicator (RSSI) 145 | //uint16_t readRSSI(bool forceTrigger = false) { // Settings this to true gives a crash... 146 | int16_t readRSSI() { 147 | /* if (forceTrigger) { 148 | // RSSI trigger not needed if DAGC is in continuous mode 149 | writeReg(REG_RSSICONFIG, RF_RSSI_START); 150 | client.publish(mqtt_status_topic, "In rssi read"); 151 | 152 | while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00) { 153 | // wait for RSSI_Ready 154 | yield(); 155 | } 156 | }*/ 157 | int16_t rssi = -readReg(REG_RSSIVALUE); 158 | #ifdef DEBUG 159 | Serial.println("rssi: " + String(rssi) + "dbi"); 160 | #endif 161 | return rssi; 162 | } 163 | 164 | // checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode 165 | bool receiveDone() { 166 | // noInterrupts(); // re-enabled in unselect() via setMode() or via 167 | // receiveBegin() 168 | /* This floods the serial output, uncomment for more debugging. 169 | #ifdef DEBUG 170 | Serial.println("receiveDone"); 171 | #endif 172 | */ 173 | if (_mode == RF69_MODE_RX && DATALEN > 0) { 174 | setMode(RF69_MODE_STANDBY); // enables interrupts 175 | return true; 176 | 177 | } else if (_mode == RF69_MODE_RX) { 178 | // already in RX no payload yet 179 | // interrupts(); // explicitly re-enable interrupts 180 | return false; 181 | } 182 | 183 | receiveBegin(); 184 | return false; 185 | } 186 | 187 | uint16_t crc16(volatile uint8_t *data, size_t n) { 188 | /* This floods the serial output, uncomment for more debugging. 189 | #ifdef DEBUG 190 | Serial.println("In crc16"); 191 | #endif 192 | */ 193 | uint16_t crcReg = 0xffff; 194 | size_t i, j; 195 | for (j = 0; j < n; j++) { 196 | uint8_t crcData = data[j]; 197 | for (i = 0; i < 8; i++) { 198 | if (((crcReg & 0x8000) >> 8) ^ (crcData & 0x80)) 199 | crcReg = (crcReg << 1) ^ 0x8005; 200 | else 201 | crcReg = (crcReg << 1); 202 | crcData <<= 1; 203 | } 204 | } 205 | return crcReg; 206 | } 207 | bool initialize(uint32_t frequency) { 208 | #ifdef DEBUG 209 | Serial.print("In initialize, frequency = "); 210 | Serial.println(frequency); 211 | #endif 212 | frequency = frequency / RF69_FSTEP; 213 | 214 | const uint8_t CONFIG[][2] = { 215 | /* 0x01 */ {REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY}, 216 | /* 0x02 */ {REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_01}, 217 | /* 0x03 */ {REG_BITRATEMSB, (uint8_t)(BITRATE >> 8)}, 218 | /* 0x04 */ {REG_BITRATELSB, (uint8_t)(BITRATE)}, 219 | /* 0x05 */ {REG_FDEVMSB, (uint8_t)(FREQUENCYDEVIATION >> 8)}, 220 | /* 0x06 */ {REG_FDEVLSB, (uint8_t)(FREQUENCYDEVIATION)}, 221 | /* 0x07 */ {REG_FRFMSB, (uint8_t)(frequency >> 16)}, 222 | /* 0x08 */ {REG_FRFMID, (uint8_t)(frequency >> 8)}, 223 | /* 0x09 */ {REG_FRFLSB, (uint8_t)(frequency)}, 224 | /* 0x19 */ {REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_4}, // p26 in datasheet, filters out noise 225 | /* 0x25 */ {REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01}, // PayloadReady 226 | /* 0x26 */ {REG_DIOMAPPING2, RF_DIOMAPPING2_CLKOUT_OFF}, // DIO5 ClkOut disable for power saving 227 | /* 0x28 */ {REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN}, // writing to this bit ensures that the FIFO & status flags are reset 228 | /* 0x29 */ {REG_RSSITHRESH, RSSITHRESHOLD}, 229 | /* 0x2B */ {REG_RXTIMEOUT2, (uint8_t)0x00}, // RegRxTimeout2 (0x2B) interrupt is generated TimeoutRssiThresh *16*T bit after Rssi interrupt if PayloadReady interrupt doesn’t occur. 230 | /* 0x2D */ {REG_PREAMBLELSB, 3}, // default 3 preamble bytes 0xAAAAAA 231 | /* 0x2E */ {REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0}, 232 | /* 0x2F */ {REG_SYNCVALUE1, (uint8_t)(SYNCVALUE >> 8)}, 233 | /* 0x30 */ {REG_SYNCVALUE2, (uint8_t)(SYNCVALUE)}, 234 | /* 0x37 */ {REG_PACKETCONFIG1, RF_PACKET1_FORMAT_FIXED | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_OFF | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF}, 235 | /* 0x38 */ {REG_PAYLOADLENGTH, PAYLOADLENGTH}, 236 | /* 0x3C */ {REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE}, // TX on FIFO not empty 237 | /* 0x3D */ {REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF}, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) 238 | /* 0x6F */ {REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0}, // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0 239 | {255, 0} 240 | }; 241 | 242 | digitalWrite(SS, HIGH); 243 | pinMode(SS, OUTPUT); 244 | SPI.begin(); 245 | SPI.setDataMode(SPI_MODE0); 246 | SPI.setBitOrder(MSBFIRST); 247 | // decided to slow down from DIV2 after SPI stalling in some instances, 248 | // especially visible on mega1284p when RFM69 and FLASH chip both present 249 | SPI.setClockDivider(SPI_CLOCK_DIV4); 250 | 251 | unsigned long start = millis(); 252 | uint8_t timeout = 50; 253 | do { 254 | writeReg(REG_SYNCVALUE1, 0xAA); 255 | yield(); 256 | } while (readReg(REG_SYNCVALUE1) != 0xaa && millis() - start < timeout); 257 | if (readReg(REG_SYNCVALUE1) != 0xaa) { 258 | #ifdef DEBUG 259 | Serial.println("ERROR: Failed setting syncvalue1 1st time"); 260 | #endif 261 | return false; 262 | } 263 | start = millis(); 264 | do { 265 | writeReg(REG_SYNCVALUE1, 0x55); 266 | yield(); 267 | } while (readReg(REG_SYNCVALUE1) != 0x55 && millis() - start < timeout); 268 | if (readReg(REG_SYNCVALUE1) != 0x55) { 269 | #ifdef DEBUG 270 | Serial.println("ERROR: Failed setting syncvalue1 2nd time"); 271 | #endif 272 | return false; 273 | } 274 | for (uint8_t i = 0; CONFIG[i][0] != 255; i++) { 275 | writeReg(CONFIG[i][0], CONFIG[i][1]); 276 | yield(); 277 | } 278 | 279 | setMode(RF69_MODE_STANDBY); 280 | start = millis(); 281 | while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis() - start < timeout) { 282 | // wait for ModeReady 283 | delay(1); 284 | } 285 | if (millis() - start >= timeout) { 286 | #ifdef DEBUG 287 | Serial.println("Failed on waiting for ModeReady()"); 288 | #endif 289 | return false; 290 | } 291 | attachInterrupt(_interruptNum, interruptHandler, RISING); 292 | 293 | #ifdef DEBUG 294 | Serial.println("RFM69 init done"); 295 | #endif 296 | return true; 297 | } 298 | void ICACHE_RAM_ATTR interruptHandler() { 299 | String output; 300 | 301 | if (inInterrupt) { 302 | #ifdef DEBUG 303 | Serial.println("Already in interruptHandler."); 304 | #endif 305 | return; 306 | } 307 | inInterrupt = true; 308 | 309 | digitalWrite(LED_BLUE, HIGH); 310 | 311 | if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) { 312 | 313 | // Read Rssi 314 | int16_t srssi = readRSSI(); 315 | 316 | setMode(RF69_MODE_STANDBY); 317 | DATALEN = 0; 318 | select(); 319 | 320 | // Init reading 321 | SPI.transfer(REG_FIFO & 0x7F); 322 | 323 | // Read 20 bytes 324 | for (uint8_t i = 0; i < 20; i++) { 325 | TEMPDATA[i] = SPI.transfer(0); 326 | } 327 | 328 | // CRC is done BEFORE decrypting message 329 | uint16_t crc = crc16(TEMPDATA, 18); 330 | uint16_t packet_crc = TEMPDATA[18] << 8 | TEMPDATA[19]; 331 | 332 | #ifdef DEBUG 333 | Serial.println(F("Got rf data")); 334 | #endif 335 | 336 | const uint32_t sensor_id_sub = SENSOR_ID - 0x5D38E8CB; 337 | enc_key[0] = (uint8_t)(sensor_id_sub >> 24); 338 | enc_key[1] = (uint8_t)(sensor_id_sub); 339 | enc_key[2] = (uint8_t)(sensor_id_sub >> 8); 340 | enc_key[3] = 0x47; 341 | enc_key[4] = (uint8_t)(sensor_id_sub >> 16); 342 | 343 | // Decrypt message 344 | for (size_t i = 0; i < 13; i++) { 345 | TEMPDATA[5 + i] = TEMPDATA[5 + i] ^ enc_key[i % 5]; 346 | } 347 | 348 | uint32_t rcv_sensor_id = TEMPDATA[5] << 24 | TEMPDATA[6] << 16 | TEMPDATA[7] << 8 | TEMPDATA[8]; 349 | 350 | // Bug fix from https://github.com/strigeus/sparsnas_decoder/pull/7/files 351 | // if (data_[0] != 0x11 || data_[1] != (SENSOR_ID & 0xFF) || data_[3] != 0x07 || rcv_sensor_id != SENSOR_ID) { 352 | // if (TEMPDATA[0] != 0x11 || TEMPDATA[1] != (SENSOR_ID & 0xFF) || TEMPDATA[3] != 0x07 || TEMPDATA[4] != 0x0E || rcv_sensor_id != SENSOR_ID) { 353 | if (TEMPDATA[0] != 0x11 || TEMPDATA[1] != (SENSOR_ID & 0xFF) || TEMPDATA[3] != 0x07 || rcv_sensor_id != SENSOR_ID) { 354 | #ifdef SHOW_BAD_PACKETS 355 | output = ""; 356 | Serial.println("Bad packet!"); 357 | for (uint8_t i = 0; i < 20; i++) { 358 | if (TEMPDATA[i]<0x10) {Serial.print("0");} 359 | Serial.print(TEMPDATA[i],HEX); 360 | Serial.print(" "); 361 | } 362 | Serial.println(" "); 363 | #endif 364 | } else 365 | { 366 | #ifdef DEBUG 367 | Serial.println("Valid package received!"); 368 | #endif 369 | analogWrite(LED_BLUE, LED_BLUE_BRIGHTNESS); 370 | 371 | gettimeofday(&tv, nullptr); 372 | clock_gettime(0, &tp); 373 | now = time(nullptr); 374 | // EPOCH+tz+dst 375 | // Serial.print("Time:"); 376 | //Serial.print(ctime(&now)); 377 | 378 | /* 379 | 0: uint8_t length; // Always 0x11 380 | 1: uint8_t sender_id_lo; // Lowest byte of sender ID 381 | 2: uint8_t unknown; // Not sure 382 | 3: uint8_t major_version; // Always 0x07 - the major version number of the sender. 383 | 4: uint8_t minor_version; // Always 0x0E - the minor version number of the sender. 384 | 5: uint32_t sender_id; // ID of sender 385 | 9: uint16_t time; // Time in units of 15 seconds. 386 | 11:uint16_t effect; // Current effect usage 387 | 13:uint32_t pulses; // Total number of pulses 388 | 17:uint8_t battery; // Battery level, 0-100. 389 | */ 390 | 391 | // Ref: https://github.com/strigeus/sparsnas_decoder 392 | int seq = (TEMPDATA[9] << 8 | TEMPDATA[10]); // Time in units of 15 seconds. 393 | unsigned int power = (TEMPDATA[11] << 8 | TEMPDATA[12]); // Current effect usage 394 | int pulse = (TEMPDATA[13] << 24 | TEMPDATA[14] << 16 | TEMPDATA[15] << 8 | TEMPDATA[16]); // Total number of pulses 395 | int battery = TEMPDATA[17]; // Battery level, 0-100. 396 | 397 | #ifdef DEBUG 398 | Serial.println("Current effect usage, hex"); 399 | Serial.print(TEMPDATA[11], HEX); 400 | Serial.print(" "); 401 | Serial.println(TEMPDATA[12], HEX); 402 | #endif 403 | 404 | // This is how to convert the 'effect' field into Watt: 405 | // float watt = (float)((3600000 / PULSES_PER_KWH) * 1024) / (effect); ( 11:uint16_t effect;) This equals "power" in this code. 406 | 407 | // Bug fix from https://github.com/strigeus/sparsnas_decoder/pull/7/files 408 | // float watt = (float)((3600000 / PULSES_PER_KWH) * 1024) / (power); 409 | float watt = power * 24; 410 | int data4 = TEMPDATA[4]^0x0f; 411 | // Note that data_[4] cycles between 0-3 when you first put in the batterys in t$ 412 | if (data4 == 1) { 413 | watt = (3600000.0f / float(PULSES_PER_KWH) * 1024.0f) / float(power); 414 | } else if (data4 == 0) { // special mode for low power usage 415 | watt = power * 0.24f / float(PULSES_PER_KWH); 416 | } 417 | /* m += sprintf(m, "%5d: %7.1f W. %d.%.3d kWh. Batt %d%%. FreqErr: %.2f", seq, watt, pulse/PULSES_PER_KWH, pulse%PULSES_PER_KWH, battery, freq); 418 | 'So in the example 10 % 3, 10 divided by 3 is 3 with remainder 1, so the answer is 1.' 419 | */ 420 | #ifdef DEBUG 421 | // Print amount of free memory. 422 | int heap = ESP.getFreeHeap(); 423 | Serial.print(F("Available memory: ")); 424 | Serial.println (heap); 425 | #endif 426 | 427 | // Prepare for output 428 | output = "Seq " + String(seq) + ": "; 429 | output += String(now) + ", "; 430 | output += String(watt) + " W, total: "; 431 | output += String(pulse / PULSES_PER_KWH) + " kWh, battery "; 432 | output += String(battery) + "%, rssi "; 433 | output += String(srssi) + "dBm. Power(raw): "; 434 | output += String(power) + " "; 435 | output += (crc == packet_crc ? "" : "CRC ERR"); 436 | String err = (crc == packet_crc ? "" : "CRC ERR"); 437 | 438 | float vcc = ESP.getVcc(); 439 | output += "Vcc: " + String(vcc) + "mV"; 440 | Serial.println(output); 441 | 442 | const size_t capacity = JSON_OBJECT_SIZE(9); 443 | DynamicJsonDocument status(capacity); 444 | if (err=="CRC ERR") { 445 | Serial.println(err); 446 | status["error"] = "CRC Error"; 447 | analogWrite(LED_RED, LED_RED_BRIGHTNESS); 448 | mClient.publish((char*) String(mqtt_debug_topic).c_str(), (char*) output.c_str()); 449 | delay(300); 450 | analogWrite(LED_RED, 0); 451 | } 452 | else { 453 | status["error"] = ""; 454 | } 455 | 456 | status["seq"] = seq; 457 | status["timestamp"] = now; 458 | status["watt"] = float(watt); 459 | status["total"] = float(pulse) / float(PULSES_PER_KWH); 460 | status["battery"] = battery; 461 | status["rssi"] = srssi; 462 | status["power"] = power; 463 | status["pulse"] = pulse; 464 | 465 | String mqttMess; 466 | serializeJson(status, mqttMess); 467 | 468 | if (status["error"] == "") { 469 | publish_mqtt(state_topic, mqttMess); 470 | mClient.publish((char*) String(mqtt_status_topic).c_str(), (char*) mqttMess.c_str()); 471 | } 472 | analogWrite(LED_BLUE, 0); 473 | } 474 | unselect(); 475 | setMode(RF69_MODE_RX); 476 | } 477 | digitalWrite(LED_BLUE, LOW); 478 | 479 | //Serial.println("Int done"); 480 | inInterrupt = false; 481 | } 482 | -------------------------------------------------------------------------------- /include/RFM69registers.h: -------------------------------------------------------------------------------- 1 | // ********************************************************************************** 2 | // Registers used in driver definition for HopeRF RFM69W/RFM69HW, Semtech SX1231/1231H 3 | // ********************************************************************************** 4 | // Copyright Felix Rusu (2015), 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 2 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; if not, write 23 | // to the Free Software Foundation, Inc., 24 | // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 | // 26 | // Licence can be viewed at 27 | // http://www.fsf.org/licenses/gpl.txt 28 | // 29 | // Please maintain this license information along with authorship 30 | // and copyright notices in any redistribution of this code 31 | // ********************************************************************************** 32 | // RFM69/SX1231 Internal registers addresses 33 | //************************************************** 34 | #define REG_FIFO 0x00 35 | #define REG_OPMODE 0x01 36 | #define REG_DATAMODUL 0x02 37 | #define REG_BITRATEMSB 0x03 38 | #define REG_BITRATELSB 0x04 39 | #define REG_FDEVMSB 0x05 40 | #define REG_FDEVLSB 0x06 41 | #define REG_FRFMSB 0x07 42 | #define REG_FRFMID 0x08 43 | #define REG_FRFLSB 0x09 44 | #define REG_OSC1 0x0A 45 | #define REG_AFCCTRL 0x0B 46 | #define REG_LOWBAT 0x0C 47 | #define REG_LISTEN1 0x0D 48 | #define REG_LISTEN2 0x0E 49 | #define REG_LISTEN3 0x0F 50 | #define REG_VERSION 0x10 51 | #define REG_PALEVEL 0x11 52 | #define REG_PARAMP 0x12 53 | #define REG_OCP 0x13 54 | #define REG_AGCREF 0x14 // not present on RFM69/SX1231 55 | #define REG_AGCTHRESH1 0x15 // not present on RFM69/SX1231 56 | #define REG_AGCTHRESH2 0x16 // not present on RFM69/SX1231 57 | #define REG_AGCTHRESH3 0x17 // not present on RFM69/SX1231 58 | #define REG_LNA 0x18 59 | #define REG_RXBW 0x19 60 | #define REG_AFCBW 0x1A 61 | #define REG_OOKPEAK 0x1B 62 | #define REG_OOKAVG 0x1C 63 | #define REG_OOKFIX 0x1D 64 | #define REG_AFCFEI 0x1E 65 | #define REG_AFCMSB 0x1F 66 | #define REG_AFCLSB 0x20 67 | #define REG_FEIMSB 0x21 68 | #define REG_FEILSB 0x22 69 | #define REG_RSSICONFIG 0x23 70 | #define REG_RSSIVALUE 0x24 71 | #define REG_DIOMAPPING1 0x25 72 | #define REG_DIOMAPPING2 0x26 73 | #define REG_IRQFLAGS1 0x27 74 | #define REG_IRQFLAGS2 0x28 75 | #define REG_RSSITHRESH 0x29 76 | #define REG_RXTIMEOUT1 0x2A 77 | #define REG_RXTIMEOUT2 0x2B 78 | #define REG_PREAMBLEMSB 0x2C 79 | #define REG_PREAMBLELSB 0x2D 80 | #define REG_SYNCCONFIG 0x2E 81 | #define REG_SYNCVALUE1 0x2F 82 | #define REG_SYNCVALUE2 0x30 83 | #define REG_SYNCVALUE3 0x31 84 | #define REG_SYNCVALUE4 0x32 85 | #define REG_SYNCVALUE5 0x33 86 | #define REG_SYNCVALUE6 0x34 87 | #define REG_SYNCVALUE7 0x35 88 | #define REG_SYNCVALUE8 0x36 89 | #define REG_PACKETCONFIG1 0x37 90 | #define REG_PAYLOADLENGTH 0x38 91 | #define REG_NODEADRS 0x39 92 | #define REG_BROADCASTADRS 0x3A 93 | #define REG_AUTOMODES 0x3B 94 | #define REG_FIFOTHRESH 0x3C 95 | #define REG_PACKETCONFIG2 0x3D 96 | #define REG_AESKEY1 0x3E 97 | #define REG_AESKEY2 0x3F 98 | #define REG_AESKEY3 0x40 99 | #define REG_AESKEY4 0x41 100 | #define REG_AESKEY5 0x42 101 | #define REG_AESKEY6 0x43 102 | #define REG_AESKEY7 0x44 103 | #define REG_AESKEY8 0x45 104 | #define REG_AESKEY9 0x46 105 | #define REG_AESKEY10 0x47 106 | #define REG_AESKEY11 0x48 107 | #define REG_AESKEY12 0x49 108 | #define REG_AESKEY13 0x4A 109 | #define REG_AESKEY14 0x4B 110 | #define REG_AESKEY15 0x4C 111 | #define REG_AESKEY16 0x4D 112 | #define REG_TEMP1 0x4E 113 | #define REG_TEMP2 0x4F 114 | #define REG_TESTLNA 0x58 115 | #define REG_TESTPA1 0x5A // only present on RFM69HW/SX1231H 116 | #define REG_TESTPA2 0x5C // only present on RFM69HW/SX1231H 117 | #define REG_TESTDAGC 0x6F 118 | 119 | //****************************************************** 120 | // RF69/SX1231 bit control definition 121 | //****************************************************** 122 | 123 | // RegOpMode 124 | #define RF_OPMODE_SEQUENCER_OFF 0x80 125 | #define RF_OPMODE_SEQUENCER_ON 0x00 // Default 126 | 127 | #define RF_OPMODE_LISTEN_ON 0x40 128 | #define RF_OPMODE_LISTEN_OFF 0x00 // Default 129 | 130 | #define RF_OPMODE_LISTENABORT 0x20 131 | 132 | #define RF_OPMODE_SLEEP 0x00 133 | #define RF_OPMODE_STANDBY 0x04 // Default 134 | #define RF_OPMODE_SYNTHESIZER 0x08 135 | #define RF_OPMODE_TRANSMITTER 0x0C 136 | #define RF_OPMODE_RECEIVER 0x10 137 | 138 | 139 | // RegDataModul 140 | #define RF_DATAMODUL_DATAMODE_PACKET 0x00 // Default 141 | #define RF_DATAMODUL_DATAMODE_CONTINUOUS 0x40 142 | #define RF_DATAMODUL_DATAMODE_CONTINUOUSNOBSYNC 0x60 143 | 144 | #define RF_DATAMODUL_MODULATIONTYPE_FSK 0x00 // Default 145 | #define RF_DATAMODUL_MODULATIONTYPE_OOK 0x08 146 | 147 | #define RF_DATAMODUL_MODULATIONSHAPING_00 0x00 // Default 148 | #define RF_DATAMODUL_MODULATIONSHAPING_01 0x01 149 | #define RF_DATAMODUL_MODULATIONSHAPING_10 0x02 150 | #define RF_DATAMODUL_MODULATIONSHAPING_11 0x03 151 | 152 | 153 | // RegBitRate (bits/sec) example bit rates 154 | #define RF_BITRATEMSB_1200 0x68 155 | #define RF_BITRATELSB_1200 0x2B 156 | #define RF_BITRATEMSB_2400 0x34 157 | #define RF_BITRATELSB_2400 0x15 158 | #define RF_BITRATEMSB_4800 0x1A // Default 159 | #define RF_BITRATELSB_4800 0x0B // Default 160 | #define RF_BITRATEMSB_9600 0x0D 161 | #define RF_BITRATELSB_9600 0x05 162 | #define RF_BITRATEMSB_19200 0x06 163 | #define RF_BITRATELSB_19200 0x83 164 | #define RF_BITRATEMSB_38400 0x03 165 | #define RF_BITRATELSB_38400 0x41 166 | 167 | #define RF_BITRATEMSB_38323 0x03 168 | #define RF_BITRATELSB_38323 0x43 169 | 170 | #define RF_BITRATEMSB_34482 0x03 171 | #define RF_BITRATELSB_34482 0xA0 172 | 173 | #define RF_BITRATEMSB_76800 0x01 174 | #define RF_BITRATELSB_76800 0xA1 175 | #define RF_BITRATEMSB_153600 0x00 176 | #define RF_BITRATELSB_153600 0xD0 177 | #define RF_BITRATEMSB_57600 0x02 178 | #define RF_BITRATELSB_57600 0x2C 179 | #define RF_BITRATEMSB_115200 0x01 180 | #define RF_BITRATELSB_115200 0x16 181 | #define RF_BITRATEMSB_12500 0x0A 182 | #define RF_BITRATELSB_12500 0x00 183 | #define RF_BITRATEMSB_25000 0x05 184 | #define RF_BITRATELSB_25000 0x00 185 | #define RF_BITRATEMSB_50000 0x02 186 | #define RF_BITRATELSB_50000 0x80 187 | #define RF_BITRATEMSB_100000 0x01 188 | #define RF_BITRATELSB_100000 0x40 189 | #define RF_BITRATEMSB_150000 0x00 190 | #define RF_BITRATELSB_150000 0xD5 191 | #define RF_BITRATEMSB_200000 0x00 192 | #define RF_BITRATELSB_200000 0xA0 193 | #define RF_BITRATEMSB_250000 0x00 194 | #define RF_BITRATELSB_250000 0x80 195 | #define RF_BITRATEMSB_300000 0x00 196 | #define RF_BITRATELSB_300000 0x6B 197 | #define RF_BITRATEMSB_32768 0x03 198 | #define RF_BITRATELSB_32768 0xD1 199 | // custom bit rates 200 | #define RF_BITRATEMSB_55555 0x02 201 | #define RF_BITRATELSB_55555 0x40 202 | #define RF_BITRATEMSB_200KBPS 0x00 203 | #define RF_BITRATELSB_200KBPS 0xa0 204 | 205 | 206 | // RegFdev - frequency deviation (Hz) 207 | #define RF_FDEVMSB_2000 0x00 208 | #define RF_FDEVLSB_2000 0x21 209 | #define RF_FDEVMSB_5000 0x00 // Default 210 | #define RF_FDEVLSB_5000 0x52 // Default 211 | #define RF_FDEVMSB_7500 0x00 212 | #define RF_FDEVLSB_7500 0x7B 213 | #define RF_FDEVMSB_10000 0x00 214 | #define RF_FDEVLSB_10000 0xA4 215 | #define RF_FDEVMSB_15000 0x00 216 | #define RF_FDEVLSB_15000 0xF6 217 | #define RF_FDEVMSB_20000 0x01 218 | #define RF_FDEVLSB_20000 0x48 219 | #define RF_FDEVMSB_25000 0x01 220 | #define RF_FDEVLSB_25000 0x9A 221 | #define RF_FDEVMSB_30000 0x01 222 | #define RF_FDEVLSB_30000 0xEC 223 | #define RF_FDEVMSB_35000 0x02 224 | #define RF_FDEVLSB_35000 0x3D 225 | #define RF_FDEVMSB_40000 0x02 226 | #define RF_FDEVLSB_40000 0x8F 227 | #define RF_FDEVMSB_45000 0x02 228 | #define RF_FDEVLSB_45000 0xE1 229 | #define RF_FDEVMSB_50000 0x03 230 | #define RF_FDEVLSB_50000 0x33 231 | #define RF_FDEVMSB_55000 0x03 232 | #define RF_FDEVLSB_55000 0x85 233 | #define RF_FDEVMSB_60000 0x03 234 | #define RF_FDEVLSB_60000 0xD7 235 | #define RF_FDEVMSB_65000 0x04 236 | #define RF_FDEVLSB_65000 0x29 237 | #define RF_FDEVMSB_70000 0x04 238 | #define RF_FDEVLSB_70000 0x7B 239 | #define RF_FDEVMSB_75000 0x04 240 | #define RF_FDEVLSB_75000 0xCD 241 | #define RF_FDEVMSB_80000 0x05 242 | #define RF_FDEVLSB_80000 0x1F 243 | #define RF_FDEVMSB_85000 0x05 244 | #define RF_FDEVLSB_85000 0x71 245 | #define RF_FDEVMSB_90000 0x05 246 | #define RF_FDEVLSB_90000 0xC3 247 | #define RF_FDEVMSB_95000 0x06 248 | #define RF_FDEVLSB_95000 0x14 249 | #define RF_FDEVMSB_100000 0x06 250 | #define RF_FDEVLSB_100000 0x66 251 | #define RF_FDEVMSB_110000 0x07 252 | #define RF_FDEVLSB_110000 0x0A 253 | #define RF_FDEVMSB_120000 0x07 254 | #define RF_FDEVLSB_120000 0xAE 255 | #define RF_FDEVMSB_130000 0x08 256 | #define RF_FDEVLSB_130000 0x52 257 | #define RF_FDEVMSB_140000 0x08 258 | #define RF_FDEVLSB_140000 0xF6 259 | #define RF_FDEVMSB_150000 0x09 260 | #define RF_FDEVLSB_150000 0x9A 261 | #define RF_FDEVMSB_160000 0x0A 262 | #define RF_FDEVLSB_160000 0x3D 263 | #define RF_FDEVMSB_170000 0x0A 264 | #define RF_FDEVLSB_170000 0xE1 265 | #define RF_FDEVMSB_180000 0x0B 266 | #define RF_FDEVLSB_180000 0x85 267 | #define RF_FDEVMSB_190000 0x0C 268 | #define RF_FDEVLSB_190000 0x29 269 | #define RF_FDEVMSB_200000 0x0C 270 | #define RF_FDEVLSB_200000 0xCD 271 | #define RF_FDEVMSB_210000 0x0D 272 | #define RF_FDEVLSB_210000 0x71 273 | #define RF_FDEVMSB_220000 0x0E 274 | #define RF_FDEVLSB_220000 0x14 275 | #define RF_FDEVMSB_230000 0x0E 276 | #define RF_FDEVLSB_230000 0xB8 277 | #define RF_FDEVMSB_240000 0x0F 278 | #define RF_FDEVLSB_240000 0x5C 279 | #define RF_FDEVMSB_250000 0x10 280 | #define RF_FDEVLSB_250000 0x00 281 | #define RF_FDEVMSB_260000 0x10 282 | #define RF_FDEVLSB_260000 0xA4 283 | #define RF_FDEVMSB_270000 0x11 284 | #define RF_FDEVLSB_270000 0x48 285 | #define RF_FDEVMSB_280000 0x11 286 | #define RF_FDEVLSB_280000 0xEC 287 | #define RF_FDEVMSB_290000 0x12 288 | #define RF_FDEVLSB_290000 0x8F 289 | #define RF_FDEVMSB_300000 0x13 290 | #define RF_FDEVLSB_300000 0x33 291 | 292 | 293 | // RegFrf (MHz) - carrier frequency 294 | // 315Mhz band 295 | #define RF_FRFMSB_314 0x4E 296 | #define RF_FRFMID_314 0x80 297 | #define RF_FRFLSB_314 0x00 298 | #define RF_FRFMSB_315 0x4E 299 | #define RF_FRFMID_315 0xC0 300 | #define RF_FRFLSB_315 0x00 301 | #define RF_FRFMSB_316 0x4F 302 | #define RF_FRFMID_316 0x00 303 | #define RF_FRFLSB_316 0x00 304 | // 433mhz band 305 | #define RF_FRFMSB_433 0x6C 306 | #define RF_FRFMID_433 0x40 307 | #define RF_FRFLSB_433 0x00 308 | #define RF_FRFMSB_434 0x6C 309 | #define RF_FRFMID_434 0x80 310 | #define RF_FRFLSB_434 0x00 311 | #define RF_FRFMSB_435 0x6C 312 | #define RF_FRFMID_435 0xC0 313 | #define RF_FRFLSB_435 0x00 314 | // 868Mhz band 315 | #define RF_FRFMSB_863 0xD7 316 | #define RF_FRFMID_863 0xC0 317 | #define RF_FRFLSB_863 0x00 318 | #define RF_FRFMSB_864 0xD8 319 | #define RF_FRFMID_864 0x00 320 | #define RF_FRFLSB_864 0x00 321 | #define RF_FRFMSB_865 0xD8 322 | #define RF_FRFMID_865 0x40 323 | #define RF_FRFLSB_865 0x00 324 | #define RF_FRFMSB_866 0xD8 325 | #define RF_FRFMID_866 0x80 326 | #define RF_FRFLSB_866 0x00 327 | #define RF_FRFMSB_867 0xD8 328 | #define RF_FRFMID_867 0xC0 329 | #define RF_FRFLSB_867 0x00 330 | #define RF_FRFMSB_868 0xD9 331 | #define RF_FRFMID_868 0x00 332 | #define RF_FRFLSB_868 0x00 333 | #define RF_FRFMSB_869 0xD9 334 | #define RF_FRFMID_869 0x40 335 | #define RF_FRFLSB_869 0x00 336 | #define RF_FRFMSB_870 0xD9 337 | #define RF_FRFMID_870 0x80 338 | #define RF_FRFLSB_870 0x00 339 | // 915Mhz band 340 | #define RF_FRFMSB_902 0xE1 341 | #define RF_FRFMID_902 0x80 342 | #define RF_FRFLSB_902 0x00 343 | #define RF_FRFMSB_903 0xE1 344 | #define RF_FRFMID_903 0xC0 345 | #define RF_FRFLSB_903 0x00 346 | #define RF_FRFMSB_904 0xE2 347 | #define RF_FRFMID_904 0x00 348 | #define RF_FRFLSB_904 0x00 349 | #define RF_FRFMSB_905 0xE2 350 | #define RF_FRFMID_905 0x40 351 | #define RF_FRFLSB_905 0x00 352 | #define RF_FRFMSB_906 0xE2 353 | #define RF_FRFMID_906 0x80 354 | #define RF_FRFLSB_906 0x00 355 | #define RF_FRFMSB_907 0xE2 356 | #define RF_FRFMID_907 0xC0 357 | #define RF_FRFLSB_907 0x00 358 | #define RF_FRFMSB_908 0xE3 359 | #define RF_FRFMID_908 0x00 360 | #define RF_FRFLSB_908 0x00 361 | #define RF_FRFMSB_909 0xE3 362 | #define RF_FRFMID_909 0x40 363 | #define RF_FRFLSB_909 0x00 364 | #define RF_FRFMSB_910 0xE3 365 | #define RF_FRFMID_910 0x80 366 | #define RF_FRFLSB_910 0x00 367 | #define RF_FRFMSB_911 0xE3 368 | #define RF_FRFMID_911 0xC0 369 | #define RF_FRFLSB_911 0x00 370 | #define RF_FRFMSB_912 0xE4 371 | #define RF_FRFMID_912 0x00 372 | #define RF_FRFLSB_912 0x00 373 | #define RF_FRFMSB_913 0xE4 374 | #define RF_FRFMID_913 0x40 375 | #define RF_FRFLSB_913 0x00 376 | #define RF_FRFMSB_914 0xE4 377 | #define RF_FRFMID_914 0x80 378 | #define RF_FRFLSB_914 0x00 379 | #define RF_FRFMSB_915 0xE4 // Default 380 | #define RF_FRFMID_915 0xC0 // Default 381 | #define RF_FRFLSB_915 0x00 // Default 382 | #define RF_FRFMSB_916 0xE5 383 | #define RF_FRFMID_916 0x00 384 | #define RF_FRFLSB_916 0x00 385 | #define RF_FRFMSB_917 0xE5 386 | #define RF_FRFMID_917 0x40 387 | #define RF_FRFLSB_917 0x00 388 | #define RF_FRFMSB_918 0xE5 389 | #define RF_FRFMID_918 0x80 390 | #define RF_FRFLSB_918 0x00 391 | #define RF_FRFMSB_919 0xE5 392 | #define RF_FRFMID_919 0xC0 393 | #define RF_FRFLSB_919 0x00 394 | #define RF_FRFMSB_920 0xE6 395 | #define RF_FRFMID_920 0x00 396 | #define RF_FRFLSB_920 0x00 397 | #define RF_FRFMSB_921 0xE6 398 | #define RF_FRFMID_921 0x40 399 | #define RF_FRFLSB_921 0x00 400 | #define RF_FRFMSB_922 0xE6 401 | #define RF_FRFMID_922 0x80 402 | #define RF_FRFLSB_922 0x00 403 | #define RF_FRFMSB_923 0xE6 404 | #define RF_FRFMID_923 0xC0 405 | #define RF_FRFLSB_923 0x00 406 | #define RF_FRFMSB_924 0xE7 407 | #define RF_FRFMID_924 0x00 408 | #define RF_FRFLSB_924 0x00 409 | #define RF_FRFMSB_925 0xE7 410 | #define RF_FRFMID_925 0x40 411 | #define RF_FRFLSB_925 0x00 412 | #define RF_FRFMSB_926 0xE7 413 | #define RF_FRFMID_926 0x80 414 | #define RF_FRFLSB_926 0x00 415 | #define RF_FRFMSB_927 0xE7 416 | #define RF_FRFMID_927 0xC0 417 | #define RF_FRFLSB_927 0x00 418 | #define RF_FRFMSB_928 0xE8 419 | #define RF_FRFMID_928 0x00 420 | #define RF_FRFLSB_928 0x00 421 | 422 | 423 | // RegOsc1 424 | #define RF_OSC1_RCCAL_START 0x80 425 | #define RF_OSC1_RCCAL_DONE 0x40 426 | 427 | 428 | // RegAfcCtrl 429 | #define RF_AFCCTRL_LOWBETA_OFF 0x00 // Default 430 | #define RF_AFCCTRL_LOWBETA_ON 0x20 431 | 432 | 433 | // RegLowBat 434 | #define RF_LOWBAT_MONITOR 0x10 435 | #define RF_LOWBAT_ON 0x08 436 | #define RF_LOWBAT_OFF 0x00 // Default 437 | 438 | #define RF_LOWBAT_TRIM_1695 0x00 439 | #define RF_LOWBAT_TRIM_1764 0x01 440 | #define RF_LOWBAT_TRIM_1835 0x02 // Default 441 | #define RF_LOWBAT_TRIM_1905 0x03 442 | #define RF_LOWBAT_TRIM_1976 0x04 443 | #define RF_LOWBAT_TRIM_2045 0x05 444 | #define RF_LOWBAT_TRIM_2116 0x06 445 | #define RF_LOWBAT_TRIM_2185 0x07 446 | 447 | 448 | // RegListen1 449 | #define RF_LISTEN1_RESOL_64 0x50 450 | #define RF_LISTEN1_RESOL_4100 0xA0 // Default 451 | #define RF_LISTEN1_RESOL_262000 0xF0 452 | 453 | #define RF_LISTEN1_RESOL_IDLE_64 0x40 454 | #define RF_LISTEN1_RESOL_IDLE_4100 0x80 // Default 455 | #define RF_LISTEN1_RESOL_IDLE_262000 0xC0 456 | 457 | #define RF_LISTEN1_RESOL_RX_64 0x10 458 | #define RF_LISTEN1_RESOL_RX_4100 0x20 // Default 459 | #define RF_LISTEN1_RESOL_RX_262000 0x30 460 | 461 | #define RF_LISTEN1_CRITERIA_RSSI 0x00 // Default 462 | #define RF_LISTEN1_CRITERIA_RSSIANDSYNC 0x08 463 | 464 | #define RF_LISTEN1_END_00 0x00 465 | #define RF_LISTEN1_END_01 0x02 // Default 466 | #define RF_LISTEN1_END_10 0x04 467 | 468 | 469 | // RegListen2 470 | #define RF_LISTEN2_COEFIDLE_VALUE 0xF5 // Default 471 | 472 | 473 | // RegListen3 474 | #define RF_LISTEN3_COEFRX_VALUE 0x20 // Default 475 | 476 | 477 | // RegVersion 478 | #define RF_VERSION_VER 0x24 // Default 479 | 480 | 481 | // RegPaLevel 482 | #define RF_PALEVEL_PA0_ON 0x80 // Default 483 | #define RF_PALEVEL_PA0_OFF 0x00 484 | #define RF_PALEVEL_PA1_ON 0x40 485 | #define RF_PALEVEL_PA1_OFF 0x00 // Default 486 | #define RF_PALEVEL_PA2_ON 0x20 487 | #define RF_PALEVEL_PA2_OFF 0x00 // Default 488 | 489 | #define RF_PALEVEL_OUTPUTPOWER_00000 0x00 490 | #define RF_PALEVEL_OUTPUTPOWER_00001 0x01 491 | #define RF_PALEVEL_OUTPUTPOWER_00010 0x02 492 | #define RF_PALEVEL_OUTPUTPOWER_00011 0x03 493 | #define RF_PALEVEL_OUTPUTPOWER_00100 0x04 494 | #define RF_PALEVEL_OUTPUTPOWER_00101 0x05 495 | #define RF_PALEVEL_OUTPUTPOWER_00110 0x06 496 | #define RF_PALEVEL_OUTPUTPOWER_00111 0x07 497 | #define RF_PALEVEL_OUTPUTPOWER_01000 0x08 498 | #define RF_PALEVEL_OUTPUTPOWER_01001 0x09 499 | #define RF_PALEVEL_OUTPUTPOWER_01010 0x0A 500 | #define RF_PALEVEL_OUTPUTPOWER_01011 0x0B 501 | #define RF_PALEVEL_OUTPUTPOWER_01100 0x0C 502 | #define RF_PALEVEL_OUTPUTPOWER_01101 0x0D 503 | #define RF_PALEVEL_OUTPUTPOWER_01110 0x0E 504 | #define RF_PALEVEL_OUTPUTPOWER_01111 0x0F 505 | #define RF_PALEVEL_OUTPUTPOWER_10000 0x10 506 | #define RF_PALEVEL_OUTPUTPOWER_10001 0x11 507 | #define RF_PALEVEL_OUTPUTPOWER_10010 0x12 508 | #define RF_PALEVEL_OUTPUTPOWER_10011 0x13 509 | #define RF_PALEVEL_OUTPUTPOWER_10100 0x14 510 | #define RF_PALEVEL_OUTPUTPOWER_10101 0x15 511 | #define RF_PALEVEL_OUTPUTPOWER_10110 0x16 512 | #define RF_PALEVEL_OUTPUTPOWER_10111 0x17 513 | #define RF_PALEVEL_OUTPUTPOWER_11000 0x18 514 | #define RF_PALEVEL_OUTPUTPOWER_11001 0x19 515 | #define RF_PALEVEL_OUTPUTPOWER_11010 0x1A 516 | #define RF_PALEVEL_OUTPUTPOWER_11011 0x1B 517 | #define RF_PALEVEL_OUTPUTPOWER_11100 0x1C 518 | #define RF_PALEVEL_OUTPUTPOWER_11101 0x1D 519 | #define RF_PALEVEL_OUTPUTPOWER_11110 0x1E 520 | #define RF_PALEVEL_OUTPUTPOWER_11111 0x1F // Default 521 | 522 | 523 | // RegPaRamp 524 | #define RF_PARAMP_3400 0x00 525 | #define RF_PARAMP_2000 0x01 526 | #define RF_PARAMP_1000 0x02 527 | #define RF_PARAMP_500 0x03 528 | #define RF_PARAMP_250 0x04 529 | #define RF_PARAMP_125 0x05 530 | #define RF_PARAMP_100 0x06 531 | #define RF_PARAMP_62 0x07 532 | #define RF_PARAMP_50 0x08 533 | #define RF_PARAMP_40 0x09 // Default 534 | #define RF_PARAMP_31 0x0A 535 | #define RF_PARAMP_25 0x0B 536 | #define RF_PARAMP_20 0x0C 537 | #define RF_PARAMP_15 0x0D 538 | #define RF_PARAMP_12 0x0E 539 | #define RF_PARAMP_10 0x0F 540 | 541 | 542 | // RegOcp 543 | #define RF_OCP_OFF 0x0F 544 | #define RF_OCP_ON 0x1A // Default 545 | 546 | #define RF_OCP_TRIM_45 0x00 547 | #define RF_OCP_TRIM_50 0x01 548 | #define RF_OCP_TRIM_55 0x02 549 | #define RF_OCP_TRIM_60 0x03 550 | #define RF_OCP_TRIM_65 0x04 551 | #define RF_OCP_TRIM_70 0x05 552 | #define RF_OCP_TRIM_75 0x06 553 | #define RF_OCP_TRIM_80 0x07 554 | #define RF_OCP_TRIM_85 0x08 555 | #define RF_OCP_TRIM_90 0x09 556 | #define RF_OCP_TRIM_95 0x0A // Default 557 | #define RF_OCP_TRIM_100 0x0B 558 | #define RF_OCP_TRIM_105 0x0C 559 | #define RF_OCP_TRIM_110 0x0D 560 | #define RF_OCP_TRIM_115 0x0E 561 | #define RF_OCP_TRIM_120 0x0F 562 | 563 | 564 | // RegAgcRef - not present on RFM69/SX1231 565 | #define RF_AGCREF_AUTO_ON 0x40 // Default 566 | #define RF_AGCREF_AUTO_OFF 0x00 567 | 568 | #define RF_AGCREF_LEVEL_MINUS80 0x00 // Default 569 | #define RF_AGCREF_LEVEL_MINUS81 0x01 570 | #define RF_AGCREF_LEVEL_MINUS82 0x02 571 | #define RF_AGCREF_LEVEL_MINUS83 0x03 572 | #define RF_AGCREF_LEVEL_MINUS84 0x04 573 | #define RF_AGCREF_LEVEL_MINUS85 0x05 574 | #define RF_AGCREF_LEVEL_MINUS86 0x06 575 | #define RF_AGCREF_LEVEL_MINUS87 0x07 576 | #define RF_AGCREF_LEVEL_MINUS88 0x08 577 | #define RF_AGCREF_LEVEL_MINUS89 0x09 578 | #define RF_AGCREF_LEVEL_MINUS90 0x0A 579 | #define RF_AGCREF_LEVEL_MINUS91 0x0B 580 | #define RF_AGCREF_LEVEL_MINUS92 0x0C 581 | #define RF_AGCREF_LEVEL_MINUS93 0x0D 582 | #define RF_AGCREF_LEVEL_MINUS94 0x0E 583 | #define RF_AGCREF_LEVEL_MINUS95 0x0F 584 | #define RF_AGCREF_LEVEL_MINUS96 0x10 585 | #define RF_AGCREF_LEVEL_MINUS97 0x11 586 | #define RF_AGCREF_LEVEL_MINUS98 0x12 587 | #define RF_AGCREF_LEVEL_MINUS99 0x13 588 | #define RF_AGCREF_LEVEL_MINUS100 0x14 589 | #define RF_AGCREF_LEVEL_MINUS101 0x15 590 | #define RF_AGCREF_LEVEL_MINUS102 0x16 591 | #define RF_AGCREF_LEVEL_MINUS103 0x17 592 | #define RF_AGCREF_LEVEL_MINUS104 0x18 593 | #define RF_AGCREF_LEVEL_MINUS105 0x19 594 | #define RF_AGCREF_LEVEL_MINUS106 0x1A 595 | #define RF_AGCREF_LEVEL_MINUS107 0x1B 596 | #define RF_AGCREF_LEVEL_MINUS108 0x1C 597 | #define RF_AGCREF_LEVEL_MINUS109 0x1D 598 | #define RF_AGCREF_LEVEL_MINUS110 0x1E 599 | #define RF_AGCREF_LEVEL_MINUS111 0x1F 600 | #define RF_AGCREF_LEVEL_MINUS112 0x20 601 | #define RF_AGCREF_LEVEL_MINUS113 0x21 602 | #define RF_AGCREF_LEVEL_MINUS114 0x22 603 | #define RF_AGCREF_LEVEL_MINUS115 0x23 604 | #define RF_AGCREF_LEVEL_MINUS116 0x24 605 | #define RF_AGCREF_LEVEL_MINUS117 0x25 606 | #define RF_AGCREF_LEVEL_MINUS118 0x26 607 | #define RF_AGCREF_LEVEL_MINUS119 0x27 608 | #define RF_AGCREF_LEVEL_MINUS120 0x28 609 | #define RF_AGCREF_LEVEL_MINUS121 0x29 610 | #define RF_AGCREF_LEVEL_MINUS122 0x2A 611 | #define RF_AGCREF_LEVEL_MINUS123 0x2B 612 | #define RF_AGCREF_LEVEL_MINUS124 0x2C 613 | #define RF_AGCREF_LEVEL_MINUS125 0x2D 614 | #define RF_AGCREF_LEVEL_MINUS126 0x2E 615 | #define RF_AGCREF_LEVEL_MINUS127 0x2F 616 | #define RF_AGCREF_LEVEL_MINUS128 0x30 617 | #define RF_AGCREF_LEVEL_MINUS129 0x31 618 | #define RF_AGCREF_LEVEL_MINUS130 0x32 619 | #define RF_AGCREF_LEVEL_MINUS131 0x33 620 | #define RF_AGCREF_LEVEL_MINUS132 0x34 621 | #define RF_AGCREF_LEVEL_MINUS133 0x35 622 | #define RF_AGCREF_LEVEL_MINUS134 0x36 623 | #define RF_AGCREF_LEVEL_MINUS135 0x37 624 | #define RF_AGCREF_LEVEL_MINUS136 0x38 625 | #define RF_AGCREF_LEVEL_MINUS137 0x39 626 | #define RF_AGCREF_LEVEL_MINUS138 0x3A 627 | #define RF_AGCREF_LEVEL_MINUS139 0x3B 628 | #define RF_AGCREF_LEVEL_MINUS140 0x3C 629 | #define RF_AGCREF_LEVEL_MINUS141 0x3D 630 | #define RF_AGCREF_LEVEL_MINUS142 0x3E 631 | #define RF_AGCREF_LEVEL_MINUS143 0x3F 632 | 633 | 634 | // RegAgcThresh1 - not present on RFM69/SX1231 635 | #define RF_AGCTHRESH1_SNRMARGIN_000 0x00 636 | #define RF_AGCTHRESH1_SNRMARGIN_001 0x20 637 | #define RF_AGCTHRESH1_SNRMARGIN_010 0x40 638 | #define RF_AGCTHRESH1_SNRMARGIN_011 0x60 639 | #define RF_AGCTHRESH1_SNRMARGIN_100 0x80 640 | #define RF_AGCTHRESH1_SNRMARGIN_101 0xA0 // Default 641 | #define RF_AGCTHRESH1_SNRMARGIN_110 0xC0 642 | #define RF_AGCTHRESH1_SNRMARGIN_111 0xE0 643 | 644 | #define RF_AGCTHRESH1_STEP1_0 0x00 645 | #define RF_AGCTHRESH1_STEP1_1 0x01 646 | #define RF_AGCTHRESH1_STEP1_2 0x02 647 | #define RF_AGCTHRESH1_STEP1_3 0x03 648 | #define RF_AGCTHRESH1_STEP1_4 0x04 649 | #define RF_AGCTHRESH1_STEP1_5 0x05 650 | #define RF_AGCTHRESH1_STEP1_6 0x06 651 | #define RF_AGCTHRESH1_STEP1_7 0x07 652 | #define RF_AGCTHRESH1_STEP1_8 0x08 653 | #define RF_AGCTHRESH1_STEP1_9 0x09 654 | #define RF_AGCTHRESH1_STEP1_10 0x0A 655 | #define RF_AGCTHRESH1_STEP1_11 0x0B 656 | #define RF_AGCTHRESH1_STEP1_12 0x0C 657 | #define RF_AGCTHRESH1_STEP1_13 0x0D 658 | #define RF_AGCTHRESH1_STEP1_14 0x0E 659 | #define RF_AGCTHRESH1_STEP1_15 0x0F 660 | #define RF_AGCTHRESH1_STEP1_16 0x10 // Default 661 | #define RF_AGCTHRESH1_STEP1_17 0x11 662 | #define RF_AGCTHRESH1_STEP1_18 0x12 663 | #define RF_AGCTHRESH1_STEP1_19 0x13 664 | #define RF_AGCTHRESH1_STEP1_20 0x14 665 | #define RF_AGCTHRESH1_STEP1_21 0x15 666 | #define RF_AGCTHRESH1_STEP1_22 0x16 667 | #define RF_AGCTHRESH1_STEP1_23 0x17 668 | #define RF_AGCTHRESH1_STEP1_24 0x18 669 | #define RF_AGCTHRESH1_STEP1_25 0x19 670 | #define RF_AGCTHRESH1_STEP1_26 0x1A 671 | #define RF_AGCTHRESH1_STEP1_27 0x1B 672 | #define RF_AGCTHRESH1_STEP1_28 0x1C 673 | #define RF_AGCTHRESH1_STEP1_29 0x1D 674 | #define RF_AGCTHRESH1_STEP1_30 0x1E 675 | #define RF_AGCTHRESH1_STEP1_31 0x1F 676 | 677 | 678 | // RegAgcThresh2 - not present on RFM69/SX1231 679 | #define RF_AGCTHRESH2_STEP2_0 0x00 680 | #define RF_AGCTHRESH2_STEP2_1 0x10 681 | #define RF_AGCTHRESH2_STEP2_2 0x20 682 | #define RF_AGCTHRESH2_STEP2_3 0x30 // XXX wrong -- Default 683 | #define RF_AGCTHRESH2_STEP2_4 0x40 684 | #define RF_AGCTHRESH2_STEP2_5 0x50 685 | #define RF_AGCTHRESH2_STEP2_6 0x60 686 | #define RF_AGCTHRESH2_STEP2_7 0x70 // default 687 | #define RF_AGCTHRESH2_STEP2_8 0x80 688 | #define RF_AGCTHRESH2_STEP2_9 0x90 689 | #define RF_AGCTHRESH2_STEP2_10 0xA0 690 | #define RF_AGCTHRESH2_STEP2_11 0xB0 691 | #define RF_AGCTHRESH2_STEP2_12 0xC0 692 | #define RF_AGCTHRESH2_STEP2_13 0xD0 693 | #define RF_AGCTHRESH2_STEP2_14 0xE0 694 | #define RF_AGCTHRESH2_STEP2_15 0xF0 695 | 696 | #define RF_AGCTHRESH2_STEP3_0 0x00 697 | #define RF_AGCTHRESH2_STEP3_1 0x01 698 | #define RF_AGCTHRESH2_STEP3_2 0x02 699 | #define RF_AGCTHRESH2_STEP3_3 0x03 700 | #define RF_AGCTHRESH2_STEP3_4 0x04 701 | #define RF_AGCTHRESH2_STEP3_5 0x05 702 | #define RF_AGCTHRESH2_STEP3_6 0x06 703 | #define RF_AGCTHRESH2_STEP3_7 0x07 704 | #define RF_AGCTHRESH2_STEP3_8 0x08 705 | #define RF_AGCTHRESH2_STEP3_9 0x09 706 | #define RF_AGCTHRESH2_STEP3_10 0x0A 707 | #define RF_AGCTHRESH2_STEP3_11 0x0B // Default 708 | #define RF_AGCTHRESH2_STEP3_12 0x0C 709 | #define RF_AGCTHRESH2_STEP3_13 0x0D 710 | #define RF_AGCTHRESH2_STEP3_14 0x0E 711 | #define RF_AGCTHRESH2_STEP3_15 0x0F 712 | 713 | 714 | // RegAgcThresh3 - not present on RFM69/SX1231 715 | #define RF_AGCTHRESH3_STEP4_0 0x00 716 | #define RF_AGCTHRESH3_STEP4_1 0x10 717 | #define RF_AGCTHRESH3_STEP4_2 0x20 718 | #define RF_AGCTHRESH3_STEP4_3 0x30 719 | #define RF_AGCTHRESH3_STEP4_4 0x40 720 | #define RF_AGCTHRESH3_STEP4_5 0x50 721 | #define RF_AGCTHRESH3_STEP4_6 0x60 722 | #define RF_AGCTHRESH3_STEP4_7 0x70 723 | #define RF_AGCTHRESH3_STEP4_8 0x80 724 | #define RF_AGCTHRESH3_STEP4_9 0x90 // Default 725 | #define RF_AGCTHRESH3_STEP4_10 0xA0 726 | #define RF_AGCTHRESH3_STEP4_11 0xB0 727 | #define RF_AGCTHRESH3_STEP4_12 0xC0 728 | #define RF_AGCTHRESH3_STEP4_13 0xD0 729 | #define RF_AGCTHRESH3_STEP4_14 0xE0 730 | #define RF_AGCTHRESH3_STEP4_15 0xF0 731 | 732 | #define RF_AGCTHRESH3_STEP5_0 0x00 733 | #define RF_AGCTHRESH3_STEP5_1 0x01 734 | #define RF_AGCTHRESH3_STEP5_2 0x02 735 | #define RF_AGCTHRESH3_STEP5_3 0x03 736 | #define RF_AGCTHRESH3_STEP5_4 0x04 737 | #define RF_AGCTHRESH3_STEP5_5 0x05 738 | #define RF_AGCTHRESH3_STEP5_6 0x06 739 | #define RF_AGCTHRESH3_STEP5_7 0x07 740 | #define RF_AGCTHRES33_STEP5_8 0x08 741 | #define RF_AGCTHRESH3_STEP5_9 0x09 742 | #define RF_AGCTHRESH3_STEP5_10 0x0A 743 | #define RF_AGCTHRESH3_STEP5_11 0x0B // Default 744 | #define RF_AGCTHRESH3_STEP5_12 0x0C 745 | #define RF_AGCTHRESH3_STEP5_13 0x0D 746 | #define RF_AGCTHRESH3_STEP5_14 0x0E 747 | #define RF_AGCTHRESH3_STEP5_15 0x0F 748 | 749 | 750 | // RegLna 751 | #define RF_LNA_ZIN_50 0x00 // Reset value 752 | #define RF_LNA_ZIN_200 0x80 // Recommended default 753 | 754 | #define RF_LNA_LOWPOWER_OFF 0x00 // Default 755 | #define RF_LNA_LOWPOWER_ON 0x40 756 | 757 | #define RF_LNA_CURRENTGAIN 0x08 758 | 759 | #define RF_LNA_GAINSELECT_AUTO 0x00 // Default 760 | #define RF_LNA_GAINSELECT_MAX 0x01 761 | #define RF_LNA_GAINSELECT_MAXMINUS6 0x02 762 | #define RF_LNA_GAINSELECT_MAXMINUS12 0x03 763 | #define RF_LNA_GAINSELECT_MAXMINUS24 0x04 764 | #define RF_LNA_GAINSELECT_MAXMINUS36 0x05 765 | #define RF_LNA_GAINSELECT_MAXMINUS48 0x06 766 | 767 | 768 | // RegRxBw 769 | #define RF_RXBW_DCCFREQ_000 0x00 770 | #define RF_RXBW_DCCFREQ_001 0x20 771 | #define RF_RXBW_DCCFREQ_010 0x40 // Recommended default 772 | #define RF_RXBW_DCCFREQ_011 0x60 773 | #define RF_RXBW_DCCFREQ_100 0x80 // Reset value 774 | #define RF_RXBW_DCCFREQ_101 0xA0 775 | #define RF_RXBW_DCCFREQ_110 0xC0 776 | #define RF_RXBW_DCCFREQ_111 0xE0 777 | 778 | #define RF_RXBW_MANT_16 0x00 // Reset value 779 | #define RF_RXBW_MANT_20 0x08 780 | #define RF_RXBW_MANT_24 0x10 // Recommended default 781 | 782 | #define RF_RXBW_EXP_0 0x00 783 | #define RF_RXBW_EXP_1 0x01 784 | #define RF_RXBW_EXP_2 0x02 785 | #define RF_RXBW_EXP_3 0x03 786 | #define RF_RXBW_EXP_4 0x04 787 | #define RF_RXBW_EXP_5 0x05 // Recommended default 788 | #define RF_RXBW_EXP_6 0x06 // Reset value 789 | #define RF_RXBW_EXP_7 0x07 790 | 791 | 792 | // RegAfcBw 793 | #define RF_AFCBW_DCCFREQAFC_000 0x00 794 | #define RF_AFCBW_DCCFREQAFC_001 0x20 795 | #define RF_AFCBW_DCCFREQAFC_010 0x40 796 | #define RF_AFCBW_DCCFREQAFC_011 0x60 797 | #define RF_AFCBW_DCCFREQAFC_100 0x80 // Default 798 | #define RF_AFCBW_DCCFREQAFC_101 0xA0 799 | #define RF_AFCBW_DCCFREQAFC_110 0xC0 800 | #define RF_AFCBW_DCCFREQAFC_111 0xE0 801 | 802 | #define RF_AFCBW_MANTAFC_16 0x00 803 | #define RF_AFCBW_MANTAFC_20 0x08 // Default 804 | #define RF_AFCBW_MANTAFC_24 0x10 805 | 806 | #define RF_AFCBW_EXPAFC_0 0x00 807 | #define RF_AFCBW_EXPAFC_1 0x01 808 | #define RF_AFCBW_EXPAFC_2 0x02 // Reset value 809 | #define RF_AFCBW_EXPAFC_3 0x03 // Recommended default 810 | #define RF_AFCBW_EXPAFC_4 0x04 811 | #define RF_AFCBW_EXPAFC_5 0x05 812 | #define RF_AFCBW_EXPAFC_6 0x06 813 | #define RF_AFCBW_EXPAFC_7 0x07 814 | 815 | 816 | // RegOokPeak 817 | #define RF_OOKPEAK_THRESHTYPE_FIXED 0x00 818 | #define RF_OOKPEAK_THRESHTYPE_PEAK 0x40 // Default 819 | #define RF_OOKPEAK_THRESHTYPE_AVERAGE 0x80 820 | 821 | #define RF_OOKPEAK_PEAKTHRESHSTEP_000 0x00 // Default 822 | #define RF_OOKPEAK_PEAKTHRESHSTEP_001 0x08 823 | #define RF_OOKPEAK_PEAKTHRESHSTEP_010 0x10 824 | #define RF_OOKPEAK_PEAKTHRESHSTEP_011 0x18 825 | #define RF_OOKPEAK_PEAKTHRESHSTEP_100 0x20 826 | #define RF_OOKPEAK_PEAKTHRESHSTEP_101 0x28 827 | #define RF_OOKPEAK_PEAKTHRESHSTEP_110 0x30 828 | #define RF_OOKPEAK_PEAKTHRESHSTEP_111 0x38 829 | 830 | #define RF_OOKPEAK_PEAKTHRESHDEC_000 0x00 // Default 831 | #define RF_OOKPEAK_PEAKTHRESHDEC_001 0x01 832 | #define RF_OOKPEAK_PEAKTHRESHDEC_010 0x02 833 | #define RF_OOKPEAK_PEAKTHRESHDEC_011 0x03 834 | #define RF_OOKPEAK_PEAKTHRESHDEC_100 0x04 835 | #define RF_OOKPEAK_PEAKTHRESHDEC_101 0x05 836 | #define RF_OOKPEAK_PEAKTHRESHDEC_110 0x06 837 | #define RF_OOKPEAK_PEAKTHRESHDEC_111 0x07 838 | 839 | 840 | // RegOokAvg 841 | #define RF_OOKAVG_AVERAGETHRESHFILT_00 0x00 842 | #define RF_OOKAVG_AVERAGETHRESHFILT_01 0x40 843 | #define RF_OOKAVG_AVERAGETHRESHFILT_10 0x80 // Default 844 | #define RF_OOKAVG_AVERAGETHRESHFILT_11 0xC0 845 | 846 | 847 | // RegOokFix 848 | #define RF_OOKFIX_FIXEDTHRESH_VALUE 0x06 // Default 849 | 850 | 851 | // RegAfcFei 852 | #define RF_AFCFEI_FEI_DONE 0x40 853 | #define RF_AFCFEI_FEI_START 0x20 854 | #define RF_AFCFEI_AFC_DONE 0x10 855 | #define RF_AFCFEI_AFCAUTOCLEAR_ON 0x08 856 | #define RF_AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default 857 | 858 | #define RF_AFCFEI_AFCAUTO_ON 0x04 859 | #define RF_AFCFEI_AFCAUTO_OFF 0x00 // Default 860 | 861 | #define RF_AFCFEI_AFC_CLEAR 0x02 862 | #define RF_AFCFEI_AFC_START 0x01 863 | 864 | 865 | // RegRssiConfig 866 | #define RF_RSSI_FASTRX_ON 0x08 // not present on RFM69/SX1231 867 | #define RF_RSSI_FASTRX_OFF 0x00 // Default 868 | 869 | #define RF_RSSI_DONE 0x02 870 | #define RF_RSSI_START 0x01 871 | 872 | 873 | // RegDioMapping1 874 | #define RF_DIOMAPPING1_DIO0_00 0x00 // Default 875 | #define RF_DIOMAPPING1_DIO0_01 0x40 876 | #define RF_DIOMAPPING1_DIO0_10 0x80 877 | #define RF_DIOMAPPING1_DIO0_11 0xC0 878 | 879 | #define RF_DIOMAPPING1_DIO1_00 0x00 // Default 880 | #define RF_DIOMAPPING1_DIO1_01 0x10 881 | #define RF_DIOMAPPING1_DIO1_10 0x20 882 | #define RF_DIOMAPPING1_DIO1_11 0x30 883 | 884 | #define RF_DIOMAPPING1_DIO2_00 0x00 // Default 885 | #define RF_DIOMAPPING1_DIO2_01 0x04 886 | #define RF_DIOMAPPING1_DIO2_10 0x08 887 | #define RF_DIOMAPPING1_DIO2_11 0x0C 888 | 889 | #define RF_DIOMAPPING1_DIO3_00 0x00 // Default 890 | #define RF_DIOMAPPING1_DIO3_01 0x01 891 | #define RF_DIOMAPPING1_DIO3_10 0x02 892 | #define RF_DIOMAPPING1_DIO3_11 0x03 893 | 894 | 895 | // RegDioMapping2 896 | #define RF_DIOMAPPING2_DIO4_00 0x00 // Default 897 | #define RF_DIOMAPPING2_DIO4_01 0x40 898 | #define RF_DIOMAPPING2_DIO4_10 0x80 899 | #define RF_DIOMAPPING2_DIO4_11 0xC0 900 | 901 | #define RF_DIOMAPPING2_DIO5_00 0x00 // Default 902 | #define RF_DIOMAPPING2_DIO5_01 0x10 903 | #define RF_DIOMAPPING2_DIO5_10 0x20 904 | #define RF_DIOMAPPING2_DIO5_11 0x30 905 | 906 | #define RF_DIOMAPPING2_CLKOUT_32 0x00 907 | #define RF_DIOMAPPING2_CLKOUT_16 0x01 908 | #define RF_DIOMAPPING2_CLKOUT_8 0x02 909 | #define RF_DIOMAPPING2_CLKOUT_4 0x03 910 | #define RF_DIOMAPPING2_CLKOUT_2 0x04 911 | #define RF_DIOMAPPING2_CLKOUT_1 0x05 // Reset value 912 | #define RF_DIOMAPPING2_CLKOUT_RC 0x06 913 | #define RF_DIOMAPPING2_CLKOUT_OFF 0x07 // Recommended default 914 | 915 | 916 | // RegIrqFlags1 917 | #define RF_IRQFLAGS1_MODEREADY 0x80 918 | #define RF_IRQFLAGS1_RXREADY 0x40 919 | #define RF_IRQFLAGS1_TXREADY 0x20 920 | #define RF_IRQFLAGS1_PLLLOCK 0x10 921 | #define RF_IRQFLAGS1_RSSI 0x08 922 | #define RF_IRQFLAGS1_TIMEOUT 0x04 923 | #define RF_IRQFLAGS1_AUTOMODE 0x02 924 | #define RF_IRQFLAGS1_SYNCADDRESSMATCH 0x01 925 | 926 | 927 | // RegIrqFlags2 928 | #define RF_IRQFLAGS2_FIFOFULL 0x80 929 | #define RF_IRQFLAGS2_FIFONOTEMPTY 0x40 930 | #define RF_IRQFLAGS2_FIFOLEVEL 0x20 931 | #define RF_IRQFLAGS2_FIFOOVERRUN 0x10 932 | #define RF_IRQFLAGS2_PACKETSENT 0x08 933 | #define RF_IRQFLAGS2_PAYLOADREADY 0x04 934 | #define RF_IRQFLAGS2_CRCOK 0x02 935 | #define RF_IRQFLAGS2_LOWBAT 0x01 // not present on RFM69/SX1231 936 | 937 | 938 | // RegRssiThresh 939 | #define RF_RSSITHRESH_VALUE 0xE4 // Default 940 | 941 | 942 | // RegRxTimeout1 943 | #define RF_RXTIMEOUT1_RXSTART_VALUE 0x00 // Default 944 | 945 | 946 | // RegRxTimeout2 947 | #define RF_RXTIMEOUT2_RSSITHRESH_VALUE 0x00 // Default 948 | 949 | 950 | // RegPreamble 951 | #define RF_PREAMBLESIZE_MSB_VALUE 0x00 // Default 952 | #define RF_PREAMBLESIZE_LSB_VALUE 0x03 // Default 953 | 954 | 955 | // RegSyncConfig 956 | #define RF_SYNC_ON 0x80 // Default 957 | #define RF_SYNC_OFF 0x00 958 | 959 | #define RF_SYNC_FIFOFILL_AUTO 0x00 // Default -- when sync interrupt occurs 960 | #define RF_SYNC_FIFOFILL_MANUAL 0x40 961 | 962 | #define RF_SYNC_SIZE_1 0x00 963 | #define RF_SYNC_SIZE_2 0x08 964 | #define RF_SYNC_SIZE_3 0x10 965 | #define RF_SYNC_SIZE_4 0x18 // Default 966 | #define RF_SYNC_SIZE_5 0x20 967 | #define RF_SYNC_SIZE_6 0x28 968 | #define RF_SYNC_SIZE_7 0x30 969 | #define RF_SYNC_SIZE_8 0x38 970 | 971 | #define RF_SYNC_TOL_0 0x00 // Default 972 | #define RF_SYNC_TOL_1 0x01 973 | #define RF_SYNC_TOL_2 0x02 974 | #define RF_SYNC_TOL_3 0x03 975 | #define RF_SYNC_TOL_4 0x04 976 | #define RF_SYNC_TOL_5 0x05 977 | #define RF_SYNC_TOL_6 0x06 978 | #define RF_SYNC_TOL_7 0x07 979 | 980 | 981 | // RegSyncValue1-8 982 | #define RF_SYNC_BYTE1_VALUE 0x00 // Default 983 | #define RF_SYNC_BYTE2_VALUE 0x00 // Default 984 | #define RF_SYNC_BYTE3_VALUE 0x00 // Default 985 | #define RF_SYNC_BYTE4_VALUE 0x00 // Default 986 | #define RF_SYNC_BYTE5_VALUE 0x00 // Default 987 | #define RF_SYNC_BYTE6_VALUE 0x00 // Default 988 | #define RF_SYNC_BYTE7_VALUE 0x00 // Default 989 | #define RF_SYNC_BYTE8_VALUE 0x00 // Default 990 | 991 | 992 | // RegPacketConfig1 993 | #define RF_PACKET1_FORMAT_FIXED 0x00 // Default 994 | #define RF_PACKET1_FORMAT_VARIABLE 0x80 995 | 996 | #define RF_PACKET1_DCFREE_OFF 0x00 // Default 997 | #define RF_PACKET1_DCFREE_MANCHESTER 0x20 998 | #define RF_PACKET1_DCFREE_WHITENING 0x40 999 | 1000 | #define RF_PACKET1_CRC_ON 0x10 // Default 1001 | #define RF_PACKET1_CRC_OFF 0x00 1002 | 1003 | #define RF_PACKET1_CRCAUTOCLEAR_ON 0x00 // Default 1004 | #define RF_PACKET1_CRCAUTOCLEAR_OFF 0x08 1005 | 1006 | #define RF_PACKET1_ADRSFILTERING_OFF 0x00 // Default 1007 | #define RF_PACKET1_ADRSFILTERING_NODE 0x02 1008 | #define RF_PACKET1_ADRSFILTERING_NODEBROADCAST 0x04 1009 | 1010 | 1011 | // RegPayloadLength 1012 | #define RF_PAYLOADLENGTH_VALUE 0x40 // Default 1013 | 1014 | 1015 | // RegBroadcastAdrs 1016 | #define RF_BROADCASTADDRESS_VALUE 0x00 1017 | 1018 | 1019 | // RegAutoModes 1020 | #define RF_AUTOMODES_ENTER_OFF 0x00 // Default 1021 | #define RF_AUTOMODES_ENTER_FIFONOTEMPTY 0x20 1022 | #define RF_AUTOMODES_ENTER_FIFOLEVEL 0x40 1023 | #define RF_AUTOMODES_ENTER_CRCOK 0x60 1024 | #define RF_AUTOMODES_ENTER_PAYLOADREADY 0x80 1025 | #define RF_AUTOMODES_ENTER_SYNCADRSMATCH 0xA0 1026 | #define RF_AUTOMODES_ENTER_PACKETSENT 0xC0 1027 | #define RF_AUTOMODES_ENTER_FIFOEMPTY 0xE0 1028 | 1029 | #define RF_AUTOMODES_EXIT_OFF 0x00 // Default 1030 | #define RF_AUTOMODES_EXIT_FIFOEMPTY 0x04 1031 | #define RF_AUTOMODES_EXIT_FIFOLEVEL 0x08 1032 | #define RF_AUTOMODES_EXIT_CRCOK 0x0C 1033 | #define RF_AUTOMODES_EXIT_PAYLOADREADY 0x10 1034 | #define RF_AUTOMODES_EXIT_SYNCADRSMATCH 0x14 1035 | #define RF_AUTOMODES_EXIT_PACKETSENT 0x18 1036 | #define RF_AUTOMODES_EXIT_RXTIMEOUT 0x1C 1037 | 1038 | #define RF_AUTOMODES_INTERMEDIATE_SLEEP 0x00 // Default 1039 | #define RF_AUTOMODES_INTERMEDIATE_STANDBY 0x01 1040 | #define RF_AUTOMODES_INTERMEDIATE_RECEIVER 0x02 1041 | #define RF_AUTOMODES_INTERMEDIATE_TRANSMITTER 0x03 1042 | 1043 | 1044 | // RegFifoThresh 1045 | #define RF_FIFOTHRESH_TXSTART_FIFOTHRESH 0x00 // Reset value 1046 | #define RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY 0x80 // Recommended default 1047 | 1048 | #define RF_FIFOTHRESH_VALUE 0x0F // Default 1049 | 1050 | 1051 | // RegPacketConfig2 1052 | #define RF_PACKET2_RXRESTARTDELAY_1BIT 0x00 // Default 1053 | #define RF_PACKET2_RXRESTARTDELAY_2BITS 0x10 1054 | #define RF_PACKET2_RXRESTARTDELAY_4BITS 0x20 1055 | #define RF_PACKET2_RXRESTARTDELAY_8BITS 0x30 1056 | #define RF_PACKET2_RXRESTARTDELAY_16BITS 0x40 1057 | #define RF_PACKET2_RXRESTARTDELAY_32BITS 0x50 1058 | #define RF_PACKET2_RXRESTARTDELAY_64BITS 0x60 1059 | #define RF_PACKET2_RXRESTARTDELAY_128BITS 0x70 1060 | #define RF_PACKET2_RXRESTARTDELAY_256BITS 0x80 1061 | #define RF_PACKET2_RXRESTARTDELAY_512BITS 0x90 1062 | #define RF_PACKET2_RXRESTARTDELAY_1024BITS 0xA0 1063 | #define RF_PACKET2_RXRESTARTDELAY_2048BITS 0xB0 1064 | #define RF_PACKET2_RXRESTARTDELAY_NONE 0xC0 1065 | #define RF_PACKET2_RXRESTART 0x04 1066 | 1067 | #define RF_PACKET2_AUTORXRESTART_ON 0x02 // Default 1068 | #define RF_PACKET2_AUTORXRESTART_OFF 0x00 1069 | 1070 | #define RF_PACKET2_AES_ON 0x01 1071 | #define RF_PACKET2_AES_OFF 0x00 // Default 1072 | 1073 | 1074 | // RegAesKey1-16 1075 | #define RF_AESKEY1_VALUE 0x00 // Default 1076 | #define RF_AESKEY2_VALUE 0x00 // Default 1077 | #define RF_AESKEY3_VALUE 0x00 // Default 1078 | #define RF_AESKEY4_VALUE 0x00 // Default 1079 | #define RF_AESKEY5_VALUE 0x00 // Default 1080 | #define RF_AESKEY6_VALUE 0x00 // Default 1081 | #define RF_AESKEY7_VALUE 0x00 // Default 1082 | #define RF_AESKEY8_VALUE 0x00 // Default 1083 | #define RF_AESKEY9_VALUE 0x00 // Default 1084 | #define RF_AESKEY10_VALUE 0x00 // Default 1085 | #define RF_AESKEY11_VALUE 0x00 // Default 1086 | #define RF_AESKEY12_VALUE 0x00 // Default 1087 | #define RF_AESKEY13_VALUE 0x00 // Default 1088 | #define RF_AESKEY14_VALUE 0x00 // Default 1089 | #define RF_AESKEY15_VALUE 0x00 // Default 1090 | #define RF_AESKEY16_VALUE 0x00 // Default 1091 | 1092 | 1093 | // RegTemp1 1094 | #define RF_TEMP1_MEAS_START 0x08 1095 | #define RF_TEMP1_MEAS_RUNNING 0x04 1096 | // not present on RFM69/SX1231 1097 | #define RF_TEMP1_ADCLOWPOWER_ON 0x01 // Default 1098 | #define RF_TEMP1_ADCLOWPOWER_OFF 0x00 1099 | 1100 | 1101 | // RegTestLna 1102 | #define RF_TESTLNA_NORMAL 0x1B 1103 | #define RF_TESTLNA_HIGH_SENSITIVITY 0x2D 1104 | 1105 | 1106 | // RegTestDagc 1107 | #define RF_DAGC_NORMAL 0x00 // Reset value 1108 | #define RF_DAGC_IMPROVED_LOWBETA1 0x20 1109 | #define RF_DAGC_IMPROVED_LOWBETA0 0x30 // Recommended default 1110 | --------------------------------------------------------------------------------