#### 1DT305 Tillämpad IoT - Tutorial - Lexx Damm, adaha09 ## Human agent biometric and stat supervisor system Lexx Damm, adaha09 My aim with this project is to prototype a future system for personel biometric and stats supervisor system for my own fictional group. The system should comprise of a system of wearable devices that gather various biometric, enviromental and position metrics. I estimate it would take 1 to 3 hours to wire up, write the code and configure the systems. ### Objective I decided early on that I wanted to do something fun and futuristic. I am into cybernetics and wearables and one of my favorite sci-fi movie is Aliens 2 which if I remember correctly have a supervisor system for the marines which show among other things camera, ECG and some other things. I also wanted to incoperate my own NFC-implants into the design somehow by making my wearable(s) NFC-connected. I believe my prototype will make it more clear the pratical use of such a supervisor system and what drawbacks or unforseen problems that may present itself. I also believe it will prove a practical use of my implants. In my project I will only focus on a monitor system that is supervised, basically a human being or AI monitoring personel stats in real-time. ### Material List of materials: | Item | Cost | Supplier | | ------------- | - |-| | Pycom Lopy4 | 34.95 EUR| Pycom webshop| | Pycom Fipy | 54 EUR| Pycom webshop| | Pycom Pyscan | 39.90 EUR | Pycom webshop| | Pycom Pytrack | 34.95 | Pycom webshop| | Playknowlogy Komponent-kit | 299.90 SEK | Kjell & co| | Mikroe ECG 4 CLICK kit | 699.09 SEK + TAX | RS Components | In my project the main processing devices I have chosen to use is the Pycom line of developer boards. I chose them because it was the recommended device to use, but personally I like the balance between down to the metal but also easy of use it provides but at a good performance and minimal physical space needed. I decided early on that I wanted to do something with both NFC and GPS, so I ordered the Pyscan and Pytrack extension boards for both my Pycom. I looked up if there was a ECG board available and found the Click line of boards from Mikroe. I first bought the ECG 2 CLICK but after some testing realized it was to complicated so I ordered the more simpler ECG 4 CLICK from Mikroe which use a UART interface and simple communication and data protocol. ### Computer setup Software links: - Atom https://atom.io/ - pycom-fwtool ubuntu deb https://pycom.io/downloads/ I used the Atom IDE on Ubuntu 20.04 and installed the pymakr package through the Atom package manager. I also installed pycom-fwtool to update my Pycom boards to the latest firmware. I uploaded the code to the two Pycom devices via Pymakr. ### Putting everything together The FiPy device is plugged into the Pytrack extension board while the LoPy is plugged into the Pyscan board. I then used a breadboard to plug in the Mikroe ECG 4 CLICK and wired the UART lines (TX and RX) to one of the headers on the Pyscan board. ![](https://i.imgur.com/TlmrfvR.jpg) ![](https://i.imgur.com/ICiH6bz.jpg) ![](https://i.imgur.com/fOuGgBk.jpg) I didn't have the time or resources to make a custom PCB, a housing for the boards so my setup is only for prototyping. ### Platform I used the The Things Network to gather my data from LoRaWAN and then forwarded it to Ubidots to visualize the data. For my prototype I used a simple dashboard on Ubidots visualizing the GPS data with a map and the ECG data with a value for the interval between heartbeats. ### The code comms - FiPy code: ```python= import machine import time import pycom import socket import ubinascii import struct import _thread from network import LoRa from L76GNSS import L76GNSS from pytrack import Pytrack # TTN EUI and APP KEY app_eui = ubinascii.unhexlify('70B3D57ED0031632') app_key = ubinascii.unhexlify('10D4E433364CF8A3E78F0708BA22EC42') pycom.heartbeat(False) pycom.rgbled(0x060000) lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) py = Pytrack() l76 = L76GNSS(py, timeout=30) lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) pycom.rgbled(0x0a0a00) while not lora.has_joined(): print('Not yet joined') time.sleep(3) print('Joined LoRa TTN') pycom.rgbled(0x000f00) sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) sock.setblocking(True) sock.bind(1) def gps_loop(): while (True): coord = l76.coordinates() if (coord[0] == None and coord[1] == None): pycom.rgbled(0x0a0a00) continue pycom.rgbled(0x00000a) print('Coordinates: {:.6f}, {:.6f}'.format(coord[0], coord[1])) pack = bytearray(struct.pack('f', float(coord[0])) + struct.pack('f', float(coord[1]))) sock.send(pack) time.sleep(60 + 60 + 60 + 60 + 60) _thread.start_new_thread(gps_loop, ()) ``` id - LoPy4 code: ```python= iimport time import pycom import _thread import ubinascii import math from machine import UART from machine import Pin from machine import Timer from pyscan import Pyscan from MFRC630 import MFRC630 from network import LoRa # TTN EUI and APP KEY app_eui = ubinascii.unhexlify('70B3D54993281B0B') app_key = ubinascii.unhexlify('3987D8D92D72242591EC37D7E327A7F8') # Dictonary of stored uid and their user is my_ids_dict = { b'\x04~e\x12\xff8\x81\x00\x00\x00': b'\x01', b'\x04\x19\x08\x12\xff8\x85\x00\x00\x00': b'\x02' } # 2's compliment to get 16 bit value from 2 bytes def twos_comp(val, bits): if (val & (1 << (bits - 1))) != 0: val = val - (1 << bits) return val # Wait for scanning the correct NFC implant def auth_thread_loop(): global auth_busy global auth_logged_in global auth_user_id auth_busy = True auth = False while (not auth): atqa = nfc.mfrc630_iso14443a_WUPA_REQA(nfc.MFRC630_ISO14443_CMD_REQA) if (atqa != 0): uid = bytearray(10) uid_len = nfc.mfrc630_iso14443a_select(uid) if (uid_len > 0): print('UID: {}'.format(uid)) for stored_uid, user_id in my_ids_dict.items(): if (uid == stored_uid): print('Logged in') auth_logged_in = True pycom.rgbled(0x000f00) auth_user_id = user_id auth = True auth_busy = False break # ECG loop def ecg_thread_loop(): global ecg_busy global ecg_interval ecg_busy = True ecg_interval = None ecg_state = 'PRE' ecg_data = [] counter = 0 while (counter < 2000): if (uart.any()): char = uart.read(1) if (uart.any() and char and char[0] == 0xaa): char = uart.read(1) if (uart.any() and char and char[0] == 0xaa): char = uart.read(1) if (uart.any() and char and char[0] == 4): payload_len = char[0] payload = uart.read(payload_len) if (payload): crc = uart.read(1) code = payload[0] if (code == 0x80): data_row_len = payload[1] data_row = bytearray(payload[2:4]) ecg_value = twos_comp(int(ubinascii.hexlify(data_row), 16), 16) ecg_data.append(ecg_value) counter += 1 i = 0 found = False for value in ecg_data: print(value) if (ecg_state == 'PRE' and value > 1800): ecg_state = 'PEAK' if (ecg_state == 'INTER' and value > 1800): ecg_state = 'PEAK' if (ecg_state == 'PEAK' and value < -1800): ecg_state = 'DIP' if (ecg_state == 'DIP' and value < 200 and value > -200): ecg_state = 'INTER' if (found == True): print('Found interval') ecg_interval = i ecg_busy = False return ecg_interval else: i = 0 found = True i += 1 ecg_busy = False def send_lora_bytes(port, bytes): sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) sock.bind(port) sock.setblocking(True) sock.send(bytes) pycom.heartbeat(False) auth_uplink_timer = Timer.Chrono() ecg_uplink_timer = Timer.Chrono() # Init the UART and configure it to use the pins 19 and 15 as UART TX and RX pins connected to the Mikroe ECG 4 CLICK uart uart = UART(1, 57600, bits=8, parity=None, stop=1, pins=('P19', 'P15')) py = Pyscan() nfc = MFRC630(py) lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) nfc.mfrc630_cmd_init() pycom.rgbled(0x0f0000) lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) auth_busy = False auth_logged_in = False auth_user_id = None ecg_busy = False ecg_interval = None auth_uplink_timer.start() ecg_uplink_timer.start() while (True): print('Waiting for LoRa connection to TTN') if (lora.has_joined()): print('Connected to TTN via LoRa') if (auth_uplink_timer.read() > 300): if (not auth_busy): _thread.start_new_thread(auth_thread_loop, ()) if (auth_logged_in): print('Sending user login') bytes_pack = bytearray(struct.pack('c', auth_user_idl)) send_lora_bytes(2, bytes_pack) auth_uplink_timer.reset() auth_logged_in = False if (ecg_uplink_timer.read() > 300): if (not ecg_busy): _thread.start_new_thread(ecg_thread_loop, ()) if (ecg_interval != None): print('Sending ecg interval') bytes_pack = bytearray(struct.pack('f', ecg_interval)) send_lora_bytes(3, bytes_pack) ecg_uplink_timer.reset() ecg_interval = None time.sleep(30) ``` Payload decoder - TTN: ```javascript= function Decoder(bytes, port) { function bytesToFloat(bytes) { // JavaScript bitwise operators yield a 32 bits integer, not a float. // Assume LSB (least significant byte first). var bits = bytes[3]<<24 | bytes[2]<<16 | bytes[1]<<8 | bytes[0]; var sign = (bits>>>31 === 0) ? 1.0 : -1.0; var e = bits>>>23 & 0xff; var m = (e === 0) ? (bits & 0x7fffff)<<1 : (bits & 0x7fffff) | 0x800000; var f = sign * m * Math.pow(2, e - 150); return f; } function bytesToShort(bytes) { var i = bytes[0]<<8 | bytes[1]; return i; } var decoded = {}; if (port === 1) { decoded = { gps: { lat: +bytesToFloat(bytes.slice(0, 4)), lng: +bytesToFloat(bytes.slice(4, 8)) } } } else if (port === 2) { decoded = { ecgInterval: bytesToShort(bytes) } } return decoded; } ``` ### Transmitting the data / connectivity I had ordered the FiPy which have Celluar connection but ended up using only LoRa. I planned to use Bluetooth between the FiPy and LoPy but revised my idea although I got Bluetooth working, because I figured if the main unit (FiPy) whent down, the LoPy would not get it's data to the internet, so I decided to use LoRaWAN on both the FiPy and LoPy indepentily. Due to the limitations of LoRaWAN i only sends the GPS coordinates from the FiPy every 5 minutes. I used LoRaWAN with The Things Network. Orginally I had plan to send the ECG data from the LoPy in realtime, every second, but rethinked and ended up sending the heart interval every 5 minutes. I also send the specific user logged in every 5 min. ### Presenting the data As my orginal idea centered around a human supervised monitoring system I chose to only show the stats in real-time and don't use a database. Due to time contraints I used a simple dashboard on Ubidots. ![](https://i.imgur.com/U0JmgHB.png) ### Finalizing the design In the end I ran out of time and hit some limitations of specifically LoRaWAN which made my original ideas impossible. In my original idea or vision I had pictured a realtime monitoring system which updated at least every second so I could send and then visualize a ECG plot. I had to rethink a way to use the ECG meaningfully and had to compromize. If I had a lot more resources and time I think I would have come much closer to my original vision. Replacing LoRaWAN with WLAN and/or have a central communication device or even a satelite modem (would make much more sense for my original application out in the field where no LoRaWAN would be available) I would also have liked to do much more with the NFC part of the project, now I only use the UID to log in to my device. I wanted originally to send the raw ECG data to the internet and a dashboard, when faced with the limitations of LoRaWAN i did look up if I could use a machine learning algorimth on the Pycom device to sense different ECG states of the agent wearing the device, but in the end it would take to much time and I decided to only send the interval between heartbeats. I had a lot of problems with connecting to LoRa due to bad coverage so it was hard to test the system as a whole. I also had a lot of problems with the ECG data protocol, some kind of error sometimes manifested it self when I read the UART data. This took a lot of time from the project and resulted in trying to get something basic to work. The most successful part of the project in my mind is what lessons I have learned. If I wanted it to work and be practical I would have to find a another wireless tehcnology which have much more data allowences AND coverage. A more powerful main device to run a AI locally would benefit the project when radio coverage and/or ability to transmit would be affected. It did also provide me with some practical knowledge about to read and process ECG data. In a more ambitious project I would have incorporated some machine learning algorithm, both on the edge devices and in a central server. ![](https://i.imgur.com/bWD2TMw.jpg) ![](https://i.imgur.com/VqDGzQG.png) ![](https://i.imgur.com/aiUIYnP.jpg) {%youtube ULU7ldsv5jw %}