From f06e658bf0f161866e397d7f9e26987a055ec967 Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Fri, 29 May 2020 15:05:46 +0200 Subject: [PATCH 01/13] github upload --- WiFi.mpy | Bin 0 -> 1610 bytes WiFi.py | 105 ++++++++++++ boot.py | 3 + cc1101_davis.mpy | Bin 0 -> 7979 bytes cc1101_davis.py | 390 ++++++++++++++++++++++++++++++++++++++++++++ davis_decode.mpy | Bin 0 -> 3139 bytes davis_decode.py | 223 +++++++++++++++++++++++++ inet.conf | 20 +++ influx_structure.md | 158 ++++++++++++++++++ main.py | 89 ++++++++++ readme.md | 371 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 1359 insertions(+) create mode 100644 WiFi.mpy create mode 100644 WiFi.py create mode 100644 boot.py create mode 100644 cc1101_davis.mpy create mode 100644 cc1101_davis.py create mode 100644 davis_decode.mpy create mode 100644 davis_decode.py create mode 100644 inet.conf create mode 100644 influx_structure.md create mode 100644 main.py create mode 100644 readme.md diff --git a/WiFi.mpy b/WiFi.mpy new file mode 100644 index 0000000000000000000000000000000000000000..cc403981ddc1d500fa06ac41c922c731282974e8 GIT binary patch literal 1610 zcmZWp+iu%N5MAoxi+mAD(XWo$(puju}Skldcn=!xwDn_ukWUbv+WHZxl z>a~;>bFsneNX*UBqkX&+^RP?0Qfr_@_*|P>yQvQ)M=_>F)u`2v)%F35=M6HBPhT_fHj~{d#tr|~_aQKI%_W|H_IZp8FIvkHE*9ZJ zktm;s3@G;n0@Xr)%#g;hqI9H| zvGiO;MfH3CyiE8UH(YF9wgWTFya2>kPjJ1Y+C+I!(*^MR3#U+0!m`x5rV&7Lz(T^6 znHqE&XoPnZbH#usHPwVoO^4>80!OOGPO{cgV7Ft;m-SQhUo;wpkH3K}O;;ceYZx=R zt_ig!)D=@dHJ-u0$GCg*)~Dfch~t-+R#sNhg(&FT!MPXcO>Y33xp6KKujx5vZpmt( zf(GKE#d`);h4iSM`k+@KCt5Y*s6Kd#kb{%@;M)p0)@U1bIWIqmfGQ1^{}Mm2-ef3% zMTfci&EYC97Yc7U@BRY<>=$GL^_Zf<2A?bzbH#Nyng~=7W~Zy825W8Dtf|LJ1D>en z;W{depPaovZ>0g681(xOW{*zXcU#+$(7n5>8>__#x4j?X_{b{HqlF*913SnLV@eHG zHq$?&Q#~SSH2h{1xjez63(i)V3FhJ@5Cub9auhz ztHDfs_oVP}|NjKKuSxJae>5RdP83WpnrVk%J3x>(Dt3@SLK_-1_-bgcp}WF?gAy8% zoywO|I#()R_+EnfT=9LdQc4!z_e3|q1$Z0Bl*EKoO~%XVE9YAmIJ&ROl}mT_0xrg@ zIK*(?>(pj$cQ=_WBi)ZgQ2(eJFJ?2@)H>Yi%11~C-44_`SQtEP)s7U1W}>c`rlK34 tT)HN8UDFL5#kmYdv3O{h>hUo=(C~EOK|)uFe>0ce%A}x}*(_su{R{jiyr2L8 literal 0 HcmV?d00001 diff --git a/WiFi.py b/WiFi.py new file mode 100644 index 0000000..2c6408c --- /dev/null +++ b/WiFi.py @@ -0,0 +1,105 @@ +import network +import utime +import machine + +_DEBUG = False + + +class NetSet(object): + + def __init__(self, wifi_type): + self.sta = network.WLAN(network.STA_IF) + self.ap = network.WLAN(network.AP_IF) + if wifi_type == 'infra': + if _DEBUG: + print("Disabling AP") + self.ap.active(False) + if _DEBUG: + print("Activating INFRA") + self.sta.active(True) + self.sta.isconnected() # False, it should be # Comments by Yoda + self._SSID = None + self._PASS = None + self._TIMEOUT = None + elif wifi_type == 'ap': + if _DEBUG: + print("Disabling INFRA") + self.ap.active(True) + if _DEBUG: + print("Activating AP") + self.sta.active(False) + self.sta.isconnected() # False, it should be # Comments by Yoda + self._SSID = None + self._PASS = None + self._TIMEOUT = None + + def connectInfraGo(self, _timeout): + if _DEBUG: + print("Connecting to infra") + self.sta.connect(self._SSID, self._PASS) + if _DEBUG: + print("Let's wait for the network to come up") + while not (self.sta.isconnected()): + if _timeout > 0: + print("Trying... {} more times".format(_timeout)) + utime.sleep_ms(1001) + _timeout -= 1 + else: + print("Out of retrys") + return False + network_config = self.sta.ifconfig() + return network_config + + def connectInfra(self, _SSID, _PASS, _TIMEOUT): + self._SSID = _SSID + self._PASS = _PASS + try: + net_conf_result = self.connectInfraGo(_TIMEOUT) + utime.sleep_ms(100) + if net_conf_result: + return { + 'ip': net_conf_result[0], + 'mask': net_conf_result[1], + 'gw': net_conf_result[2], + 'dns': net_conf_result[3] } + else: + return False + except Exception as e: + print("ERROR: Network configuration failed with: {}".format(e)) + return False + + def connectAp(self): + # TBI + pass + + def readNetworkConfig(self): + self.config_dict = {} + try: + with open('inet.conf', 'r') as conf_handler: + for item in conf_handler.readlines(): + option = item.split("=")[0].strip() + if len(item.split("=")) == 2 and '#' not in option: + value = item.split("=")[1].strip() + self.config_dict.update({option: value}) + else: + if _DEBUG: + if '#' in option: + print(b"COMMENT in config") + else: + print(b"WARNING: Fucked up option, make it better") + except Exception as e: + if _DEBUG: + print("WARNING: Errors in INFRA config, still going for AP") + return False + if _DEBUG: + print("CONFIG DICT: {}".format(self.config_dict)) + self._SSID = self.config_dict['_SSID'] + self._PASS = self.config_dict['_PASS'] + self._TIMEOUT = int(self.config_dict['_TIMEOUT']) + self._INFLUX_HOST = self.config_dict['_INFLUX_HOST'] + self._INFLUX_PORT = self.config_dict['_INFLUX_PORT'] + self._INFLUX_USER = self.config_dict['_INFLUX_USER'] + self._INFLUX_PASS = self.config_dict['_INFLUX_PASS'] + self._INF_DB_WEATHER = self.config_dict['_INF_DB_WEATHER'] + self._INF_DB_STATUS = self.config_dict['_INF_DB_STATUS'] + self._INF_DB_RAW = self.config_dict['_INF_DB_RAW'] diff --git a/boot.py b/boot.py new file mode 100644 index 0000000..fea6b0e --- /dev/null +++ b/boot.py @@ -0,0 +1,3 @@ +# This file is executed on every boot (including wake-boot from deepsleep) +import gc +gc.collect() diff --git a/cc1101_davis.mpy b/cc1101_davis.mpy new file mode 100644 index 0000000000000000000000000000000000000000..384f59a96e24619aeabb63b1b75a16107dfd542e GIT binary patch literal 7979 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 literal 0 HcmV?d00001 diff --git a/cc1101_davis.py b/cc1101_davis.py new file mode 100644 index 0000000..35a022d --- /dev/null +++ b/cc1101_davis.py @@ -0,0 +1,390 @@ +import utime +import gc +import machine + +ss = machine.Pin(15,machine.Pin.OUT) # Chip select / HCS +so = machine.Pin(12) # HMISO +si = machine.Pin(13) # HMOSI +sck = machine.Pin(14) # HSCLK +interrupt = machine.Pin(2) # Interrupt for packet available + +gc.collect() + +class CC1101(object): + def __init__(self): + self.debug = 1 + self.hspi = machine.SPI(1, baudrate=600000, polarity=0, phase=0) + self.PA_TABLE = [0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0] + + self.FREQ_2 = [0x21, 0x21, 0x21, 0x21, 0x21] + self.FREQ_1 = [0x62, 0x65, 0x67, 0x64, 0x66] + self.FREQ_0 = [0xE2, 0x40, 0x9D, 0x11, 0x6F] + + self.CRC_TABLE = [ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0] + self.BUFFER_SIZE = 16 + self.DAVIS_PACKET_LENGTH = 10 + self.rxBuffer = [] + self.rxBufferIndex = 0 + self.rxBufferLength = 0 + self.hopIndex = 0 + self.freqComp = [0, 0, 0, 0, 0] + + # CC1101 Transfer Types. + self.WRITE_BURST = 0x40 + self.READ_SINGLE = 0x80 + self.READ_BURST = 0xC0 + + # Davis Register Configuration Settings. + self.DAVIS_IOCFG2 = 0x2E # GDO2 Output Pin Configuration + self.DAVIS_IOCFG1 = 0x2E # GDO1 Output Pin Configuration + self.DAVIS_IOCFG0 = 0x01 # GDO0 Output Pin Configuration + self.DAVIS_FIFOTHR = 0x42 # RX FIFO and TX FIFO Thresholds + self.DAVIS_SYNC1 = 0xCB # Synchronization word, high byte + self.DAVIS_SYNC0 = 0x89 # Synchronization word, low byte + self.DAVIS_PKTLEN = 0x0A # Packet Length + self.DAVIS_PKTCTRL1 = 0xC4 # Packet Automation Control + self.DAVIS_PKTCTRL0 = 0x00 # Packet Automation Control + self.DAVIS_ADDR = 0x00 # Device Address + self.DAVIS_CHANNR = 0x00 # Channel Number + self.DAVIS_FSCTRL1 = 0x06 # Frequency Synthesizer Control + self.DAVIS_FSCTRL0 = 0xF0 # Frequency Synthesizer Control + self.DAVIS_FREQ2 = 0x23 # Frequency Control Word, High Byte + self.DAVIS_FREQ1 = 0x0D # Frequency Control Word, Middle Byte + self.DAVIS_FREQ0 = 0x97 # Frequency Control Word, Low Byte + self.DAVIS_MDMCFG4 = 0xC9 # Modem Configuration + self.DAVIS_MDMCFG3 = 0x83 # Modem Configuration + self.DAVIS_MDMCFG2 = 0x12 # Modem Configuration + self.DAVIS_MDMCFG1 = 0x21 # Modem Configuration + self.DAVIS_MDMCFG0 = 0xF9 # Modem Configuration + self.DAVIS_DEVIATN = 0x24 # Modem Deviation Setting + self.DAVIS_MCSM2 = 0x07 # Main Radio Control State Machine Configuration + self.DAVIS_MCSM1 = 0x00 # Main Radio Control State Machine Configuration + self.DAVIS_MCSM0 = 0x18 # Main Radio Control State Machine Configuration + self.DAVIS_FOCCFG = 0x16 # Frequency Offset Compensation Configuration + self.DAVIS_BSCFG = 0x6C # Bit Synchronization Configuration + self.DAVIS_AGCCTRL2 = 0x43 # AGC Control + self.DAVIS_AGCCTRL1 = 0x40 # AGC Control + self.DAVIS_AGCCTRL0 = 0x91 # AGC Control + self.DAVIS_WOREVT1 = 0x87 # High Byte Event0 Timeout + self.DAVIS_WOREVT0 = 0x6B # Low Byte Event0 Timeout + self.DAVIS_WORCTRL = 0xF8 # Wake On Radio Control + self.DAVIS_FREND1 = 0x56 # Front End RX Configuration + self.DAVIS_FREND0 = 0x10 # Front End TX Configuration + self.DAVIS_FSCAL3 = 0xEF # Frequency Synthesizer Calibration + self.DAVIS_FSCAL2 = 0x2B # Frequency Synthesizer Calibration + self.DAVIS_FSCAL1 = 0x2F # Frequency Synthesizer Calibration + self.DAVIS_FSCAL0 = 0x1F # Frequency Synthesizer Calibration + self.DAVIS_RCCTRL1 = 0x00 # RC Oscillator Configuration + self.DAVIS_RCCTRL0 = 0x00 # RC Oscillator Configuration + self.DAVIS_FSTEST = 0x59 # Frequency Synthesizer Calibration Control + self.DAVIS_PTEST = 0x7F # Production Test + self.DAVIS_AGCTEST = 0x3F # AGC Test + self.DAVIS_TEST2 = 0x81 # Various Test Settings + self.DAVIS_TEST1 = 0x35 # Various Test Settings + self.DAVIS_TEST0 = 0x09 # Various Test Settings + + self.CC1101_IOCFG2 = 0x00 # GDO2 Output Pin Configuration + self.CC1101_IOCFG1 = 0x01 # GDO1 Output Pin Configuration + self.CC1101_IOCFG0 = 0x02 # GDO0 Output Pin Configuration + self.CC1101_FIFOTHR = 0x03 # RX FIFO and TX FIFO Thresholds + self.CC1101_SYNC1 = 0x04 # Sync Word, High Byte + self.CC1101_SYNC0 = 0x05 # Sync Word, Low Byte + self.CC1101_PKTLEN = 0x06 # Packet Length + self.CC1101_PKTCTRL1 = 0x07 # Packet Automation Control + self.CC1101_PKTCTRL0 = 0x08 # Packet Automation Control + self.CC1101_ADDR = 0x09 # Device Address + self.CC1101_CHANNR = 0x0A # Channel Number + self.CC1101_FSCTRL1 = 0x0B # Frequency Synthesizer Control + self.CC1101_FSCTRL0 = 0x0C # Frequency Synthesizer Control + self.CC1101_FREQ2 = 0x0D # Frequency Control Word, High Byte + self.CC1101_FREQ1 = 0x0E # Frequency Control Word, Middle Byte + self.CC1101_FREQ0 = 0x0F # Frequency Control Word, Low Byte + self.CC1101_MDMCFG4 = 0x10 # Modem Configuration + self.CC1101_MDMCFG3 = 0x11 # Modem Configuration + self.CC1101_MDMCFG2 = 0x12 # Modem Configuration + self.CC1101_MDMCFG1 = 0x13 # Modem Configuration + self.CC1101_MDMCFG0 = 0x14 # Modem Configuration + self.CC1101_DEVIATN = 0x15 # Modem Deviation Setting + self.CC1101_MCSM2 = 0x16 # Main Radio Control State Machine Configuration + self.CC1101_MCSM1 = 0x17 # Main Radio Control State Machine Configuration + self.CC1101_MCSM0 = 0x18 # Main Radio Control State Machine Configuration + self.CC1101_FOCCFG = 0x19 # Frequency Offset Compensation Configuration + self.CC1101_BSCFG = 0x1A # Bit Synchronization Configuration + self.CC1101_AGCCTRL2 = 0x1B # AGC Control + self.CC1101_AGCCTRL1 = 0x1C # AGC Control + self.CC1101_AGCCTRL0 = 0x1D # AGC Control + self.CC1101_WOREVT1 = 0x1E # High Byte Event0 Timeout + self.CC1101_WOREVT0 = 0x1F # Low Byte Event0 Timeout + self.CC1101_WORCTRL = 0x20 # Wake On Radio Control + self.CC1101_FREND1 = 0x21 # Front End RX Configuration + self.CC1101_FREND0 = 0x22 # Front End TX Configuration + self.CC1101_FSCAL3 = 0x23 # Frequency Synthesizer Calibration + self.CC1101_FSCAL2 = 0x24 # Frequency Synthesizer Calibration + self.CC1101_FSCAL1 = 0x25 # Frequency Synthesizer Calibration + self.CC1101_FSCAL0 = 0x26 # Frequency Synthesizer Calibration + self.CC1101_RCCTRL1 = 0x27 # RC Oscillator Configuration + self.CC1101_RCCTRL0 = 0x28 # RC Oscillator Configuration + self.CC1101_FSTEST = 0x29 # Frequency Synthesizer Calibration Control + self.CC1101_PTEST = 0x2A # Production Test + self.CC1101_AGCTEST = 0x2B # AGC Test + self.CC1101_TEST2 = 0x2C # Various Test Settings + self.CC1101_TEST1 = 0x2D # Various Test Settings + self.CC1101_TEST0 = 0x2E # Various Test Settings + + # CC1101 Status Registers. + self.CC1101_PARTNUM = 0x30 # Chip ID + self.CC1101_VERSION = 0x31 # Chip ID + self.CC1101_FREQEST = 0x32 # Frequency Offset Estimate from Demodulator + self.CC1101_LQI = 0x33 # Demodulator Estimate for Link Quality + self.CC1101_RSSI = 0x34 # Received Signal Strength Indication + self.CC1101_MARCSTATE = 0x35 # Main Radio Control State Machine State + self.CC1101_WORTIME1 = 0x36 # High Byte of WOR Time + self.CC1101_WORTIME0 = 0x37 # Low Byte of WOR Time + self.CC1101_PKTSTATUS = 0x38 # Current GDOx Status and Packet Status + self.CC1101_VCO_VC_DAC = 0x39 # Current Setting from PLL Calibration Module + self.CC1101_TXBYTES = 0x3A # Underflow and Number of Bytes + self.CC1101_RXBYTES = 0x3B # Overflow and Number of Bytes + self.CC1101_RCCTRL1_STATUS = 0x3C # Last RC Oscillator Calibration Result + self.CC1101_RCCTRL0_STATUS = 0x3D # Last RC Oscillator Calibration Result + + # CC1101 PA Table, TX FIFO and RX FIFO. + self.CC1101_PATABLE = 0x3E # PA TABLE address + self.CC1101_TXFIFO = 0x3F # TX FIFO address + self.CC1101_RXFIFO = 0x3F # RX FIFO address + + # CC1101 Command Strobes. + self.CC1101_SRES = 0x30 # Reset CC1101 chip + self.CC1101_SFSTXON = 0x31 # Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL = 1). If in RX (with CCA): + # Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). + self.CC1101_SXOFF = 0x32 # Turn off crystal oscillator + self.CC1101_SCAL = 0x33 # Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without + # setting manual calibration mode (MCSM0.FS_AUTOCAL = 0) + self.CC1101_SRX = 0x34 # Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL = 1 + self.CC1101_STX = 0x35 # In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL = 1. + # If in RX state and CCA is enabled: Only go to TX if channel is clear + self.CC1101_SIDLE = 0x36 # Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable + self.CC1101_SWOR = 0x38 # Start automatic RX polling sequence (Wake-on-Radio) if WORCTRL.RC_PD = 0 + self.CC1101_SPWD = 0x39 # Enter power down mode when CSn goes high + self.CC1101_SFRX = 0x3A # Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states + self.CC1101_SFTX = 0x3B # Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states + self.CC1101_SWORRST = 0x3C # Reset real time clock to Event1 value + self.CC1101_SNOP = 0x3D # No operation. May be used to get access to the chip status byte + + # CC1101 Transfer Types. + self.WRITE_BURST = 0x40 + self.READ_SINGLE = 0x80 + self.READ_BURST = 0xC0 + + # CC1101 Returned Status Bytes. + self.CC1101_STATE_IDLE = 0x01 + self.CC1101_STATE_ENDCAL = 0x0C + self.CC1101_STATE_RX = 0x0D + self.CC1101_STATE_RXFIFO_ERROR = 0x11 + self.CC1101_STATE_TX = 0x13 + self.CC1101_STATE_TX_END = 0x14 + self.CC1101_STATE_TXFIFO_ERROR = 0x16 + self.reset() + self.setRegisters() + for i in range(0, 5): + self.freqComp[i] = self.DAVIS_FSCTRL0 + + def readRegister(self, regAddr): + addr = regAddr | self.READ_SINGLE + ss.off() + read_addr = bytes([addr]) + self.hspi.write(read_addr) + val = self.hspi.read(1, 0x00) + ss.on() + return int(val[0]) + + def writeRegister(self, regAddr, value): + ss.off() + self.hspi.write(bytes([regAddr])) + self.hspi.write(bytes([value])) + ss.on() + + def writeBurst(self, regAddr, wr_buffer): + addr = regAddr | self.WRITE_BURST + ss.off() + self.hspi.write(bytes([addr])) + for contents in wr_buffer: + self.hspi.write(bytes([contents])) + ss.on() + + def readBurst(self, regAddr, size): + addr = regAddr | self.READ_BURST + ss.off() + self.hspi.write(bytes([addr])) + rd_buffer = [] + for i in range(0, size): + rd_result = self.hspi.read(1, 0x00) + rd_buffer.append(hex(rd_result[0])) + ss.on() + return rd_buffer + + def cmdStrobe(self, command): + ss.off() + self.hspi.write(bytes([command])) + ss.on() + + def readStatus(self, regAddr): + addr = regAddr | self.READ_BURST + ss.off() + self.hspi.write(bytes([addr])) + value = self.hspi.read(1, 0x00) + ss.on() + return int(value[0]) + + def reset(self): + ss.off() + utime.sleep_ms(1) + ss.on() + utime.sleep_ms(1) + ss.off() + while so.value(): + pass + self.hspi.write(bytes([self.CC1101_SRES])) + while so.value(): + pass + ss.on() + + def sidle(self): + self.cmdStrobe(self.CC1101_SIDLE) + while self.readStatus(self.CC1101_MARCSTATE) != 0x01: + utime.sleep_us(100) + self.cmdStrobe(self.CC1101_SFTX) + self.cmdStrobe(self.CC1101_SFRX) + utime.sleep_us(100) + + def setRegisters(self): + self.writeRegister(self.CC1101_IOCFG2, self.DAVIS_IOCFG2) + self.writeRegister(self.CC1101_IOCFG1, self.DAVIS_IOCFG1) + self.writeRegister(self.CC1101_IOCFG0, self.DAVIS_IOCFG0) + self.writeRegister(self.CC1101_FIFOTHR, self.DAVIS_FIFOTHR) + self.writeRegister(self.CC1101_SYNC1, self.DAVIS_SYNC1) + self.writeRegister(self.CC1101_SYNC0, self.DAVIS_SYNC0) + self.writeRegister(self.CC1101_PKTLEN, self.DAVIS_PKTLEN) + self.writeRegister(self.CC1101_PKTCTRL1, self.DAVIS_PKTCTRL1) + self.writeRegister(self.CC1101_PKTCTRL0, self.DAVIS_PKTCTRL0) + self.writeRegister(self.CC1101_ADDR, self.DAVIS_ADDR) + self.writeRegister(self.CC1101_CHANNR, self.DAVIS_CHANNR) + self.writeRegister(self.CC1101_FSCTRL1, self.DAVIS_FSCTRL1) + self.writeRegister(self.CC1101_FSCTRL0, self.DAVIS_FSCTRL0) + self.writeRegister(self.CC1101_FREQ2, self.DAVIS_FREQ2) + self.writeRegister(self.CC1101_FREQ1, self.DAVIS_FREQ1) + self.writeRegister(self.CC1101_FREQ0, self.DAVIS_FREQ0) + self.writeRegister(self.CC1101_MDMCFG4, self.DAVIS_MDMCFG4) + self.writeRegister(self.CC1101_MDMCFG3, self.DAVIS_MDMCFG3) + self.writeRegister(self.CC1101_MDMCFG2, self.DAVIS_MDMCFG2) + self.writeRegister(self.CC1101_MDMCFG1, self.DAVIS_MDMCFG1) + self.writeRegister(self.CC1101_MDMCFG0, self.DAVIS_MDMCFG0) + self.writeRegister(self.CC1101_DEVIATN, self.DAVIS_DEVIATN) + self.writeRegister(self.CC1101_MCSM2, self.DAVIS_MCSM2) + self.writeRegister(self.CC1101_MCSM1, self.DAVIS_MCSM1) + self.writeRegister(self.CC1101_MCSM0, self.DAVIS_MCSM0) + self.writeRegister(self.CC1101_FOCCFG, self.DAVIS_FOCCFG) + self.writeRegister(self.CC1101_BSCFG, self.DAVIS_BSCFG) + self.writeRegister(self.CC1101_AGCCTRL2, self.DAVIS_AGCCTRL2) + self.writeRegister(self.CC1101_AGCCTRL1, self.DAVIS_AGCCTRL1) + self.writeRegister(self.CC1101_AGCCTRL0, self.DAVIS_AGCCTRL0) + self.writeRegister(self.CC1101_WOREVT1, self.DAVIS_WOREVT1) + self.writeRegister(self.CC1101_WOREVT0, self.DAVIS_WOREVT0) + self.writeRegister(self.CC1101_WORCTRL, self.DAVIS_WORCTRL) + self.writeRegister(self.CC1101_FREND1, self.DAVIS_FREND1) + self.writeRegister(self.CC1101_FREND0, self.DAVIS_FREND0) + self.writeRegister(self.CC1101_FSCAL3, self.DAVIS_FSCAL3) + self.writeRegister(self.CC1101_FSCAL2, self.DAVIS_FSCAL2) + self.writeRegister(self.CC1101_FSCAL1, self.DAVIS_FSCAL1) + self.writeRegister(self.CC1101_FSCAL0, self.DAVIS_FSCAL0) + self.writeRegister(self.CC1101_RCCTRL1, self.DAVIS_RCCTRL1) + self.writeRegister(self.CC1101_RCCTRL0, self.DAVIS_RCCTRL0) + self.writeRegister(self.CC1101_FSTEST, self.DAVIS_FSTEST) + self.writeRegister(self.CC1101_PTEST, self.DAVIS_PTEST) + self.writeRegister(self.CC1101_AGCTEST, self.DAVIS_AGCTEST) + self.writeRegister(self.CC1101_TEST2, self.DAVIS_TEST2) + self.writeRegister(self.CC1101_TEST1, self.DAVIS_TEST1) + self.writeRegister(self.CC1101_TEST0, self.DAVIS_TEST0) + self.writeBurst(self.CC1101_PATABLE, self.PA_TABLE) + self.setFrequency(self.hopIndex) + + def flush(self): + self.sidle() + self.cmdStrobe(self.CC1101_SFRX) # Flush Rx FIFO + self.cmdStrobe(self.CC1101_SFTX) # Flush Tx FIFO + self.rxBuffer = [0x00] * self.BUFFER_SIZE + self.rxBufferLength = self.rxBufferIndex = 0 + + def rx(self): + self.cmdStrobe(self.CC1101_SRX) + while (self.readStatus(self.CC1101_MARCSTATE) & 0x1F) != self.CC1101_STATE_RX: + utime.sleep_us(900) + self.rxing = 1 + self.writeRegister(self.CC1101_IOCFG0, self.DAVIS_IOCFG0) + + def hop(self): + self.hopIndex += 1 # Increment the index + if (self.hopIndex > 4): # 5 EU frequencies + self.hopIndex = 0 + self.writeRegister(self.CC1101_FSCTRL0, self.freqComp[self.hopIndex]) + self.setFrequency(self.hopIndex) # Set the frequency. + + def setFrequency(self, index): + self.sidle() + self.writeRegister(self.CC1101_FREQ2, self.FREQ_2[index]) + self.writeRegister(self.CC1101_FREQ1, self.FREQ_1[index]) + self.writeRegister(self.CC1101_FREQ0, self.FREQ_0[index]) + self.flush() + + def calcCrc(self, _buffer, length): + crc = 0x0000 + buffer_index = 0 + for i in range(length, 0, -1): + crc = (crc << 8) ^ self.CRC_TABLE[(crc >> 8) ^ (_buffer[buffer_index])] + buffer_index += 1 + return crc + + def readRssi(self): + rssi = self.readRegister(self.CC1101_RXFIFO) + if rssi >= 128: + return (rssi - 256)/2 - 74 + elif rssi < 128: + return rssi/2 -74 + else: + return False + + def readLQI(self): + return self.readRegister(self.CC1101_RXFIFO) & 0x7F + diff --git a/davis_decode.mpy b/davis_decode.mpy new file mode 100644 index 0000000000000000000000000000000000000000..d297958fbeec74dd196ec055c7a744153cee8d95 GIT binary patch literal 3139 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 4 + lsb = data & 0b00001111 + result = {"MSB": msb, "LSB": lsb} + return result + + def davis_id(self, header): + self.davis_packet_id = 0 + self.battery_low = 0 + self.unit_id = 0 + bin_header = self.byte_split(header) + self.unit_id = bin_header['LSB'] & 0b0111 + self.battery_low = bin_header['LSB'] >> 3 + self.davis_packet_id = bin_header['MSB'] + result = {"davis_id": self.unit_id, + "packet_id": self.davis_packet_id, + "bat_low": self.battery_low} + return result + + def decode_wind(self, databytes): + # wind speed in mph, i suppose. Let's convert it + wind_speed = round(float(databytes['windspeed'] * 1.60934), 1) + wind_direction_factor = round(float(360)/float(255), 1) + wind_direction = databytes['winddir'] + wind_direction = float(wind_direction) * wind_direction_factor + result = {"speed": wind_speed, "direction": wind_direction} + return result + + def decode_temp(self, temp): + temp_f = (float(temp)) / float(160) # in Fahrenheit + temp_c = round((temp_f - 32) * float(5)/float(9), 1) + result = {"celsius": temp_c, "fahrenheit": temp_f} + return result + + def decode_humidity(self, hum): + pass + + def supercap_decode(self, byte2, byte3): + cap = (byte2 << 2) + (byte3 >> 6) + result = float(cap / 100.00) + return result + + def solarvolt_decode(self, byte2, byte3): + solar = (byte2 << 1) + (byte3 >> 7) + result = float(solar) + return result + + def rain_decode(self, rain): + result = float(rain & 0x7F) + return result + + def rainrate_decode(self, byte2, byte3): + # if byte3(b2 here) is 0xFF, or 255, there is no rain + #print("b2:{} b3:{} = result:{}".format(byte2, byte3, byte2 + (byte3 >> 4 << 8))) + if byte2 == 255: + rainstate = 0 + rainrate = 0 + elif byte2 == 254: + rainstate = 1 + rainrate = 0.2 + else: + rainstate = 2 + if byte3 > 4: + rainrate = 720 / ((byte3 >> 4 << 8) + byte2) + else: + rainrate = 0 + result = {"state": float(rainstate), "rate": float(rainrate)} + #print(result) + return result + + def DecodePacket(self, packet): + # By default and most of the time, write to weather + self.write_influx_db = self.weather_influx_db + # Set all to None + self.wind = False + self.measurement = False + self.name = False + self.value = False + self.tags = False + self.wind = self.decode_wind( + {"windspeed": packet[1], "winddir": packet[2]}) + if self.davis_packet_id == 2: + # SuperCap charge 0x2 + if _DEBUG: + print('SCAP:') + supercap = self.supercap_decode( + packet[3], packet[4] + ) + if _DEBUG: + print("{}".format(supercap)) + self.write_influx_db = self.stat_influx_db + self.measurement = 'iss' + self.name = 'voltage' + self.tags = {'type': 'capacitor'} + self.value = supercap + elif self.davis_packet_id == 3: + # No fucking idea 0x3 + # {'hop':1,'h':48,'b0':6,'b1':237,'b2':255,'b3':195,'b4':135,'b5':50,'b6':110,'b7':255,'b8':255,'b9':179,'rssi':45,'lqi':0,'nxt':64,'cnt':163} + self.measurement = None + self.name = None + self.tags = None + self.value = None + + elif self.davis_packet_id == 5: + # Rainrate 0x5 + rainrate_dict = self.rainrate_decode( + packet[3], + packet[4]) + if _DEBUG: + print("RAINRATE: {}".format(rainrate_dict)) + self.measurement = 'rain' + self.name = 'value' + self.tags = {'type': 'rainrate'} + self.value = rainrate_dict['rate'] + elif self.davis_packet_id == 6: + # Sun Irradiation 0x6 (NOT ON vantage Vue) + pass + elif self.davis_packet_id == 7: + # Super Cap voltage 0x7 + solarvolt = self.solarvolt_decode( + packet[3], packet[4] + ) + if _DEBUG: + print("SOLV {}".format(solarvolt)) + self.write_influx_db = self.stat_influx_db + self.measurement = 'iss' + self.name = 'voltage' + self.tags = {'type': 'solar'} + self.value = solarvolt + elif self.davis_packet_id == 8: + # Temperature 0x8 + raw_temp = (packet[3] << 8) + packet[4] + temp_dict = self.decode_temp(raw_temp) + temp = float(temp_dict['celsius']) + if _DEBUG: + print("TEMP: {}".format(temp)) + self.measurement = 'temphumi' + self.name = 'temperature' + self.tags = {'type': 'external'} + self.value = temp + elif self.davis_packet_id == 9: + # Wind gusts 0x9 + windgust = packet[3] * 1.60934 + if _DEBUG: + print("WINDGUST: {}".format(windgust)) + self.measurement = 'wind' + self.name = 'value' + self.tags = {'type': 'windgust'} + self.value = windgust + elif self.davis_packet_id == 10: + # Humidity 0xa + raw_humidity = (((packet[4] >> 4) & 0b0011) << 8) \ + + packet[3] + humidity = round(int(raw_humidity) / float(10), 1) + if _DEBUG: + print("HUMI: {}".format(humidity)) + self.measurement = 'temphumi' + self.name = 'humidity' + self.tags = {'type': 'external'} + self.value = humidity + elif self.davis_packet_id == 14: + # Rain bucket tips 0xe + raw_rain = (packet[3]) + (packet[4] >> 7 << 8) + rain = self.rain_decode(raw_rain) + if _DEBUG: + print("RAINCOUNT: {}".format(rain)) + self.measurement = 'rain' + self.name = 'value' + self.tags = {'type': 'rain_bucket_tips'} + self.value = rain + diff --git a/inet.conf b/inet.conf new file mode 100644 index 0000000..8db3f0d --- /dev/null +++ b/inet.conf @@ -0,0 +1,20 @@ +# No spaces around '=' +# Try to avoid spaced at end or beginning of passwords. Stripping it +# One config option per line, all options need to be set. + +_SSID=YourSSID +_PASS=YourWifiPass + +# Time to keep waiting for the network to come up. Delay is 1001ms +_TIMEOUT=15 +_INFLUX_HOST=IPofTheInfluxDB +_INFLUX_PORT=PortOfTheInfluxDB + +# currently not implemented +_INFLUX_USER=InfluxUser +_INFLUX_PASS=HisPasswd + +# Names of the databases +_INF_DB_WEATHER=weather +_INF_DB_STATUS=status +_INF_DB_RAW=raw diff --git a/influx_structure.md b/influx_structure.md new file mode 100644 index 0000000..422fdee --- /dev/null +++ b/influx_structure.md @@ -0,0 +1,158 @@ +#Structure of InfluxDB +InfluxDB was chosen for it's simplicity and ease of management, live with it. + +##influxDB SCHEMA: +Firs off, 2 databases: + weather + status + +###DB weather + measure wind + ---------------- + value | speed or direction or windgust | davis_id + --------------------------------------------------- + field tag tag + + measure temphumi + ---------------- + temperature | humidity | external, internal | davis_id + --------------------------------------------------------- + field field tag tag + + measure rain + ---------------- + rain | rate / total / intensity | davis_id + --------------------------------------------- + field tag tag + + + +###DB status + + iss measure + ---------------- + voltage | solar or capacitor + ---------------------------------------------------------------- + field tag + + RasPI system (only on the raspi system) + ---------------- + usage | disk, mem, cpu, eth, wifi % + ------------------------------------ + field | tag + +## Retention policies + ------- + weather + ------- + create retention policy realtime on weather duration 168h replication 1 shard duration 1h + create retention policy monthly on weather duration 720h replication 1 shard duration 24h + create retention policy yearly on weather duration 8760h replication 1 shard duration 168h + create retention policy infinite on weather duration 0s replication 1 shard duration 720h + alter retention policy realtime on weather default + + ------ + status + ------ + create retention policy realtime on status duration 168h replication 1 shard duration 1h + create retention policy monthly on status duration 720h replication 1 shard duration 24h + create retention policy yearly on status duration 8760h replication 1 shard duration 168h + create retention policy infinite on status duration 0s replication 1 shard duration 720h + alter retention policy realtime on status default + +## Continuous queries + ------------------------------------------------------------------------------- + WIND + ------------------------------------------------------------------------------- + CREATE CONTINUOUS QUERY "cq_wind_10m" ON "weather_v2" BEGIN + SELECT max(value) AS wind_max, mean(value) AS wind, min(value) AS wind_min + INTO "monthly"."wind_aggregated" + FROM realtime.wind + GROUP BY time(10m), type + END + CREATE CONTINUOUS QUERY "cq_wind_1h" ON "weather_v2" BEGIN + SELECT max(value) AS wind_max, mean(value) AS wind, min(value) AS wind_min + INTO "yearly"."wind_aggregated" + FROM realtime.wind + GROUP BY time(1h), type + END + CREATE CONTINUOUS QUERY "cq_wind_6h" ON "weather_v2" BEGIN + SELECT max(value) AS wind_max, mean(value) AS wind, min(value) AS wind_min + INTO "infinite"."wind_aggregated" + FROM realtime.wind + GROUP BY time(6h), type + END + + ------------------------------------------------------------------------------- + RAIN + ------------------------------------------------------------------------------- + CREATE CONTINUOUS QUERY "cq_rain_10m" ON "weather_v2" BEGIN + SELECT max("value") AS val_max, mean(value) AS value + INTO "monthly"."rainrate_aggregated" + FROM realtime.rain + GROUP BY type,time(10m) + END + CREATE CONTINUOUS QUERY "cq_rain_1h" ON "weather_v2" BEGIN + SELECT max("value") AS val_max, mean(value) AS value + INTO "yearly"."rainrate_aggregated" + FROM realtime.rain + GROUP BY type,time(1h) + END + CREATE CONTINUOUS QUERY "cq_rain_6h" ON "weather_v2" BEGIN + SELECT max("value") AS val_max, mean(value) AS value + INTO "infinite"."rainrate_aggregated" + FROM realtime.rain + GROUP BY type,time(6h) + END + ------------------------------------------------------------------------------- + TEMPHUMI + ------------------------------------------------------------------------------- + CREATE CONTINUOUS QUERY "cq_temphumi_10m" ON "weather_v2" BEGIN + SELECT + max("humidity") AS humidity_max, + min("humidity") AS humidity_min, + mean("humidity") AS humidity, + max("temperature") AS temperature_max, + min("temperature") AS temperature_min, + mean("temperature") AS temperature + INTO "monthly"."temphumi_aggregated" + FROM realtime.temphumi + GROUP BY type, time(10m) + END + + CREATE CONTINUOUS QUERY "cq_temphumi_1h" ON "weather_v2" BEGIN + SELECT + max("humidity") AS humidity_max, + min("humidity") AS humidity_min, + mean("humidity") AS humidity, + max("temperature") AS temperature_max, + min("temperature") AS temperature_min, + mean("temperature") AS temperature + INTO "yearly"."temphumi_aggregated" + FROM realtime.temphumi + GROUP BY type, time(1h) + END + + CREATE CONTINUOUS QUERY "cq_temphumi_6h" ON "weather_v2" BEGIN + SELECT + max("humidity") AS humidity_max, + min("humidity") AS humidity_min, + mean("humidity") AS humidity, + max("temperature") AS temperature_max, + min("temperature") AS temperature_min, + mean("temperature") AS temperature + INTO "infinite"."temphumi_aggregated" + FROM realtime.temphumi + GROUP BY type, time(6h) + END + + ------------------------------------------------------------------------------- + TRAFFIC + ------------------------------------------------------------------------------- + CREATE CONTINUOUS QUERY "cq_net_1m" ON "status" BEGIN + SELECT NON_NEGATIVE_DERIVATIVE(max(*)) as traffic + INTO "monthly"."net_aggregated" + FROM realtime.net + WHERE time > now()-1m + GROUP BY time(30s) + END diff --git a/main.py b/main.py new file mode 100644 index 0000000..a091243 --- /dev/null +++ b/main.py @@ -0,0 +1,89 @@ +import cc1101_davis +import davis_decode +import utime +import WiFi +gc.collect() + +_DEBUG = False + +wifi_con = WiFi.NetSet('infra') +wifi_con.readNetworkConfig() +ips = wifi_con.connectInfra( + wifi_con._SSID, + wifi_con._PASS, + wifi_con._TIMEOUT) + +if _DEBUG: + print("IPCONF: {}".format(ips)) + +davis = cc1101_davis.CC1101() +davis.setRegisters() +davis.setFrequency(davis.hopIndex) +decoder = davis_decode.davisDecoder( + wifi_con._INF_DB_WEATHER, + wifi_con._INF_DB_STATUS, + wifi_con._INF_DB_RAW) + +# Main receive loop +while True: + data_length = davis.readRegister(davis.CC1101_RXBYTES) + data = "" + if data_length & 0x7f == 15: + data = davis.readBurst(davis.CC1101_RXFIFO, 10) + rssi = davis.readRssi() + lqi = davis.readLQI() + hop = davis.hopIndex + davis.flush() + davis.hop() + davis.rx() + data_int = [davis_decode.reverseBits(int(item)) for item in data] + header = decoder.davis_id(data_int[0]) + decoder.DecodePacket(data_int) + data_prn = "{:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5}".format( + data_int[0], + data_int[1], + data_int[2], + data_int[3], + data_int[4], + data_int[5], + data_int[6], + data_int[7], + data_int[8], + data_int[8],) + print("{_data:60} HOP: {_hop:<5} RSSI: {_rssi:<5} LQI: {_lqi:<5}".format( + _rssi=rssi, + _hop=hop, + _data=data_prn, + _lqi=lqi)) + if _DEBUG: + print("Header: {} Wind: {}".format(header, decoder.wind)) + print("{}: {}/{} ({})".format( + decoder.measurement, + decoder.name, + decoder.value, + decoder.tags)) + sent_ok = False + data_sent = None + try: + (sent_ok, data_sent) = davis_decode.send_to_influx( + wifi_con._INFLUX_HOST, + wifi_con._INFLUX_PORT, + decoder.write_influx_db, + wifi_con._INFLUX_USER, + wifi_con._INFLUX_PASS, + decoder.unit_id, + decoder.wind, + decoder.measurement, + decoder.name, + decoder.value, + decoder.tags) + except Exception as e: + print("ERROR: Data send 'urequest': {}".format(e)) + if _DEBUG: + if sent_ok: + print("DATA SEND: {}".format(data_sent.status_code)) + else: + print("DATA SEND FAIL: {}".format(data_sent)) + else: + utime.sleep_ms(100) + gc.collect() diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..dc1b8bb --- /dev/null +++ b/readme.md @@ -0,0 +1,371 @@ +#ESP8266 + CC1101 Davis weather station wifi logger + + +The intention is to gather data from a Weather station made by Davis. +In this case a Vantage Vue (integrated all sensors in one package) and +push them directly to an InfluxDB instance via WiFi. + +##Prerequisites: +- WiFi available, plus access to it. (WPA2 PSK preferred) +- Running INfluxDB instance on the same network +- ESP8266 microcontroller (NodeMCU 8266 preferred) +- git, since you're here, I assume this is already settled +- Micropython tools: ampy, esptool +- serial console emulator, I use picocom +- CC1101 from Texas Instruments radio chip, the 868 MHz version! There are 433Mhz sold out there, read descriptions +- a couple wires, need to solder those tiny CC1101 pins and wires. +- 5V / 3.3V source, depending on what version of ESP you get. A stable 3.3V is preferred + +##Quick setup of HW: +###1. Interconnect these pins: +The pins are marked on the NodeMcu ESP8266, on the CC1101 module, pins are counted from left, if you face the chip towards you. + +ESP8266 | ESP8266 description | CC1101 | CC1101 description | +|-------|---------------------|-----------|--------------------| +|GND | GND | 1- GND | GND | +|3V3 | Voltage In | 2- VCC | Vcc, Input voltage | +|D7 | GPIO13 | 3- Pin3 | MOSI | +|D5 | GPIO14 | 4- Pin4 | SCLK | +|D6 | GPIO12 | 5- Pin5 | MISO | +|- | - | 6- Pin6 | GDO2 | +|- | - | 7- Pin7 | GDO0 | +|D8 | GPIO15 | 8- Pin8 | CSN | + +IO pin GDO0, currently configured as interrupt, when new packet is received (i.e. goes HIGH). +This currently just to lights up a led, interrupt based receive is not implemented, though sounds cool. + +###2. Clone this repo, get Micropython +``` +git clone https://bastart.spoton.cz/git/Ventil/esp8266_CC1101_davis_vantage_vue.git +cd esp8266_CC1101_davis_vantage_vue +wget https://micropython.org/resources/firmware/esp8266-20191220-v1.12.bin -P /tmp +``` +###3. Upload Micropython, check +Need to delete the flash first, then write the custom firmware. +You need to determine which device is the one +to write to. If you have only one ESP8266, you are probably safe to use the ttyUSB0, +I will use ttyUSB1 as I have multiple UARTS on my machine +``` +esptool.py --port /dev/ttyUSB1 --baud 115200 erase_flash +esptool.py v2.8 +Serial port /dev/ttyUSB1 +Connecting.... +Detecting chip type... ESP8266 +Chip is ESP8266EX +Features: WiFi +Crystal is 26MHz +MAC: cc:50:e3:56:b2:5b +Uploading stub... +Running stub... +Stub running... +Erasing flash (this may take a while)... +Chip erase completed successfully in 7.8s +Hard resetting via RTS pin... +``` +Now it is time to upload uPython: +``` +esptool.py --port /dev/ttyUSB1 --baud 115200 write_flash 0 /tmp/esp8266-20191220-v1.12.bin +esptool.py v2.8 +Serial port /dev/ttyUSB1 +Connecting.... +Detecting chip type... ESP8266 +Chip is ESP8266EX +Features: WiFi +Crystal is 26MHz +MAC: cc:50:e3:56:b2:5b +Uploading stub... +Running stub... +Stub running... +Configuring flash size... +Auto-detected Flash size: 4MB +Flash params set to 0x0040 +Compressed 619828 bytes to 404070... +Wrote 619828 bytes (404070 compressed) at 0x00000000 in 35.8 seconds (effective 138.6 kbit/s)... +Hash of data verified. + +Leaving... +Hard resetting via RTS pin... +``` +And of course, when you try to get to the serial console, you should get somethinglike this +``` +picocom -b 115200 /dev/ttyUSB1 +picocom v3.1 + +port is : /dev/ttyUSB1 +flowcontrol : none +baudrate is : 115200 +parity is : none +databits are : 8 +stopbits are : 1 +escape is : C-a +local echo is : no +noinit is : no +noreset is : no +hangup is : no +nolock is : no +send_cmd is : sz -vv +receive_cmd is : rz -vv -E +imap is : +omap is : +emap is : crcrlf,delbs, +logfile is : none +initstring : none +exit_after is : not set +exit is : no + +Type [C-a] [C-h] to see available commands +Terminal ready + +>>> + +``` +Exit from the console with Ctrl + A + X or ampy will not be able to list files +on the esp8266 +###4. Freeze modules, or just upload the .mpy files +You can simply upload all the modules in question. If you modify anything in the .py +files, you need to freeze them again with mpy-cross +``` +/usr/bin/ampy -p /dev/ttyUSB1 put WiFi.mpy +/usr/bin/ampy -p /dev/ttyUSB1 put cc1101_davis.mpy +/usr/bin/ampy -p /dev/ttyUSB1 put davis_decode.mpy +``` + +to freeze a module: +``` +mpy-cross WiFi.py +ls -l WiFi.* +WiFi.mpy <-- the newly compiled (frozen) module +WiFi.py + +``` +###5. Modify inet.conf +Before uploading the inte.conf, please change it to your desired values. +###6, Upload files +``` +/usr/bin/ampy -p /dev/ttyUSB1 put boot.py +/usr/bin/ampy -p /dev/ttyUSB1 put main.py +/usr/bin/ampy -p /dev/ttyUSB1 put inet.conf + +/usr/bin/ampy -p /dev/ttyUSB1 ls +/WiFi.mpy +/boot.py +/cc1101_davis.mpy +/davis_decode.mpy +/inet.conf +/main.py + +``` +###7. If you haven't already, create 2 DBs in inclux +I am tempted to push the raw, undecoded data to a DB as well, but influx is not siutd for this. You can ignore the last DB creation +``` +ssh 192.168.1.2 +influx +create database weather +create database status +create database raw +``` +###8. Restart esp8266, check data on serial +``` +picocom -b 115200 /dev/ttyUSB1 +picocom v3.1 + +port is : /dev/ttyUSB1 +flowcontrol : none +baudrate is : 115200 +parity is : none +databits are : 8 +stopbits are : 1 +escape is : C-a +local echo is : no +noinit is : no +noreset is : no +hangup is : no +nolock is : no +send_cmd is : sz -vv +receive_cmd is : rz -vv -E +imap is : +omap is : +emap is : crcrlf,delbs, +logfile is : none +initstring : none +exit_after is : not set +exit is : no + +Type [C-a] [C-h] to see available commands +Terminal ready + +>>> +>>> +>>> +>>> +>>> +>>> +>>> +>>> +>>> +>>> +>>> +>>> {ll��|�#�o + + � + $� + c|����|#� + #��nN�$oN��� + bp��$sl{lp�o� + �l + + + " + N�|�l + + #��nN�$��l`�Nl or���N + + � + �$p�n� + r�ܜ� + + bn�|$ + �� + #��on� + l �n$�$`n{�ےo + l �o + + ��#�ol� + ��no��{lp�o� + + r����� + �p� + # + N�|��p��on�l�l �n$�$`nr���� + $l`{��n + l$ ���o�r��n|�ll$d`#���r�l�o��o�l ��r�$�$� + l`��r�p��l� + + $`���o�l��� + l$`sl��b���# + ��B| + $b���#|����l$b��n��Trying... 15 more times +Trying... 14 more times +Trying... 13 more times +Trying... 12 more times +Trying... 11 more times +Trying... 10 more times +IPCONF: {'ip': '192.168.1.174', 'mask': '255.255.255.0', 'gw': '192.168.1.254', 'dns': '192.168.1.4'} + 0 10 4 35 8 4 78 196 255 255 HOP: 0 RSSI: -71.5 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 0, 'davis_id': 0} Wind: {'speed': 16.1, 'direction': 5.6} +False: False/False (False) +DATA SEND FAIL: ERROR measurement set False + 224 10 234 17 1 4 38 49 255 255 HOP: 1 RSSI: -70 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 14, 'davis_id': 0} Wind: {'speed': 16.1, 'direction': 327.6} +rain: value/17.0 ({'type': 'rain_bucket_tips'}) +DATA SEND: 204 + 80 9 224 255 113 15 89 230 255 255 HOP: 2 RSSI: -70 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 5, 'davis_id': 0} Wind: {'speed': 14.5, 'direction': 313.6} +rain: value/0.0 ({'type': 'rainrate'}) +DATA SEND: 204 + 128 8 252 34 233 10 229 180 255 255 HOP: 3 RSSI: -70 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 8, 'davis_id': 0} Wind: {'speed': 12.9, 'direction': 352.8} +temphumi: temperature/13.3 ({'type': 'external'}) +DATA SEND: 204 + 160 8 249 109 41 2 202 57 255 255 HOP: 4 RSSI: -69 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 10, 'davis_id': 0} Wind: {'speed': 12.9, 'direction': 348.6} +temphumi: humidity/62.1 ({'type': 'external'}) +DATA SEND: 204 + 224 9 225 17 1 2 182 58 255 255 HOP: 0 RSSI: -68 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 14, 'davis_id': 0} Wind: {'speed': 14.5, 'direction': 315.0} +rain: value/17.0 ({'type': 'rain_bucket_tips'}) +DATA SEND: 204 + 80 10 241 255 115 10 236 224 255 255 HOP: 1 RSSI: -68.5 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 5, 'davis_id': 0} Wind: {'speed': 16.1, 'direction': 337.4} +rain: value/0.0 ({'type': 'rainrate'}) +DATA SEND: 204 + 128 16 233 34 219 10 39 214 255 255 HOP: 2 RSSI: -68.5 LQI: 127 +Header: {'bat_low': 0, 'packet_id': 8, 'davis_id': 0} Wind: {'speed': 25.7, 'direction': 326.2} +temphumi: temperature/13.2 ({'type': 'external'}) +``` +And with '_DEBUG' set to False on line 7, in main.py: +You can see the raw data that are comming in from the Davis weather station. + +``` +>>> +MPY: soft reboot +Trying... 15 more times + 0 17 244 212 193 138 98 76 255 255 HOP: 0 RSSI: -68 LQI: 127 + 224 13 3 17 3 3 32 253 255 255 HOP: 1 RSSI: -68.5 LQI: 127 + 80 13 5 255 112 2 10 211 255 255 HOP: 2 RSSI: -68 LQI: 127 + 128 9 236 34 203 2 181 206 255 255 HOP: 3 RSSI: -68.5 LQI: 127 + 160 11 252 106 43 2 123 92 255 255 HOP: 4 RSSI: -69 LQI: 127 + 224 13 247 17 3 6 37 228 255 255 HOP: 0 RSSI: -68.5 LQI: 127 + 80 12 6 255 113 2 8 111 255 255 HOP: 1 RSSI: -69 LQI: 127 + 128 9 239 34 203 3 62 51 255 255 HOP: 2 RSSI: -70 LQI: 127 + 32 8 232 212 195 128 93 215 255 255 HOP: 3 RSSI: -70.5 LQI: 127 + 224 6 239 17 3 3 7 218 255 255 HOP: 4 RSSI: -69.5 LQI: 127 + 80 7 237 255 115 7 72 162 255 255 HOP: 0 RSSI: -69 LQI: 127 + 128 9 14 34 203 0 252 14 255 255 HOP: 1 RSSI: -68.5 LQI: 127 +``` + +If you are interested in the packet format, please: +``` + Header byte0 byte1 byte2 byte3 byte4 byte5 byte6 byte7 byte8 Freq Sig_strength Link_quality + 224 13 3 17 3 3 32 253 255 255 HOP: 1 RSSI: -68.5 LQI: 127 +``` + +###9, explore data in Influx +You're all set, let's look at the data +``` +ssh 192.168.1.2 +influx +> use weather +Using database weather +> select * from wind where time > now() - 1m group by type +name: wind +tags: type=direction +time davis_id value +---- -------- ----- +1590755264047546640 0 23.8 +1590755266495686261 0 12.6 +1590755269170611760 0 315 +1590755271670765583 0 4.2 +1590755274297615725 0 340.2 +1590755276695612090 0 351.4 +1590755279347820779 0 14 +1590755282048791933 0 14 +1590755284420807397 0 5.6 +1590755287147874950 0 5.6 +1590755289521471177 0 25.2 +1590755292271754999 0 323.4 +1590755294748104920 0 351.4 +1590755297195883784 0 350 +1590755302322174318 0 330.4 +1590755317723159515 0 333.2 +1590755320496027169 0 341.6 + +name: wind +tags: type=speed +time davis_id value +---- -------- ----- +1590755264047546640 0 20.9 +1590755266495686261 0 20.9 +1590755269170611760 0 16.1 +1590755271670765583 0 25.7 +1590755274297615725 0 24.1 +1590755276695612090 0 22.5 +1590755279347820779 0 24.1 +1590755282048791933 0 22.5 +1590755284420807397 0 20.9 +1590755287147874950 0 17.7 +1590755289521471177 0 20.9 +1590755292271754999 0 22.5 +1590755294748104920 0 19.3 +1590755297195883784 0 22.5 +1590755302322174318 0 20.9 +1590755317723159515 0 11.3 +1590755320496027169 0 12.9 + +name: wind +tags: type=windgust +time davis_id value +---- -------- ----- +1590755279347820779 0 25.7494 +``` +### Optionally, get grafana to plot the graphs for you From c99dbd86f4bf84104d0f494bfc496edd1af06d20 Mon Sep 17 00:00:00 2001 From: "Milan \"Ventil\" Toman" Date: Fri, 29 May 2020 15:07:18 +0200 Subject: [PATCH 02/13] Update readme.md --- readme.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/readme.md b/readme.md index dc1b8bb..b0f3a3a 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,11 @@ -#ESP8266 + CC1101 Davis weather station wifi logger +# ESP8266 + CC1101 Davis weather station wifi logger The intention is to gather data from a Weather station made by Davis. In this case a Vantage Vue (integrated all sensors in one package) and push them directly to an InfluxDB instance via WiFi. -##Prerequisites: +## Prerequisites: - WiFi available, plus access to it. (WPA2 PSK preferred) - Running INfluxDB instance on the same network - ESP8266 microcontroller (NodeMCU 8266 preferred) @@ -16,8 +16,8 @@ push them directly to an InfluxDB instance via WiFi. - a couple wires, need to solder those tiny CC1101 pins and wires. - 5V / 3.3V source, depending on what version of ESP you get. A stable 3.3V is preferred -##Quick setup of HW: -###1. Interconnect these pins: +## Quick setup of HW: +### 1. Interconnect these pins: The pins are marked on the NodeMcu ESP8266, on the CC1101 module, pins are counted from left, if you face the chip towards you. ESP8266 | ESP8266 description | CC1101 | CC1101 description | @@ -34,13 +34,13 @@ ESP8266 | ESP8266 description | CC1101 | CC1101 description | IO pin GDO0, currently configured as interrupt, when new packet is received (i.e. goes HIGH). This currently just to lights up a led, interrupt based receive is not implemented, though sounds cool. -###2. Clone this repo, get Micropython +### 2. Clone this repo, get Micropython ``` git clone https://bastart.spoton.cz/git/Ventil/esp8266_CC1101_davis_vantage_vue.git cd esp8266_CC1101_davis_vantage_vue wget https://micropython.org/resources/firmware/esp8266-20191220-v1.12.bin -P /tmp ``` -###3. Upload Micropython, check +### 3. Upload Micropython, check Need to delete the flash first, then write the custom firmware. You need to determine which device is the one to write to. If you have only one ESP8266, you are probably safe to use the ttyUSB0, @@ -121,7 +121,7 @@ Terminal ready ``` Exit from the console with Ctrl + A + X or ampy will not be able to list files on the esp8266 -###4. Freeze modules, or just upload the .mpy files +### 4. Freeze modules, or just upload the .mpy files You can simply upload all the modules in question. If you modify anything in the .py files, you need to freeze them again with mpy-cross ``` @@ -138,9 +138,9 @@ WiFi.mpy <-- the newly compiled (frozen) module WiFi.py ``` -###5. Modify inet.conf +### 5. Modify inet.conf Before uploading the inte.conf, please change it to your desired values. -###6, Upload files +### 6, Upload files ``` /usr/bin/ampy -p /dev/ttyUSB1 put boot.py /usr/bin/ampy -p /dev/ttyUSB1 put main.py @@ -155,7 +155,7 @@ Before uploading the inte.conf, please change it to your desired values. /main.py ``` -###7. If you haven't already, create 2 DBs in inclux +### 7. If you haven't already, create 2 DBs in inclux I am tempted to push the raw, undecoded data to a DB as well, but influx is not siutd for this. You can ignore the last DB creation ``` ssh 192.168.1.2 @@ -164,7 +164,7 @@ create database weather create database status create database raw ``` -###8. Restart esp8266, check data on serial +### 8. Restart esp8266, check data on serial ``` picocom -b 115200 /dev/ttyUSB1 picocom v3.1 @@ -310,7 +310,7 @@ If you are interested in the packet format, please: 224 13 3 17 3 3 32 253 255 255 HOP: 1 RSSI: -68.5 LQI: 127 ``` -###9, explore data in Influx +### 9, explore data in Influx You're all set, let's look at the data ``` ssh 192.168.1.2 From 773fafd698a5302782f9b92192cdac7064246c61 Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Fri, 29 May 2020 15:49:49 +0200 Subject: [PATCH 03/13] DB structure changed --- influx_structure.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/influx_structure.md b/influx_structure.md index 422fdee..79694ba 100644 --- a/influx_structure.md +++ b/influx_structure.md @@ -64,50 +64,50 @@ Firs off, 2 databases: ------------------------------------------------------------------------------- WIND ------------------------------------------------------------------------------- - CREATE CONTINUOUS QUERY "cq_wind_10m" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_wind_10m" ON "weather" BEGIN SELECT max(value) AS wind_max, mean(value) AS wind, min(value) AS wind_min INTO "monthly"."wind_aggregated" FROM realtime.wind - GROUP BY time(10m), type + GROUP BY time(10m), type, davis_id END - CREATE CONTINUOUS QUERY "cq_wind_1h" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_wind_1h" ON "weather" BEGIN SELECT max(value) AS wind_max, mean(value) AS wind, min(value) AS wind_min INTO "yearly"."wind_aggregated" FROM realtime.wind - GROUP BY time(1h), type + GROUP BY time(1h), type, davis_id END - CREATE CONTINUOUS QUERY "cq_wind_6h" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_wind_6h" ON "weather" BEGIN SELECT max(value) AS wind_max, mean(value) AS wind, min(value) AS wind_min INTO "infinite"."wind_aggregated" FROM realtime.wind - GROUP BY time(6h), type + GROUP BY time(6h), type, davis_id END ------------------------------------------------------------------------------- RAIN ------------------------------------------------------------------------------- - CREATE CONTINUOUS QUERY "cq_rain_10m" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_rain_10m" ON "weather" BEGIN SELECT max("value") AS val_max, mean(value) AS value INTO "monthly"."rainrate_aggregated" FROM realtime.rain - GROUP BY type,time(10m) + GROUP BY type,time(10m), davis_id END - CREATE CONTINUOUS QUERY "cq_rain_1h" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_rain_1h" ON "weather" BEGIN SELECT max("value") AS val_max, mean(value) AS value INTO "yearly"."rainrate_aggregated" FROM realtime.rain - GROUP BY type,time(1h) + GROUP BY type,time(1h), davis_id END - CREATE CONTINUOUS QUERY "cq_rain_6h" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_rain_6h" ON "weather" BEGIN SELECT max("value") AS val_max, mean(value) AS value INTO "infinite"."rainrate_aggregated" FROM realtime.rain - GROUP BY type,time(6h) + GROUP BY type,time(6h), davis_id END ------------------------------------------------------------------------------- TEMPHUMI ------------------------------------------------------------------------------- - CREATE CONTINUOUS QUERY "cq_temphumi_10m" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_temphumi_10m" ON "weather" BEGIN SELECT max("humidity") AS humidity_max, min("humidity") AS humidity_min, @@ -117,10 +117,10 @@ Firs off, 2 databases: mean("temperature") AS temperature INTO "monthly"."temphumi_aggregated" FROM realtime.temphumi - GROUP BY type, time(10m) + GROUP BY type, time(10m), davis_id END - CREATE CONTINUOUS QUERY "cq_temphumi_1h" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_temphumi_1h" ON "weather" BEGIN SELECT max("humidity") AS humidity_max, min("humidity") AS humidity_min, @@ -130,10 +130,10 @@ Firs off, 2 databases: mean("temperature") AS temperature INTO "yearly"."temphumi_aggregated" FROM realtime.temphumi - GROUP BY type, time(1h) + GROUP BY type, time(1h), davis_id END - CREATE CONTINUOUS QUERY "cq_temphumi_6h" ON "weather_v2" BEGIN + CREATE CONTINUOUS QUERY "cq_temphumi_6h" ON "weather" BEGIN SELECT max("humidity") AS humidity_max, min("humidity") AS humidity_min, @@ -143,7 +143,7 @@ Firs off, 2 databases: mean("temperature") AS temperature INTO "infinite"."temphumi_aggregated" FROM realtime.temphumi - GROUP BY type, time(6h) + GROUP BY type, time(6h), davis_id END ------------------------------------------------------------------------------- From 372c4d235f929f1925894a6f8c2a697d84150b50 Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Tue, 2 Jun 2020 14:54:47 +0200 Subject: [PATCH 04/13] freq comp added --- cc1101_davis.mpy | Bin 7979 -> 8147 bytes cc1101_davis.py | 8 ++++++++ main.py | 31 ++++++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/cc1101_davis.mpy b/cc1101_davis.mpy index 384f59a96e24619aeabb63b1b75a16107dfd542e..e2c622fd603ceb59084fdcf262ab2a6cf8f8f0a1 100644 GIT binary patch delta 390 zcmZ2&ciDczR%Q=|fQdU~IXGL{TRB=eQzzcJq+lc{CY79+lk8TMTIgC-lwTB>%pi0) zqO+kvpoNV=P<8TN#uJQ&o7V%o+#n*jL6{jR0unT10`g6Pd^5(#z+^@ShR$M>fTGmm)Vvafvc#OyR4aw*S{;S( zAkPp_KX)KoT_MC@0o6_geV}-ggOM0B?}R*cLqkJ`4I;*q@5rVqaHZvx7H60-0F7n< z8qE;Xm=G<&2lBpiQL^ZS(#bJ$QCzj!8af&tKt1Y{&&c_Bw*groruVHI q5 4): # 5 EU frequencies self.hopIndex = 0 + present = self.readRegister(self.CC1101_FSCTRL0) + print("Present value: {}, WRITING {} TO CC1101_FSCTRL0 / {}".format(present, self.freqComp[self.hopIndex], self.CC1101_FSCTRL0)) self.writeRegister(self.CC1101_FSCTRL0, self.freqComp[self.hopIndex]) self.setFrequency(self.hopIndex) # Set the frequency. @@ -388,3 +390,9 @@ class CC1101(object): def readLQI(self): return self.readRegister(self.CC1101_RXFIFO) & 0x7F + def calcFreqError(self, value): + if value >= 128: + error = (value - 256) >> 1 + else: + error = value >> 1 + return error diff --git a/main.py b/main.py index a091243..328f5c0 100644 --- a/main.py +++ b/main.py @@ -4,7 +4,20 @@ import utime import WiFi gc.collect() +#_SSID = 'BastArt' +#_PASS = '3 litry Kvasaru!' +#_TIMEOUT = 15 _DEBUG = False +# +#_INFLUX_HOST = '192.168.1.2' +#_INFLUX_PORT = '8086' +#_INFLUX_USER = 'ventil' +#_INFLUX_PASS = '3 litry Kvasaru!' +# +#_INF_DB_WEATHER = 'weather' +#_INF_DB_STATUS = 'status' +#_INF_DB_RAW = 'raw' + wifi_con = WiFi.NetSet('infra') wifi_con.readNetworkConfig() @@ -25,6 +38,7 @@ decoder = davis_decode.davisDecoder( wifi_con._INF_DB_RAW) # Main receive loop +interpacket_time = 0 while True: data_length = davis.readRegister(davis.CC1101_RXBYTES) data = "" @@ -32,6 +46,14 @@ while True: data = davis.readBurst(davis.CC1101_RXFIFO, 10) rssi = davis.readRssi() lqi = davis.readLQI() + freqEst = davis.readStatus(davis.CC1101_FREQEST) + freqError = davis.calcFreqError(freqEst) + print("FERROR: {} (EST: {})".format(freqError, freqEst)) + print("FCOMP: {}".format(davis.freqComp)) + if davis.freqComp[davis.hopIndex] + freqEst <= 255: + davis.freqComp[davis.hopIndex] = davis.freqComp[davis.hopIndex] + freqEst + else: + davis.freqComp[davis.hopIndex] = 255 hop = davis.hopIndex davis.flush() davis.hop() @@ -49,12 +71,13 @@ while True: data_int[6], data_int[7], data_int[8], - data_int[8],) - print("{_data:60} HOP: {_hop:<5} RSSI: {_rssi:<5} LQI: {_lqi:<5}".format( + data_int[9]) + print("{_data:60} HOP: {_hop:<5} RSSI: {_rssi:<5} LQI: {_lqi:<5} {_last}s since".format( _rssi=rssi, _hop=hop, _data=data_prn, - _lqi=lqi)) + _lqi=lqi, + _last=interpacket_time / 10)) if _DEBUG: print("Header: {} Wind: {}".format(header, decoder.wind)) print("{}: {}/{} ({})".format( @@ -84,6 +107,8 @@ while True: print("DATA SEND: {}".format(data_sent.status_code)) else: print("DATA SEND FAIL: {}".format(data_sent)) + interpacket_time = 0 else: + interpacket_time += 1 utime.sleep_ms(100) gc.collect() From a022415719dd7d9f5d43e745abaea4b65e72228c Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Tue, 7 Jul 2020 11:47:24 +0200 Subject: [PATCH 05/13] Error in pin numbering --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index b0f3a3a..14e26d0 100644 --- a/readme.md +++ b/readme.md @@ -22,8 +22,8 @@ The pins are marked on the NodeMcu ESP8266, on the CC1101 module, pins are count ESP8266 | ESP8266 description | CC1101 | CC1101 description | |-------|---------------------|-----------|--------------------| -|GND | GND | 1- GND | GND | -|3V3 | Voltage In | 2- VCC | Vcc, Input voltage | +|3V3 | Voltage In | 1- VCC | Vcc, Input voltage | +|GND | GND | 2- GND | GND | |D7 | GPIO13 | 3- Pin3 | MOSI | |D5 | GPIO14 | 4- Pin4 | SCLK | |D6 | GPIO12 | 5- Pin5 | MISO | From 4670eb836eb166f2556d4ea00eb8379bd9a1241a Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Mon, 5 Oct 2020 17:32:37 +0200 Subject: [PATCH 06/13] CRC checks, wifi ECONABORT sorted to machine.reset() --- WiFi.mpy | Bin 1610 -> 1596 bytes WiFi.py | 1 - cc1101_davis.mpy | Bin 8147 -> 8066 bytes cc1101_davis.py | 11 +++++------ davis_decode.mpy | Bin 3139 -> 3755 bytes davis_decode.py | 24 ++++++++++++++++++++++-- main.py | 37 ++++++++++++++++++++++++++++++++++--- 7 files changed, 61 insertions(+), 12 deletions(-) diff --git a/WiFi.mpy b/WiFi.mpy index cc403981ddc1d500fa06ac41c922c731282974e8..0d6dfb8a14bb6e4d123402d3c75f62f3a7c5e80a 100644 GIT binary patch delta 111 zcmX@bvxi5=mz7Cgq0vG@fPtMaJku>xub@)HBZZ+MP?|3laX`cIY~yrjW6sO8I>n%FoiN|Pp)Iy#%MCxlzES!J40YH0|P^6cS)m= OlR0yP*JdUb4<-Pe{T?y^ delta 125 zcmdnPbBf2xmz7Cgp)p26h=H9iJku>xub@&x!y|>EAyAqxFSVpRzbIRb5y;^xEy>JH z1vB|_6O%JC^Cs%3GjsQFP7KRr#4 z-e|(u;3U-$et1*IhYi9)&Oy%cA&yQyuA4eOZrmLDF7%yJO9R7?Lyb=(qOLnXsE>@? z1U8c|KB+V2+&W45thVelWZk}$F Uz2$8gTPJtQt1)&=-XO0G0G9ttUH||9 delta 309 zcmZp&zidC@CL_njTdQOQnr$ql*fR19BqyY5YpQBnPo6AmRWHO)t;{IG5VCQDus~W- zYN2y}Zovj&_RtN&tY*w6jFB5e1UCpX14TfBW=uf7DUff*7#Wz%$iUE9Y!XnETAZ3! zqEMEYQ<`d}P+hB|5FX?i;_2rOWGjUDD>yqF8X6eJy9GOk1o;>!=mUkD9E`-6c_-wl z8&3WwTU(zHEy0(Zn3L>Wlq@=-R7pwAP?w?MaKn*JPLd7bM>ltT*dQ$A9ON7y;^^e# zy1C=y#x0@mLf;+U()jd9{nPM<8_o~wBR3~A0G-1ZpH!NbmRiJ 4): # 5 EU frequencies self.hopIndex = 0 present = self.readRegister(self.CC1101_FSCTRL0) - print("Present value: {}, WRITING {} TO CC1101_FSCTRL0 / {}".format(present, self.freqComp[self.hopIndex], self.CC1101_FSCTRL0)) + # DEBUG print("Present value: {}, WRITING {} TO CC1101_FSCTRL0 / {}".format(present, self.freqComp[self.hopIndex], self.CC1101_FSCTRL0)) self.writeRegister(self.CC1101_FSCTRL0, self.freqComp[self.hopIndex]) self.setFrequency(self.hopIndex) # Set the frequency. @@ -370,12 +370,11 @@ class CC1101(object): self.writeRegister(self.CC1101_FREQ0, self.FREQ_0[index]) self.flush() - def calcCrc(self, _buffer, length): + def calcCrc(self, _buffer): crc = 0x0000 - buffer_index = 0 - for i in range(length, 0, -1): - crc = (crc << 8) ^ self.CRC_TABLE[(crc >> 8) ^ (_buffer[buffer_index])] - buffer_index += 1 + for i in range(0, len(_buffer)): + crc = ((crc << 8) ^ self.CRC_TABLE[(crc >> 8) ^ (_buffer[i])]) % 65536 + # DEBUG print("CRC: {}".format(crc)) return crc def readRssi(self): diff --git a/davis_decode.mpy b/davis_decode.mpy index d297958fbeec74dd196ec055c7a744153cee8d95..09e8beb62987e6fedb5b0aed4ac0b14af0269696 100644 GIT binary patch delta 822 zcmZ9K%TE(Q9LHzcX}9u_c3ZH<2MaAth4ScY+p^(RN&-YvT5AXg+;rOoH)0Dr1u;;& zV2B~{VBL!cPb6OSq7r<8aPVm2!Nh|n7IA6cYRP9y*#mwPb{cY%0+?oj`+FjweV*`uLpvDI zuC;6P-x3WP+u^8FWh|F?FcWXkcAr6`p>p5xb4Np7A*^|Qp5E4V&eQ8^9qS=^wtsmZ z8|z9;YAjfDv1HF}<6#KSxa`EOW>MWojbdw2<7Ysc6&!-wW);ZR@t{M02jw-7eZmXe z_7kI$({##4ZOYY5e`M$B>!ea1yVpKD3BhbCX99vCToME%^&!cRqyUnFND3h-j3gdO z5hO*C6tk!pD`s*(z0S~8S)otONqqxrWbU$0@>B5>2~Y_T2~r6X2~i0V2~!CZ;i>RM zB2*$oqEwwCt*=I(n4gq*cHCu(h0nFn$GxA7|+)xV$(IH6}u zT`;L@rYfA(S@SlO^(W>$ys1Nmg9W{v8HHG%V>;ogUS+!BUHypJgb#P)7Kr`;tMTr$ delta 265 zcmZ22dssr>mz7Cgq0vV|jDcM)C9y2CI6fscIX@*;ub?s`rB%L_gP|c%TBx)rwXig` zxTJWZy+W8+QEFLgQE{qMW=U~~5tD!fSf2}6Tah3`sR^?fV_-4^b4SSQNi0^Z+zss7 zYIXaWvLgikTWVs7)4Rv*VO*W??WfXYbLQoWgdMQGc=(dn2Ri360_{rxuwHQ+-|K!wV%$lsu)x=n{ Jc@-BU3jh@@OfUcd diff --git a/davis_decode.py b/davis_decode.py index c3f9e34..32d0e15 100644 --- a/davis_decode.py +++ b/davis_decode.py @@ -1,5 +1,5 @@ import urequests - +import machine _DEBUG = False @@ -32,8 +32,28 @@ def send_to_influx(host, port, db, user, password, davis_unit_id, wind, measurem try: return (True, urequests.post(post, data=data)) except Exception as e: - return (False, "ERROR sending data to influx: {}".format(e)) + if e.args[0] == 103: + machine.reset() + else: + return (False, "ERROR sending data to influx: {}".format(e)) +def raw_send_to_influx(host, port, db, user, password, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, rssi, lqi): + post = "http://{}:{}/write?db={}".format(host, port, db) + if _DEBUG: + print("SENDING TO: {}".format(post)) + data = "data b0={_b0},b1={_b1},b2={_b2},b3={_b3},b4={_b4},b5={_b5},b6={_b6},b7={_b7},b8={_b8},b9={_b9},rssi={_rssi},lqi={_lqi}".format( + _b0=b0, _b1=b1, _b2=b2, _b3=b3, + _b4=b4, _b5=b5, _b6=b6, _b7=b7, + _b8=b8, _b9=b9, _rssi=rssi, _lqi=lqi) + if _DEBUG: + print("POST_DATA: {}".format(data)) + try: + return (True, urequests.post(post, data=data)) + except Exception as e: + if e.args[0] == 103: + machine.reset() + else: + return (False, "ERROR sending RAW data to influx: {}".format(e)) def reverseBits(data): data = "{:08b}".format(data) diff --git a/main.py b/main.py index 328f5c0..5ca84f6 100644 --- a/main.py +++ b/main.py @@ -2,12 +2,13 @@ import cc1101_davis import davis_decode import utime import WiFi +import machine gc.collect() #_SSID = 'BastArt' #_PASS = '3 litry Kvasaru!' #_TIMEOUT = 15 -_DEBUG = False +_DEBUG = True # #_INFLUX_HOST = '192.168.1.2' #_INFLUX_PORT = '8086' @@ -48,8 +49,9 @@ while True: lqi = davis.readLQI() freqEst = davis.readStatus(davis.CC1101_FREQEST) freqError = davis.calcFreqError(freqEst) - print("FERROR: {} (EST: {})".format(freqError, freqEst)) - print("FCOMP: {}".format(davis.freqComp)) + if _DEBUG: + print("FERROR: {} (EST: {})".format(freqError, freqEst)) + print("FCOMP: {}".format(davis.freqComp)) if davis.freqComp[davis.hopIndex] + freqEst <= 255: davis.freqComp[davis.hopIndex] = davis.freqComp[davis.hopIndex] + freqEst else: @@ -59,6 +61,12 @@ while True: davis.hop() davis.rx() data_int = [davis_decode.reverseBits(int(item)) for item in data] + crc = davis.calcCrc(data_int[:8]) + if crc != 0x0000: + print("Corrupt data CRC: {}".format(crc)) + continue + else: + print("Data OK, CRC: {}".format(crc)) header = decoder.davis_id(data_int[0]) decoder.DecodePacket(data_int) data_prn = "{:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5}".format( @@ -87,6 +95,7 @@ while True: decoder.tags)) sent_ok = False data_sent = None + gc.collect() try: (sent_ok, data_sent) = davis_decode.send_to_influx( wifi_con._INFLUX_HOST, @@ -102,6 +111,28 @@ while True: decoder.tags) except Exception as e: print("ERROR: Data send 'urequest': {}".format(e)) + try: + (raw_sent_ok, raw_data_sent) = davis_decode.raw_send_to_influx( + wifi_con._INFLUX_HOST, + wifi_con._INFLUX_PORT, + decoder.raw_influx_db, + wifi_con._INFLUX_USER, + wifi_con._INFLUX_PASS, + data_int[0], + data_int[1], + data_int[2], + data_int[3], + data_int[4], + data_int[5], + data_int[6], + data_int[7], + data_int[8], + data_int[9], + rssi, + lqi) + except Exception as e: + print("ERROR: Data send 'urequest': {}".format(e)) + if _DEBUG: if sent_ok: print("DATA SEND: {}".format(data_sent.status_code)) From aebca4e6eb1f4c430e7cc6370371a89de25b783d Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Thu, 8 Oct 2020 13:49:58 +0200 Subject: [PATCH 07/13] raw data send correction --- davis_decode.mpy | Bin 3755 -> 3755 bytes davis_decode.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/davis_decode.mpy b/davis_decode.mpy index 09e8beb62987e6fedb5b0aed4ac0b14af0269696..e30be792f4074bde9e960feb514d85252db2d98f 100644 GIT binary patch delta 14 VcmZ22yIOXGBnu<|W+|45TmT`31KI!p delta 14 VcmZ22yIOXGBnzY0W+|45TmT~H1Qh@P diff --git a/davis_decode.py b/davis_decode.py index 32d0e15..2ffb3d7 100644 --- a/davis_decode.py +++ b/davis_decode.py @@ -41,7 +41,7 @@ def raw_send_to_influx(host, port, db, user, password, b0, b1, b2, b3, b4, b5, b post = "http://{}:{}/write?db={}".format(host, port, db) if _DEBUG: print("SENDING TO: {}".format(post)) - data = "data b0={_b0},b1={_b1},b2={_b2},b3={_b3},b4={_b4},b5={_b5},b6={_b6},b7={_b7},b8={_b8},b9={_b9},rssi={_rssi},lqi={_lqi}".format( + data = "data b0={_b0},b1={_b1},b2={_b2},b3={_b3},b4={_b4},b5={_b5},b6={_b6},b7={_b7},b8={_b8},b9={_b9},rssi={_rssi},lqi={_lqi}".format( _b0=b0, _b1=b1, _b2=b2, _b3=b3, _b4=b4, _b5=b5, _b6=b6, _b7=b7, _b8=b8, _b9=b9, _rssi=rssi, _lqi=lqi) From 62060638a13367558852328babb70ba411a495da Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Thu, 8 Oct 2020 13:57:18 +0200 Subject: [PATCH 08/13] DB schema creation update --- influx_structure.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/influx_structure.md b/influx_structure.md index 79694ba..796b838 100644 --- a/influx_structure.md +++ b/influx_structure.md @@ -1,12 +1,16 @@ #Structure of InfluxDB + InfluxDB was chosen for it's simplicity and ease of management, live with it. ##influxDB SCHEMA: + Firs off, 2 databases: + weather status ###DB weather + measure wind ---------------- value | speed or direction or windgust | davis_id From f9a653c26db80a60db6633d6c5e7531ada89f6a4 Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Thu, 8 Oct 2020 13:58:22 +0200 Subject: [PATCH 09/13] DB schema creation update --- influx_structure.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/influx_structure.md b/influx_structure.md index 796b838..58a190a 100644 --- a/influx_structure.md +++ b/influx_structure.md @@ -1,15 +1,13 @@ -#Structure of InfluxDB - +# Structure of InfluxDB InfluxDB was chosen for it's simplicity and ease of management, live with it. -##influxDB SCHEMA: - +## influxDB SCHEMA: Firs off, 2 databases: weather status -###DB weather +### DB weather measure wind ---------------- @@ -31,7 +29,7 @@ Firs off, 2 databases: -###DB status +### DB status iss measure ---------------- From 8a563f86cfe881a3cfb257a2d026a17911ec1d45 Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Thu, 8 Oct 2020 14:00:00 +0200 Subject: [PATCH 10/13] DB schema creation update --- influx_structure.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/influx_structure.md b/influx_structure.md index 58a190a..dd298c0 100644 --- a/influx_structure.md +++ b/influx_structure.md @@ -1,11 +1,14 @@ # Structure of InfluxDB InfluxDB was chosen for it's simplicity and ease of management, live with it. -## influxDB SCHEMA: -Firs off, 2 databases: +## influxDB SCHEMA +Let's take a look at how to create a suitable database for the data + +### Firs off, 3 databases: - weather - status + create database weather + create database status + create database raw ### DB weather From 944fc476f7160327c21f8c1f557a74457dfa9822 Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Thu, 8 Oct 2020 14:04:14 +0200 Subject: [PATCH 11/13] DB schema creation update --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 14e26d0..4830220 100644 --- a/readme.md +++ b/readme.md @@ -155,8 +155,8 @@ Before uploading the inte.conf, please change it to your desired values. /main.py ``` -### 7. If you haven't already, create 2 DBs in inclux -I am tempted to push the raw, undecoded data to a DB as well, but influx is not siutd for this. You can ignore the last DB creation +### 7. If you haven't already, create 3 DBs in influx +I am pushing the RAW data as well, just for fun. ``` ssh 192.168.1.2 influx From 553778740d9fc113e62e87d715534b50555fd6da Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Tue, 13 Oct 2020 12:07:25 +0200 Subject: [PATCH 12/13] MIT license --- readme.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/readme.md b/readme.md index 4830220..418e9c7 100644 --- a/readme.md +++ b/readme.md @@ -369,3 +369,12 @@ time davis_id value 1590755279347820779 0 25.7494 ``` ### Optionally, get grafana to plot the graphs for you + +### License +Copyright + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From fb7f14deb73698d8950aa3c8e6e6c1b96ac3fa41 Mon Sep 17 00:00:00 2001 From: Milan Ventil Toman Date: Wed, 4 Nov 2020 14:19:53 +0100 Subject: [PATCH 13/13] Rx function moved into the CC1101, RAM savings implemented --- WiFi.mpy | Bin 1596 -> 1596 bytes WiFi.py | 28 ++++++++-------- cc1101_davis.mpy | Bin 8066 -> 8434 bytes cc1101_davis.py | 65 ++++++++++++++++++++++++++++-------- davis_decode.mpy | Bin 3755 -> 3755 bytes davis_decode.py | 24 +++++++------- main.py | 84 ++++++++++++++++------------------------------- 7 files changed, 107 insertions(+), 94 deletions(-) diff --git a/WiFi.mpy b/WiFi.mpy index 0d6dfb8a14bb6e4d123402d3c75f62f3a7c5e80a..0bee824e8797a570c94fe0401a0d4cf9b2587dce 100644 GIT binary patch delta 211 zcmdnPvxjFwC?osCuuMjdjR%AnJ(74_GK&+Fax(MM6&wSS1RRq~GRqQ6KwM8hw;;zP zeuO+kfEP)LV?c|8k%p>#gVJOvrUhb2!p`}5d8t4nfZ9v)6*BYEiV~A1Utm&`N)it# zsssw_>FFs{*DB=Z7o{qcWag$8CruV$7GpG?tj^rQm^66#gYsl4rUhcf!p`}5d8t4nfZ9v)6*BYEiV}+_Utm&`Di#kZ zsssw_>FFs{*DB=Z7o{qcWag$87f%*o7GpG-tj^rQSUh 0: - print("Trying... {} more times".format(_timeout)) + print(b"Trying... {} more times".format(_timeout)) utime.sleep_ms(1001) _timeout -= 1 else: - print("Out of retrys") + print(b"Out of retrys") return False network_config = self.sta.ifconfig() return network_config @@ -64,7 +66,7 @@ class NetSet(object): else: return False except Exception as e: - print("ERROR: Network configuration failed with: {}".format(e)) + print(b"ERROR: Network configuration failed with: {}".format(e)) return False def connectAp(self): @@ -88,10 +90,10 @@ class NetSet(object): print(b"WARNING: Fucked up option, make it better") except Exception as e: if _DEBUG: - print("WARNING: Errors in INFRA config, still going for AP") + print(b"WARNING: Errors in INFRA config, still going for AP") return False if _DEBUG: - print("CONFIG DICT: {}".format(self.config_dict)) + print(b"CONFIG DICT: {}".format(self.config_dict)) self._SSID = self.config_dict['_SSID'] self._PASS = self.config_dict['_PASS'] self._TIMEOUT = int(self.config_dict['_TIMEOUT']) diff --git a/cc1101_davis.mpy b/cc1101_davis.mpy index f4ab9026a6bdf7364e4bd11bc96ec9dfd84f43a5..1e84f098e760d36ab69d9f6b5c39d62a07449060 100644 GIT binary patch delta 998 zcmZuwU2M}<6u#F=T6yN5Oo@ChQ=BQ2`(P{wJC?D*TavMXzeF~{&kr8)KHBM2|HwB#sO6W`0}U>i+Kv(sTsNlwX*EY<2mbSYa2v>a1O+L;r$ip;>s6@F*j*xJiv z50eeHiEOd^ttiKSTqv#LY}Ry34NbaS2g#VLrv?fD`4>*sRa=#drP)cY!Bf`=TpM}j zN@9+jb$8=N@{4=W-H~G~aIW2eKA+Q4p8cko=Xqdr#9AxkPe`)XeV`5*t2CO)`>`P& zG{)~NFK*=+Hb#D}?Zqkbuyz#xNRE4&@D&pCH0bFc#1F)=WPfTq%<;%xmg+iseCiU5 zB6$J-X-9ZBsaR&_%ooxxMz>e>$K%GoflWP1qsiq3Kecn2;_0{+UpycEbWdel_QscO zoUgsTBjNR*8Ek>4v#C?;3?UsgBDS&-F|I&>=a2HSkqI#x358+He7&JRzkWBkZh$tx z_&=rncopK`X$rI|up)sn{WSt)uP#1?g>Iwp0gT-FcMhn~ZY5iXCkO9bI8hGAL$HWQ)R`(zTcR*9XXW#kc+?yH5YxarP zf}zj;f+hae@M5Pjha?kId-#?lQpS)pEKwLOO|gNb zqRh`}UbEI-_#wKysY_G#povZow7>PF?O#=}-4_z7CM9R*PBdqKLmbM-1{h@4=Ln7H SNjQywkFerX-4w3~75xXX0~&4s delta 595 zcmez5*knIpi)M=lLja>>4{z(GR?gIfR*qKgR0kl*3&h5)>_Er~AyX$ld@K~0%pi0) zqO+kvpoNV=P_=IL~xKdJ+O4Ef5H?LxUP@{OP(TJI z;FFq{UXrodot=k^@xkN}!Cc0dlMe~{F}|NHC=@2qY?3V}RFs;S;#68xTq4-;U0u^i zSzX6+a-EPuqBg^kO$|=+4dF*O2s4T>)HXJlF&*0?!eArBmXTVqts&He(Tp*&@o7ZV zb?4jlk&!~|BEn`2kz0}(7#KQ*If^r@QX5^ggoKiFQ-Vv1@{>}9CopLmF$i&s2m+OD z5Eh*LK*)|!e6qZ-9i#5%IAK{v0g2+&lAzS|%;J*NqGI6*Dw7*U^w{+E88(PmZr&`S z&92bIAt}a{mQz}sA(xzNXlP&> 8) ^ (_buffer[i])]) % 65536 - # DEBUG print("CRC: {}".format(crc)) + crc = ((crc << 8) ^ self._CRC_TABLE[(crc >> 8) ^ (_buffer[i])]) % 65536 return crc def readRssi(self): @@ -395,3 +394,41 @@ class CC1101(object): else: error = value >> 1 return error + + def reverseBits(self, data): + data = "{:08b}".format(data) + z = "" + for i in range(len(data),0,-1): + z = z + (data[i-1]) + return int(z, 2) + + def rxPacket(self): + data_length = self.readRegister(self.CC1101_RXBYTES) + #data = "" + if data_length & 0x7f == 15: + data = bytearray(self.DAVIS_PACKET_LENGTH) + data = self.readBurst(self.CC1101_RXFIFO, self.DAVIS_PACKET_LENGTH) + self.rssi = self.readRssi() + self.lqi = self.readLQI() + freqEst = self.readStatus(self.CC1101_FREQEST) + freqError = self.calcFreqError(freqEst) + if DEBUG: + print(b"FERROR: {} (EST: {})".format(freqError, freqEst)) + print(b"FCOMP: {}".format(davis.freqComp)) + if self.freqComp[self.hopIndex] + freqEst <= 255: + self.freqComp[self.hopIndex] = self.freqComp[self.hopIndex] + freqEst + else: + self.freqComp[self.hopIndex] = 255 + self.flush() + self.hop() + self.rx() + data_int = [self.reverseBits(int(item)) for item in data] + crc = self.calcCrc(data_int[:8]) + if crc != 0x0000: + print(b"Corrupt data CRC: {}".format(crc)) + return False + else: + print(b"Data OK, CRC: {}".format(crc)) + return data_int + else: + return False diff --git a/davis_decode.mpy b/davis_decode.mpy index e30be792f4074bde9e960feb514d85252db2d98f..05051c6cd95e179b602e809020b8b3332d8816ea 100644 GIT binary patch delta 85 zcmZ22yIOWb29sbCU$Cp6i>IHvLWsYWLUnD@IHvLWsYWLUnEN