Rob Braggaar
Published © CC BY-SA

Smart Parking Node

Monitor your parking lot with the LoPy using LoRa!

BeginnerFull instructions provided3 hours4,161
Smart Parking Node

Things used in this project

Hardware components

LoPy4
Pycom LoPy4
×1
Sparkfun Lithium Ion Battery - 2000mAh
×1
SparkFun Compass Module - HMC6352
×1
TheStripe™ 868 Mhz PCB A ntenna
×1

Story

Read more

Custom parts and enclosures

case

lid

Schematics

Diagram

Sensor

Lopy

Internal antenna

Compact 868 Mhz ISM band antenna.

Code

boot.py

Python
This script is ran first and then start the main script when it's done.
"""Enable serial communication with the Lopy.
Disable WLAN, LED.
"""
import os
import machine
from network import WLAN
import pycom


uart = machine.UART(0, 115200)
os.dupterm(uart)

wl = WLAN()
wl.deinit()

pycom.heartbeat(False)

machine.main('main.py')
print('==========Starting main.py==========\n')

main.py

Python
The main script that loops continuously.
"""The main script that will loop continuously with the use of deepsleep.
Sensorvalue is read once every minute. If a change is detected, send it with
LoRa.

Parameters:
start_val: has to be chosen in the field depeding on the environment
"""
import time
from machine import I2C
from network import LoRa
import socket
import binascii
import struct
import pycom


print('Main start')

# global parameters:
start_val = 2590  # e.g. 259.0 degrees

# LoRa details keys obtained from KPN
dev_addr = 7656999  # converted hex to decimal for better readability
nwks_key = binascii.unhexlify('d9ab51e44341853fbf0abe2671dddccd')
apps_key = binascii.unhexlify('99150d3a4dfddd08e6be1b63e58dd91f')

i2c = I2C(0, I2C.MASTER, baudrate=100000, pins=('P9', 'P10'))
addr = i2c.scan()
if addr:
    print('Peripheral found on address: ', addr, '\n')
    addr = addr[0]
else:
    print('No peripherals found!\n')
    addr = 0x21  # use default address
    pycom.rgbled(0xFF0000)  # light the led to indicate an error with peripheral


class Sensor():
    """Address is 0x42>>1, which is 0x21"""

    def __init__(self, i2c, addr):
        self.i2c = i2c
        self.addr = addr
        self.val = 0

    def read(self):
        self.i2c.writeto(addr, bytes([0x41]))  # query for heading
        time.sleep_ms(10)
        # read 2 bytes
        raw_val = self.i2c.readfrom(self.addr, 2)
        # bitshift first byte 8 places to the left
        self.val = raw_val[0] * 2**8 + raw_val[1]
        return self.val


sensor = Sensor(i2c, addr)

# Setup LoRa
lora = LoRa(mode=LoRa.LORAWAN)

# join a network using ABP
lora.join(activation=LoRa.ABP, auth=(dev_addr, nwks_key, apps_key), timeout=0)
print("LoRa active: ",  lora.has_joined())

# create a LoRa socket
lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

# set the LoRaWAN data rate
lora_sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)


def ack():
    for i in range(3):
        pycom.rgbled(0x00ff00)
        time.sleep_ms(100)
        pycom.rgbled(0)
        time.sleep_ms(100)


def lora_tx(payload):
    print('Sending uplink message')
    pycom.rgbled(0xff0000)
    lora_sock.send(payload)
    print('LoRa uplink complete')
    ack()


time.sleep_ms(10)  # give the sensor some time to get a good reading
other_val = sensor.read()  # e.g. 261.0 degrees

# set to more than 2 degrees (find a good threshold here)
if abs(start_val - other_val) > 20:
    lora_tx(bytes([0x01]))  # there is a parked vehicle
else:
    lora_tx(bytes([0x00]))  # no vehicle detected`

machine.deepsleep(1000 * 60)  # 60 sec interval, resumes again from top

Credits

Rob Braggaar

Rob Braggaar

3 projects • 9 followers
Professional tinkerer, Node specialist and tech geek

Comments