diff --git a/.gitignore b/.gitignore index beced4e..e943765 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,15 @@ *.conf .DS_Store +pyscan/* +pysense/* +pysense2/* +pytrack/* +pytrack2/* + +pyscan.zip +pysense.zip +pysense2.zip +pytrack.zip +pytrack2.zip + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..17034ef --- /dev/null +++ b/Makefile @@ -0,0 +1,102 @@ +release: pyscan pysense pysense2 pytrack pytrack2 + + +pyscan: + rm -rf pyscan + rm -f pyscan.zip + @echo "Making Pyscan" + mkdir pyscan + mkdir pyscan/lib + #sensors + cp shields/lib/LIS2HH12.py pyscan/lib/ + cp shields/lib/MFRC630.py pyscan/lib/ + cp shields/lib/SI7006A20.py pyscan/lib/ + cp shields/lib/LTR329ALS01.py pyscan/lib/ + #pycoproc + cp shields/lib/pycoproc_1.py pyscan/lib/ + #example + cp shields/pyscan_1.py pyscan/main.py + + zip -r pyscan.zip pyscan + +pysense: + rm -rf pysense + rm -f pysense.zip + @echo "Making Pysense" + mkdir pysense + mkdir pysense/lib + # sensors + cp shields/lib/LIS2HH12.py pysense/lib/ + cp shields/lib/LTR329ALS01.py pysense/lib/ + cp shields/lib/MPL3115A2.py pysense/lib/ + cp shields/lib/SI7006A20.py pysense/lib/ + # pycoproc + cp shields/lib/pycoproc_1.py pysense/lib/ + # example + cp shields/pysense_1.py pysense/main.py + + zip -r pysense.zip pysense + +pysense2: + rm -rf pysense2 + rm -f pysense2.zip + @echo "Making Pysense 2" + mkdir pysense2 + mkdir pysense2/lib + # sensors + cp shields/lib/LIS2HH12.py pysense2/lib/ + cp shields/lib/LTR329ALS01.py pysense2/lib/ + cp shields/lib/MPL3115A2.py pysense2/lib/ + cp shields/lib/SI7006A20.py pysense2/lib/ + # pycoproc + cp shields/lib/pycoproc_2.py pysense2/lib/ + # example + cp shields/pysense_2.py pysense2/main.py + + zip -r pysense2.zip pysense2 + +pytrack: + rm -rf pytrack + rm -f pytrack.zip + @echo "Making Pytrack" + mkdir pytrack + mkdir pytrack/lib + #sensors + cp shields/lib/L76GNSS.py pytrack/lib/ + cp shields/lib/LIS2HH12.py pytrack/lib/ + #pycoproc + cp shields/lib/pycoproc_1.py pytrack/lib/ + #example + cp shields/pytrack_1.py pytrack/main.py + + zip -r pytrack.zip pytrack + +pytrack2: + rm -rf pytrack2 + rm -f pytrack2.zip + @echo "Making Pytrack2" + mkdir pytrack2 + mkdir pytrack2/lib + #sensors + cp shields/lib/L76GNSS.py pytrack2/lib/ + cp shields/lib/LIS2HH12.py pytrack2/lib/ + #pycoproc + cp shields/lib/pycoproc_2.py pytrack2/lib/ + #example + cp shields/pytrack_2.py pytrack2/main.py + + zip -r pytrack2.zip pytrack2 + +clean: + @echo "Cleaning up files" + rm -rf pyscan + rm -rf pysense + rm -rf pysense2 + rm -rf pytrack + rm -rf pytrack2 + + rm -f pyscan.zip + rm -f pysense.zip + rm -f pysense2.zip + rm -f pytrack.zip + rm -f pytrack2.zip \ No newline at end of file diff --git a/README.md b/README.md index 178f449..ce4e46c 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,12 @@ # Pycom Libraries and Examples ## Introduction -This repository contains out of the box examples for Pycom devices, including Pysense, Pytrack, and Pyscan. +This repository contains libraries and out of the box examples for Pycom devices, including the Shields: Pysense, Pytrack, and Pyscan. ## Table of Contents * [Examples](/examples) * [Libraries](/lib) -* [Pysense](/pysense) -* [Pytrack](/pytrack) -* [Pyscan](/pyscan) -* [Pybytes](/pybytes) - -## Pysense, Pytrack, Pyscan - -To install the required libraries for Pysense, Pytrack, and Pyscan, please download this repo as a ZIP file. You will then be able to extract and upload the library files to your Pycom device (via FTP or Pymakr Plugin). Please see [docs.pycom.io](https://docs.pycom.io) for more information. +* [Shields](/shields) ## Links * [Pycom](https://pycom.io) diff --git a/lib/sqnsupgrade/README.md b/lib/sqnsupgrade/README.md index 7646d50..e6ec433 100644 --- a/lib/sqnsupgrade/README.md +++ b/lib/sqnsupgrade/README.md @@ -12,7 +12,7 @@ Please start with the following steps: 1. Upgrade the Pycom Firmware Updater tool to latest version 2. Select Firmware Type `stable` in the communication window to upgrade to latest stable version -You can find the different versions of firmwares available here: http://software.pycom.io/downloads/sequans2.html​ +You can find the different versions of firmwares available here: http://software.pycom.io/downloads/sequans2.html These files are password protected, to download them you should be a forum.pycom.io member and access to: Announcements & News --> Announcements only for members --> Firmware Files for Sequans LTE modem now are secured, or clicking Here diff --git a/pymesh/pymesh_frozen/lib/pymesh_config.py b/pymesh/pymesh_frozen/lib/pymesh_config.py index 798f8f8..74a0292 100644 --- a/pymesh/pymesh_frozen/lib/pymesh_config.py +++ b/pymesh/pymesh_frozen/lib/pymesh_config.py @@ -5,7 +5,6 @@ see the Pycom Licence v1.0 document supplied with this file, or available at https://www.pycom.io/opensource/licensing ''' -import ubinascii import json from network import LoRa @@ -78,10 +77,7 @@ def write_config(pymesh_config, force_restart = False): time.sleep(1) machine.deepsleep(1000) - def check_mac(pymesh_config): - lora = LoRa(mode=LoRa.LORA, region= LoRa.EU868) - MAC = int(str(ubinascii.hexlify(lora.mac()))[2:-1], 16) - + def check_mac(pymesh_config, MAC): if pymesh_config.get('MAC') is None: # if MAC config unspecified, set it to LoRa MAC print_debug(3, "Set MAC in config file as " + str(MAC)) @@ -102,7 +98,7 @@ def check_mac(pymesh_config): print_debug(3, "MAC ok" + str(MAC)) - def read_config(): + def read_config(MAC): file = PymeshConfig.CONFIG_FILENAME pymesh_config = {} error_file = True @@ -138,10 +134,10 @@ def read_config(): pymesh_config['br_ena'] = PymeshConfig.BR_ENABLE pymesh_config['br_prio'] = PymeshConfig.BR_PRIORITY - PymeshConfig.check_mac(pymesh_config) + PymeshConfig.check_mac(pymesh_config, MAC) print_debug(3, "Default settings:" + str(pymesh_config)) PymeshConfig.write_config(pymesh_config, True) - PymeshConfig.check_mac(pymesh_config) + PymeshConfig.check_mac(pymesh_config, MAC) print_debug(3, "Settings:" + str(pymesh_config)) return pymesh_config diff --git a/pymesh/pymesh_frozen/lorawan/main.py b/pymesh/pymesh_frozen/lorawan/main.py index 223cee6..33f33da 100644 --- a/pymesh/pymesh_frozen/lorawan/main.py +++ b/pymesh/pymesh_frozen/lorawan/main.py @@ -1,5 +1,7 @@ -import pycom import time +import ubinascii +import pycom +from network import LoRa try: from pymesh_config import PymeshConfig @@ -28,8 +30,11 @@ def new_message_cb(rcv_ip, rcv_port, rcv_data): pycom.heartbeat(False) +lora = LoRa(mode=LoRa.LORA, region= LoRa.EU868) +lora_mac = int(str(ubinascii.hexlify(lora.mac()))[2:-1], 16) + # read config file, or set default values -pymesh_config = PymeshConfig.read_config() +pymesh_config = PymeshConfig.read_config(lora_mac) #initialize Pymesh pymesh = Pymesh(pymesh_config, new_message_cb) diff --git a/pymesh/pymesh_frozen/main.py b/pymesh/pymesh_frozen/main.py index 4cf6fbd..5d7c17a 100644 --- a/pymesh/pymesh_frozen/main.py +++ b/pymesh/pymesh_frozen/main.py @@ -1,5 +1,7 @@ -import pycom import time +import ubinascii +import pycom +from network import LoRa try: from pymesh_config import PymeshConfig @@ -28,8 +30,11 @@ def new_message_cb(rcv_ip, rcv_port, rcv_data): pycom.heartbeat(False) +lora = LoRa(mode=LoRa.LORA, region= LoRa.EU868) +lora_mac = int(str(ubinascii.hexlify(lora.mac()))[2:-1], 16) + # read config file, or set default values -pymesh_config = PymeshConfig.read_config() +pymesh_config = PymeshConfig.read_config(lora_mac) #initialize Pymesh pymesh = Pymesh(pymesh_config, new_message_cb) diff --git a/pymesh/pymesh_frozen/main_BR.py b/pymesh/pymesh_frozen/main_BR.py index 3c53257..fdb9780 100644 --- a/pymesh/pymesh_frozen/main_BR.py +++ b/pymesh/pymesh_frozen/main_BR.py @@ -1,5 +1,7 @@ import time +import ubinascii import pycom +from network import LoRa # 2 = test pybytes OTA feature # 4 = added device_id (pybytes token) in the packets to BR @@ -66,8 +68,11 @@ def new_br_message_cb(rcv_ip, rcv_port, rcv_data, dest_ip, dest_port): pycom.heartbeat(False) +lora = LoRa(mode=LoRa.LORA, region= LoRa.EU868) +lora_mac = int(str(ubinascii.hexlify(lora.mac()))[2:-1], 16) + # read config file, or set default values -pymesh_config = PymeshConfig.read_config() +pymesh_config = PymeshConfig.read_config(lora_mac) #initialize Pymesh pymesh = Pymesh(pymesh_config, new_message_cb) diff --git a/pymesh/readme.md b/pymesh/readme.md new file mode 100644 index 0000000..0be1a7a --- /dev/null +++ b/pymesh/readme.md @@ -0,0 +1,3 @@ +# For reference only + +This library is the open-source part of the Pymesh LoRa Firmware which can be provisioned through Pybytes and cannot be used as stand-alone on a Pybytes or Pygate type firmware. Please check the [Pycom Documentation](https://docs.pycom.io/pybytes/pymeshintegration/provisioning/) on how to get Pymesh type firmware provisioned to your device. You will not have to use this library in your project or flash it to your device separately, as it is already included in the firmware. diff --git a/shields/README.md b/shields/README.md index e8ecf84..0586192 100644 --- a/shields/README.md +++ b/shields/README.md @@ -9,5 +9,5 @@ This directory contains libraries and out of the box examples for Pysense, Pytra 2. Open Pymakr 3. Run an example that matches to your shield -Note: Note: For using Pyscan, you need to upload either MFRC630.mpy or MFRC630.py. +Note: For using Pyscan, you need to upload either MFRC630.mpy or MFRC630.py. It is always recommended to use MFRC630.mpy as it takes less space on your module. diff --git a/shields/lib/L76GNSS.py b/shields/lib/L76GNSS.py index 37cc2fd..c493eb1 100644 --- a/shields/lib/L76GNSS.py +++ b/shields/lib/L76GNSS.py @@ -113,7 +113,7 @@ def _checksum(self, nmeadata): calc_cksum = 0 for s in nmeadata: calc_cksum ^= ord(s) - return('{:X}'.format(calc_cksum)) + return('{:02X}'.format(calc_cksum)) def write(self, data): self.i2c.writeto(GPS_I2CADDR, '${}*{}\r\n'.format(data, self._checksum(data)) ) diff --git a/shields/lib/LTR329ALS01.py b/shields/lib/LTR329ALS01.py index 9087156..8915ac4 100644 --- a/shields/lib/LTR329ALS01.py +++ b/shields/lib/LTR329ALS01.py @@ -28,6 +28,14 @@ class LTR329ALS01: ALS_GAIN_8X = const(0x03) ALS_GAIN_48X = const(0x06) ALS_GAIN_96X = const(0x07) + ALS_GAIN_VALUES = { + ALS_GAIN_1X: 1, + ALS_GAIN_2X: 2, + ALS_GAIN_4X: 4, + ALS_GAIN_8X: 8, + ALS_GAIN_48X: 48, + ALS_GAIN_96X: 96 + } ALS_INT_50 = const(0x01) ALS_INT_100 = const(0x00) @@ -37,6 +45,16 @@ class LTR329ALS01: ALS_INT_300 = const(0x06) ALS_INT_350 = const(0x07) ALS_INT_400 = const(0x03) + ALS_INT_VALUES = { + ALS_INT_50: 0.5, + ALS_INT_100: 1, + ALS_INT_150: 1.5, + ALS_INT_200: 2, + ALS_INT_250: 2.5, + ALS_INT_300: 3, + ALS_INT_350: 3.5, + ALS_INT_400: 4 + } ALS_RATE_50 = const(0x00) ALS_RATE_100 = const(0x01) @@ -51,6 +69,9 @@ def __init__(self, pysense = None, sda = 'P22', scl = 'P21', gain = ALS_GAIN_1X, else: self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl)) + self.gain = gain + self.integration = integration + contr = self._getContr(gain) self.i2c.writeto_mem(ALS_I2CADDR, ALS_CONTR_REG, bytearray([contr])) @@ -78,3 +99,19 @@ def light(self): data0 = int(self._getWord(ch0high[0], ch0low[0])) return (data0, data1) + + def lux(self): + # Calculate Lux value from formular in Appendix A of the datasheet + light_level = self.light() + if light_level[0]+light_level[1] > 0: + ratio = light_level[1]/(light_level[0]+light_level[1]) + if ratio < 0.45: + return (1.7743 * light_level[0] + 1.1059 * light_level[1]) / self.ALS_GAIN_VALUES[self.gain] / self.ALS_INT_VALUES[self.integration] + elif ratio < 0.64 and ratio >= 0.45: + return (4.2785 * light_level[0] - 1.9548 * light_level[1]) / self.ALS_GAIN_VALUES[self.gain] / self.ALS_INT_VALUES[self.integration] + elif ratio < 0.85 and ratio >= 0.64: + return (0.5926 * light_level[0] + 0.1185 * light_level[1]) / self.ALS_GAIN_VALUES[self.gain] / self.ALS_INT_VALUES[self.integration] + else: + return 0 + else: + return 0 diff --git a/lib/MFRC630/MFRC630.py b/shields/lib/MFRC630.py similarity index 97% rename from lib/MFRC630/MFRC630.py rename to shields/lib/MFRC630.py index 574bc40..0d6c2f2 100644 --- a/lib/MFRC630/MFRC630.py +++ b/shields/lib/MFRC630.py @@ -370,7 +370,7 @@ def mfrc630_MF_read_block(self, block_address, dest): buffer_length = self.mfrc630_fifo_length() rx_len = buffer_length if (buffer_length <= 16) else 16 dest = self.mfrc630_read_fifo(rx_len) - return rx_len + return dest def mfrc630_iso14443a_WUPA_REQA(self, instruction): diff --git a/shields/lib/MPL3115A2.py b/shields/lib/MPL3115A2.py index b0a44c7..ce90631 100644 --- a/shields/lib/MPL3115A2.py +++ b/shields/lib/MPL3115A2.py @@ -79,8 +79,10 @@ def __init__(self, pysense = None, sda = 'P22', scl = 'P21', mode = PRESSURE): raise MPL3115A2exception("Error with MPL3115A2") def _read_status(self): - while True: + read_attempts = 0 + while read_attempts < 500: self.i2c.readfrom_mem_into(MPL3115_I2CADDR, MPL3115_STATUS, self.STA_reg) + read_attempts += 1 if(self.STA_reg[0] == 0): time.sleep(0.01) @@ -90,6 +92,11 @@ def _read_status(self): else: return False + # If we get here the sensor isn't responding. Reset it so next time in it should work + self.i2c.writeto_mem(MPL3115_I2CADDR, MPL3115_CTRL_REG1, bytes([0x00])) # put into standby + self.i2c.writeto_mem(MPL3115_I2CADDR, MPL3115_CTRL_REG1, bytes([0x04])) # reset + return False + def pressure(self): if self.mode == ALTITUDE: raise MPL3115A2exception("Incorrect Measurement Mode MPL3115A2") diff --git a/shields/lib/SI7006A20.py b/shields/lib/SI7006A20.py index d9a4025..f49a302 100644 --- a/shields/lib/SI7006A20.py +++ b/shields/lib/SI7006A20.py @@ -22,8 +22,18 @@ class SI7006A20: SI7006A20_I2C_ADDR = const(0x40) + # I2C commands TEMP_NOHOLDMASTER = const(0xF3) HUMD_NOHOLDMASTER = const(0xF5) + WRITE_USER_REG1 = const(0xE6) + READ_USER_REG1 = const(0xE7) + WRITE_HEATER_CTRL_REG = const(0x51) + READ_HEATER_CTRL_REG = const(0x11) + + # Register masks and offsets + USER_REG1_HTR_ENABLE_MASK = const(0b00000100) + USER_REG1_HTR_ENABLE_OFFSET = const(0x02) + HTR_CTRL_REG_MASK = const(0b00001111) def __init__(self, pysense = None, sda = 'P22', scl = 'P21'): if pysense is not None: @@ -55,18 +65,32 @@ def humidity(self): def read_user_reg(self): """ reading the user configuration register """ - self.i2c.writeto(SI7006A20_I2C_ADDR, bytearray([0xE7])) + self.i2c.writeto(SI7006A20_I2C_ADDR, bytearray([READ_USER_REG1])) time.sleep(0.5) data = self.i2c.readfrom(SI7006A20_I2C_ADDR, 1) return data[0] def read_heater_reg(self): """ reading the heater configuration register """ - self.i2c.writeto(SI7006A20_I2C_ADDR, bytearray([0x11])) + self.i2c.writeto(SI7006A20_I2C_ADDR, bytearray([READ_HEATER_CTRL_REG])) time.sleep(0.5) data = self.i2c.readfrom(SI7006A20_I2C_ADDR, 1) return data[0] + def write_heater_reg(self, heater_value): + """ writing the heater configuration register """ + # We should only set the bottom four bits of this register + heater_setting = heater_value & HTR_CTRL_REG_MASK + self.write_reg(WRITE_HEATER_CTRL_REG, heater_setting) + + def heater_control(self, on_off): + """ turn the heater on or off """ + # Get current settings for everything else + user_reg = self.read_user_reg() + # Set the heater bit + user_reg = (user_reg & ~USER_REG1_HTR_ENABLE_MASK) | (on_off << USER_REG1_HTR_ENABLE_OFFSET) + self.write_reg(WRITE_USER_REG1, user_reg) + def read_electronic_id(self): """ reading electronic identifier """ self.i2c.writeto(SI7006A20_I2C_ADDR, bytearray([0xFA]) + bytearray([0x0F])) diff --git a/shields/lib/pycoproc_1.py b/shields/lib/pycoproc_1.py index 48fa051..a8f7e82 100644 --- a/shields/lib/pycoproc_1.py +++ b/shields/lib/pycoproc_1.py @@ -127,7 +127,7 @@ def __init__(self, board_type, i2c=None, sda='P22', scl='P21'): self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 7)) if self.read_fw_version() < 6: - raise ValueError('Firmware out of date') + raise ValueError('Firmware for Shield1 out of date') def _write(self, data, wait=True): diff --git a/shields/lib/pycoproc_2.py b/shields/lib/pycoproc_2.py index b563d3b..a1ead51 100644 --- a/shields/lib/pycoproc_2.py +++ b/shields/lib/pycoproc_2.py @@ -152,7 +152,7 @@ def __init__(self, i2c=None, sda='P22', scl='P21'): # for Pysense/Pytrack 2.0, the minimum firmware version is 15 fw = self.read_fw_version() if fw < 16: - raise ValueError('Firmware out of date', fw) + raise ValueError('Firmware for Shield2 out of date', fw) # init the ADC for the battery measurements self.write_byte(ANSELC_ADDR, 1 << 2) # RC2 analog input diff --git a/shields/pyscan_1.py b/shields/pyscan_1.py index 66ab94e..9e9c263 100644 --- a/shields/pyscan_1.py +++ b/shields/pyscan_1.py @@ -1,86 +1,114 @@ ''' Simple Pyscan NFC / MiFare Classic Example -Copyright (c) 2020, Pycom Limited. +Copyright (c) 2019, Pycom Limited. -This example runs the NFC discovery loop in a thread. -If a card is detected it will read the UID and compare it to VALID_CARDS -RGB LED is BLUE while waiting for card, -GREEN if card is valid, RED if card is invalid +This example continuously sends a REQA for ISO14443A card type +If a card is discovered, it will read the UID +If DECODE_CARD = True, will attempt to authenticate with CARDkey +If authentication succeeds will attempt to read sectors from the card ''' -DEBUG = False # change to True to see debug messages - from pycoproc_1 import Pycoproc from MFRC630 import MFRC630 from LIS2HH12 import LIS2HH12 from LTR329ALS01 import LTR329ALS01 -import binascii import time import pycom -import _thread +#add your card UID here VALID_CARDS = [[0x43, 0x95, 0xDD, 0xF8], [0x43, 0x95, 0xDD, 0xF9], [0x46, 0x5A, 0xEB, 0x7D, 0x8A, 0x08, 0x04]] + +# This is the default key for an unencrypted MiFare card +CARDkey = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ] +DECODE_CARD = False + py = Pycoproc(Pycoproc.PYSCAN) nfc = MFRC630(py) lt = LTR329ALS01(py) li = LIS2HH12(py) +pybytes_enabled = False +if 'pybytes' in globals(): + if(pybytes.isconnected()): + print('Pybytes is connected, sending signals to Pybytes') + pybytes_enabled = True + RGB_BRIGHTNESS = 0x8 RGB_RED = (RGB_BRIGHTNESS << 16) RGB_GREEN = (RGB_BRIGHTNESS << 8) RGB_BLUE = (RGB_BRIGHTNESS) +counter = 0 + +def check_uid(uid, len): + return VALID_CARDS.count(uid[:len]) + +def send_sensor_data(name, timeout): + if(pybytes_enabled): + while(True): + pybytes.send_signal(2, lt.light()) + pybytes.send_signal(3, li.acceleration()) + time.sleep(timeout) + # Make sure heartbeat is disabled before setting RGB LED pycom.heartbeat(False) # Initialise the MFRC630 with some settings nfc.mfrc630_cmd_init() -def check_uid(uid, len): - return VALID_CARDS.count(uid[:len]) - -def print_debug(msg): - if DEBUG: - print(msg) - -def send_sensor_data(name, timeout): - while(True): - print(lt.light()) - print(li.acceleration()) - time.sleep(timeout) - -def discovery_loop(nfc, id): - while True: - # Send REQA for ISO14443A card type - print_debug('Sending REQA for ISO14443A card type...') - atqa = nfc.mfrc630_iso14443a_WUPA_REQA(nfc.MFRC630_ISO14443_CMD_REQA) - print_debug('Response: {}'.format(atqa)) - if (atqa != 0): - # A card has been detected, read UID - print_debug('A card has been detected, read UID...') - uid = bytearray(10) - uid_len = nfc.mfrc630_iso14443a_select(uid) - print_debug('UID has length: {}'.format(uid_len)) - if (uid_len > 0): - print_debug('Checking if card with UID: [{:s}] is listed in VALID_CARDS...'.format(binascii.hexlify(uid[:uid_len],' ').upper())) +print('Scanning for cards') +while True: + # Send REQA for ISO14443A card type + atqa = nfc.mfrc630_iso14443a_WUPA_REQA(nfc.MFRC630_ISO14443_CMD_REQA) + if (atqa != 0): + # A card has been detected, read UID + print('A card has been detected, reading its UID ...') + uid = bytearray(10) + uid_len = nfc.mfrc630_iso14443a_select(uid) + print('UID has length {}'.format(uid_len)) + if (uid_len > 0): + # A valid UID has been detected, print details + counter += 1 + print("%d\tUID [%d]: %s" % (counter, uid_len, nfc.format_block(uid, uid_len))) + if DECODE_CARD: + # Try to authenticate with CARD key + nfc.mfrc630_cmd_load_key(CARDkey) + for sector in range(0, 16): + if (nfc.mfrc630_MF_auth(uid, nfc.MFRC630_MF_AUTH_KEY_A, sector * 4)): + pycom.rgbled(RGB_GREEN) + # Authentication was sucessful, read card data + readbuf = bytearray(16) + for b in range(0, 4): + f_sect = sector * 4 + b + len = nfc.mfrc630_MF_read_block(f_sect, readbuf) + print("\t\tSector %s: Block: %s: %s" % (nfc.format_block([sector], 1), nfc.format_block([b], 1), nfc.format_block(readbuf, len))) + else: + print("Authentication denied for sector %s!" % nfc.format_block([sector], 1)) + pycom.rgbled(RGB_RED) + # It is necessary to call mfrc630_MF_deauth after authentication + # Although this is also handled by the reset / init cycle + nfc.mfrc630_MF_deauth() + else: + #check if card uid is listed in VALID_CARDS if (check_uid(list(uid), uid_len)) > 0: - print_debug('Card is listed, turn LED green') + print('Card is listed, turn LED green') pycom.rgbled(RGB_GREEN) + if(pybytes_enabled): + pybytes.send_signal(1, ('Card is listed', uid)) else: - print_debug('Card is not listed, turn LED red') + print('Card is not listed, turn LED red') pycom.rgbled(RGB_RED) - else: - # No card detected - print_debug('Did not detect any card...') - pycom.rgbled(RGB_BLUE) - nfc.mfrc630_cmd_reset() - time.sleep(.5) - nfc.mfrc630_cmd_init() - -# This is the start of our main execution... start the thread -_thread.start_new_thread(discovery_loop, (nfc, 0)) -_thread.start_new_thread(send_sensor_data, ('Thread 2', 10)) + if(pybytes_enabled): + pybytes.send_signal(1, ('Unauthorized card detected', uid)) + + else: + pycom.rgbled(RGB_BLUE) + # We could go into power saving mode here... to be investigated + nfc.mfrc630_cmd_reset() + time.sleep(.5) + # Re-Initialise the MFRC630 with settings as these got wiped during reset + nfc.mfrc630_cmd_init() diff --git a/shields/pyscan_1_nfc.py b/shields/pyscan_1_nfc.py deleted file mode 100644 index 6b2ea36..0000000 --- a/shields/pyscan_1_nfc.py +++ /dev/null @@ -1,75 +0,0 @@ -''' -Simple Pyscan NFC / MiFare Classic Example -Copyright (c) 2019, Pycom Limited. - -This example continuously sends a REQA for ISO14443A card type -If a card is discovered, it will read the UID -If DECODE_CARD = True, will attempt to authenticate with CARDkey -If authentication succeeds will attempt to read sectors from the card -''' - -from pycoproc_1 import Pycoproc -from MFRC630 import MFRC630 -import time -import pycom - -# This is the default key for an unencrypted MiFare card -CARDkey = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ] -DECODE_CARD = False - -py = Pycoproc(Pycoproc.PYSCAN) -nfc = MFRC630(py) - -RGB_BRIGHTNESS = 0x8 - -RGB_RED = (RGB_BRIGHTNESS << 16) -RGB_GREEN = (RGB_BRIGHTNESS << 8) -RGB_BLUE = (RGB_BRIGHTNESS) - -counter = 0 - -# Make sure heartbeat is disabled before setting RGB LED -pycom.heartbeat(False) - -# Initialise the MFRC630 with some settings -nfc.mfrc630_cmd_init() - -while True: - # Send REQA for ISO14443A card type - atqa = nfc.mfrc630_iso14443a_WUPA_REQA(nfc.MFRC630_ISO14443_CMD_REQA) - if (atqa != 0): - # A card has been detected, read UID - uid = bytearray(10) - uid_len = nfc.mfrc630_iso14443a_select(uid) - if (uid_len > 0): - # A valid UID has been detected, print details - counter += 1 - print("%d\tUID [%d]: %s" % (counter, uid_len, nfc.format_block(uid, uid_len))) - if DECODE_CARD: - # Try to authenticate with CARD key - nfc.mfrc630_cmd_load_key(CARDkey) - for sector in range(0, 16): - if (nfc.mfrc630_MF_auth(uid, nfc.MFRC630_MF_AUTH_KEY_A, sector * 4)): - pycom.rgbled(RGB_GREEN) - # Authentication was sucessful, read card data - readbuf = bytearray(16) - for b in range(0, 4): - f_sect = sector * 4 + b - len = nfc.mfrc630_MF_read_block(f_sect, readbuf) - print("\t\tSector %s: Block: %s: %s" % (nfc.format_block([sector], 1), nfc.format_block([b], 1), nfc.format_block(readbuf, len))) - else: - print("Authentication denied for sector %s!" % nfc.format_block([sector], 1)) - pycom.rgbled(RGB_RED) - # It is necessary to call mfrc630_MF_deauth after authentication - # Although this is also handled by the reset / init cycle - nfc.mfrc630_MF_deauth() - else: - # If we're not trying to authenticate, show green when a UID > 0 has been detected - pycom.rgbled(RGB_GREEN) - else: - pycom.rgbled(RGB_BLUE) - # We could go into power saving mode here... to be investigated - nfc.mfrc630_cmd_reset() - time.sleep(.5) - # Re-Initialise the MFRC630 with settings as these got wiped during reset - nfc.mfrc630_cmd_init() diff --git a/shields/pyscan_1_pybytes.py b/shields/pyscan_1_pybytes.py deleted file mode 100644 index 458b743..0000000 --- a/shields/pyscan_1_pybytes.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2019, Pycom Limited. -# -# This software is licensed under the GNU GPL version 3 or any -# later version, with permitted additional terms. For more information -# see the Pycom Licence v1.0 document supplied with this file, or -# available at https://www.pycom.io/opensource/licensing -# - -''' -Simple Pyscan NFC / MiFare Classic Example -Copyright (c) 2019, Pycom Limited. -This example runs the NFC discovery loop in a thread. -If a card is detected it will read the UID and compare it to VALID_CARDS -RGB LED is BLUE while waiting for card, -GREEN if card is valid, RED if card is invalid -''' - -DEBUG = False # change to True to see debug messages - -from pycoproc_1 import Pycoproc -from MFRC630 import MFRC630 -from LIS2HH12 import LIS2HH12 -from LTR329ALS01 import LTR329ALS01 -import binascii -import time -import pycom -import _thread - -VALID_CARDS = [[0x43, 0x95, 0xDD, 0xF8], - [0x43, 0x95, 0xDD, 0xF9]] - -py = Pycoproc(Pycoproc.PYSENSE) -nfc = MFRC630(py) -lt = LTR329ALS01(py) -li = LIS2HH12(py) - -RGB_BRIGHTNESS = 0x8 - -RGB_RED = (RGB_BRIGHTNESS << 16) -RGB_GREEN = (RGB_BRIGHTNESS << 8) -RGB_BLUE = (RGB_BRIGHTNESS) - -# Make sure heartbeat is disabled before setting RGB LED -pycom.heartbeat(False) - -# Initialise the MFRC630 with some settings -nfc.mfrc630_cmd_init() - -def check_uid(uid, len): - return VALID_CARDS.count(uid[:len]) - -def print_debug(msg): - if DEBUG: - print(msg) - -def send_sensor_data(name, timeout): - while(pybytes): - pybytes.send_signal(2, lt.light()) - pybytes.send_signal(3, li.acceleration()) - time.sleep(timeout) - -def discovery_loop(arg1, arg2): - while(pybytes): - # Send REQA for ISO14443A card type - print_debug('Sending REQA for ISO14443A card type...') - atqa = nfc.mfrc630_iso14443a_WUPA_REQA(nfc.MFRC630_ISO14443_CMD_REQA) - print_debug('Response: {}'.format(atqa)) - if (atqa != 0): - # A card has been detected, read UID - print_debug('A card has been detected, read UID...') - uid = bytearray(10) - uid_len = nfc.mfrc630_iso14443a_select(uid) - print_debug('UID has length: {}'.format(uid_len)) - if (uid_len > 0): - print_debug('Checking if card with UID: [{:s}] is listed in VALID_CARDS...'.format(binascii.hexlify(uid[:uid_len],' ').upper())) - if (check_uid(list(uid), uid_len)) > 0: - print_debug('Card is listed, turn LED green') - pycom.rgbled(RGB_GREEN) - pybytes.send_signal(1, ('Card is listed, Access granted', uid)) - else: - print_debug('Card is not listed, turn LED red') - pycom.rgbled(RGB_RED) - pybytes.send_signal(1, ('Card is not listed, Access denied', uid)) - else: - # No card detected - print_debug('Did not detect any card...') - pycom.rgbled(RGB_BLUE) - pybytes.send_signal(1, ('Did not detect any card', 0)) - nfc.mfrc630_cmd_reset() - time.sleep(5) - nfc.mfrc630_cmd_init() - - -# This is the start of our main execution... start the thread -_thread.start_new_thread(discovery_loop, (nfc, 0)) -_thread.start_new_thread(send_sensor_data, ('Thread 2',10)) diff --git a/shields/pysense_1.py b/shields/pysense_1.py index 0a0d4b1..2a4e126 100644 --- a/shields/pysense_1.py +++ b/shields/pysense_1.py @@ -25,13 +25,18 @@ py = Pycoproc(Pycoproc.PYSENSE) +pybytes_enabled = False +if 'pybytes' in globals(): + if(pybytes.isconnected()): + print('Pybytes is connected, sending signals to Pybytes') + pybytes_enabled = True + mp = MPL3115A2(py,mode=ALTITUDE) # Returns height in meters. Mode may also be set to PRESSURE, returning a value in Pascals print("MPL3115A2 temperature: " + str(mp.temperature())) print("Altitude: " + str(mp.altitude())) mpp = MPL3115A2(py,mode=PRESSURE) # Returns pressure in Pa. Mode may also be set to ALTITUDE, returning a value in meters print("Pressure: " + str(mpp.pressure())) - si = SI7006A20(py) print("Temperature: " + str(si.temperature())+ " deg C and Relative Humidity: " + str(si.humidity()) + " %RH") print("Dew point: "+ str(si.dew_point()) + " deg C") @@ -47,8 +52,20 @@ print("Roll: " + str(li.roll())) print("Pitch: " + str(li.pitch())) -print("Battery voltage: " + str(py.read_battery_voltage())) +# set your battery voltage limits here +vmax = 4.2 +vmin = 3.3 +battery_voltage = py.read_battery_voltage() +battery_percentage = (battery_voltage - vmin / (vmax - vmin))*100 +print("Battery voltage: " + str(py.read_battery_voltage()), " percentage: ", battery_percentage) +if(pybytes_enabled): + pybytes.send_signal(1, mpp.pressure()) + pybytes.send_signal(2, si.temperature()) + pybytes.send_signal(3, lt.light()) + pybytes.send_signal(4, li.acceleration()) + pybytes.send_battery_level(int(battery_percentage)) + print("Sent data to pybytes") -time.sleep(3) +time.sleep(5) py.setup_sleep(10) py.go_to_sleep() diff --git a/shields/pysense_1_pybytes.py b/shields/pysense_1_pybytes.py deleted file mode 100644 index 2d3326d..0000000 --- a/shields/pysense_1_pybytes.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2019, Pycom Limited. -# -# This software is licensed under the GNU GPL version 3 or any -# later version, with permitted additional terms. For more information -# see the Pycom Licence v1.0 document supplied with this file, or -# available at https://www.pycom.io/opensource/licensing -# - -# See https://docs.pycom.io for more information regarding library specifics - -from pycoproc_1 import Pycoproc -from LIS2HH12 import LIS2HH12 -from SI7006A20 import SI7006A20 -from LTR329ALS01 import LTR329ALS01 -from MPL3115A2 import MPL3115A2,ALTITUDE,PRESSURE - -py = Pycoproc(Pycoproc.PYSENSE) -mp = MPL3115A2(py,mode=ALTITUDE) # Returns height in meters. Mode may also be set to PRESSURE, returning a value in Pascals -si = SI7006A20(py) -lt = LTR329ALS01(py) -li = LIS2HH12(py) - -import _thread -from time import sleep -import uos - -def send_sensor_data(): - h2 = None - t2 = None - l2 = None - while (pybytes): - h = round(si.humidity(),1) - t = round(si.temperature(),1) - l = lt.light() - if h != h2: - print('humidity', h) - pybytes.send_signal(1, h) - h2=h - if t != t2: - print('temperature', t) - pybytes.send_signal(2, t) - t2=t - if l != l2: - print('luminocity', l) - pybytes.send_signal(3, l) - l2=l - sleep(10) - -# _thread.start_new_thread(send_sensor_data, ()) -send_sensor_data() diff --git a/shields/pysense_2.py b/shields/pysense_2.py index cfa6280..ff793e7 100644 --- a/shields/pysense_2.py +++ b/shields/pysense_2.py @@ -24,6 +24,14 @@ pycom.rgbled(0x0A0A08) # white py = Pycoproc() +if py.read_product_id() != Pycoproc.USB_PID_PYSENSE: + raise Exception('Not a Pysense') + +pybytes_enabled = False +if 'pybytes' in globals(): + if(pybytes.isconnected()): + print('Pybytes is connected, sending signals to Pybytes') + pybytes_enabled = True mp = MPL3115A2(py,mode=ALTITUDE) # Returns height in meters. Mode may also be set to PRESSURE, returning a value in Pascals print("MPL3115A2 temperature: " + str(mp.temperature())) @@ -40,7 +48,7 @@ lt = LTR329ALS01(py) -print("Light (channel Blue lux, channel Red lux): " + str(lt.light())) +print("Light (channel Blue, channel Red): " + str(lt.light())," Lux: ", str(lt.lux()), "lx") li = LIS2HH12(py) print("Acceleration: " + str(li.acceleration())) @@ -48,3 +56,17 @@ print("Pitch: " + str(li.pitch())) print("Battery voltage: " + str(py.read_battery_voltage())) + +# set your battery voltage limits here +vmax = 4.2 +vmin = 3.3 +battery_voltage = py.read_battery_voltage() +battery_percentage = (battery_voltage - vmin / (vmax - vmin))*100 +print("Battery voltage: " + str(py.read_battery_voltage()), " percentage: ", battery_percentage) +if(pybytes_enabled): + pybytes.send_signal(1, mpp.pressure()) + pybytes.send_signal(2, si.temperature()) + pybytes.send_signal(3, lt.light()) + pybytes.send_signal(4, li.acceleration()) + pybytes.send_battery_level(int(battery_percentage)) + print("Sent data to pybytes") diff --git a/shields/pytrack_1.py b/shields/pytrack_1.py index 4751617..cab1cb9 100644 --- a/shields/pytrack_1.py +++ b/shields/pytrack_1.py @@ -34,6 +34,12 @@ py = Pycoproc(Pycoproc.PYTRACK) l76 = L76GNSS(py, timeout=30) +pybytes_enabled = False +if 'pybytes' in globals(): + if(pybytes.isconnected()): + print('Pybytes is connected, sending signals to Pybytes') + pybytes_enabled = True + # sd = SD() # os.mount(sd, '/sd') # f = open('/sd/gps-record.txt', 'w') @@ -42,3 +48,13 @@ coord = l76.coordinates() #f.write("{} - {}\n".format(coord, rtc.now())) print("{} - {} - {}".format(coord, rtc.now(), gc.mem_free())) + if(pybytes_enabled): + pybytes.send_signal(1, coord) + time.sleep(10) + +""" +# sleep procedure +time.sleep(3) +py.setup_sleep(10) +py.go_to_sleep() +""" diff --git a/shields/pytrack_1_pybytes.py b/shields/pytrack_1_pybytes.py deleted file mode 100644 index 51e03ab..0000000 --- a/shields/pytrack_1_pybytes.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2019, Pycom Limited. -# -# This software is licensed under the GNU GPL version 3 or any -# later version, with permitted additional terms. For more information -# see the Pycom Licence v1.0 document supplied with this file, or -# available at https://www.pycom.io/opensource/licensing -# - -import machine -import math -import network -import os -import time -import utime -from machine import RTC -from machine import SD -from machine import Timer -from L76GNSS import L76GNSS -from pycoproc_1 import Pycoproc -from LIS2HH12 import LIS2HH12 -# setup as a station - -import gc - -time.sleep(2) -gc.enable() - -# setup rtc -rtc = machine.RTC() -rtc.ntp_sync("pool.ntp.org") -utime.sleep_ms(750) -print('\nRTC Set from NTP to UTC:', rtc.now()) -utime.timezone(7200) -print('Adjusted from UTC to EST timezone', utime.localtime(), '\n') -py = Pycoproc(Pycoproc.PYTRACK) -l76 = L76GNSS(py, timeout=30) -chrono = Timer.Chrono() -chrono.start() -li = LIS2HH12(py) -#sd = SD() -#os.mount(sd, '/sd') -#f = open('/sd/gps-record.txt', 'w') -while (pybytes): - coord = l76.coordinates() - #f.write("{} - {}\n".format(coord, rtc.now())) - print('Sending data', coord) - pybytes.send_signal(1, coord) - pybytes.send_signal(2, li.acceleration()) - time.sleep(10) diff --git a/shields/pytrack_2.py b/shields/pytrack_2.py index 3f33ff5..52fe547 100644 --- a/shields/pytrack_2.py +++ b/shields/pytrack_2.py @@ -36,19 +36,29 @@ print('Adjusted from UTC to EST timezone', utime.localtime(), '\n') py = Pycoproc() +if py.read_product_id() != Pycoproc.USB_PID_PYTRACK: + raise Exception('Not a Pytrack') time.sleep(1) l76 = L76GNSS(py, timeout=30, buffer=512) +pybytes_enabled = False +if 'pybytes' in globals(): + if(pybytes.isconnected()): + print('Pybytes is connected, sending signals to Pybytes') + pybytes_enabled = True + # sd = SD() # os.mount(sd, '/sd') # f = open('/sd/gps-record.txt', 'w') -# while (True): -for _ in range(5): +while (True): coord = l76.coordinates() #f.write("{} - {}\n".format(coord, rtc.now())) print("{} - {} - {}".format(coord, rtc.now(), gc.mem_free())) + if(pybytes_enabled): + pybytes.send_signal(1, coord) + time.sleep(10) """ # sleep procedure