Light Sensing with an LDR and Pycom

Updated 18 March 2022

Note: With the rollout of TTNv3, the "Setup" section of this guide no longer works - but we're keeping it here for posterity. Let us know on our forums if you need help getting started with the new method.

One of the simplest sensors in any makers toolkit is a light sensor or LDR. An LDR works by changing its resistance from 1k ohm to 10K ohm depending on how much light is striking it. In this tutorial, we will show you how to use one with a Pycom Lopy4 and transmit your readings to TTN via LoRaWAN!

The Circuit

An LDR needs to be used with a 10k ohm resistor. This drops the voltage down to a level easily interpreted by the ADC on the Lopy4. We want to see values about the middle of the range when in a normally lit room. The Pycom Lopy4 has 12-bit ADC, so the maximum reading will be 4096. We will be using the Pycom Expansion Board 3.0 and the Lopy4, but any Pycom board will work! If you are connecting to your Pycom board directly refer to the relevant pinout diagram.

Pycom-lopy4-expansionboard-ldr-schematic

The Code

The following code takes light measurements every ten seconds, and then sends them to The Things Network via LoRaWAN

# Measuring light with an LDR
from network import LoRa
import socket
import utime
import binascii
import pycom
import ustruct
import machine
from machine import Pin

adc = machine.ADC()               # create an ADC object
apin = adc.channel(pin=Pin.exp_board.G31) # Lopy4 specific: (pin = 'P17')   create an analog pin on P17 & connect TMP36

# Light measurment
def light_measure():
    print("")
    print("Reading LDR Sensor...")
    value = apin()
    print("ADC count = %d" %(value))

    # LoPy  has 1.1 V input range for ADC
    light = value
    print("light = %5.1f" % (light))

    return light

# disable LED heartbeat (so we can control the LED)
pycom.heartbeat(False)
# set LED to red
pycom.rgbled(0x7f0000)

# lora config
lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AS923)
# access info
app_eui = binascii.unhexlify('XXXXXXXX')
app_key = binascii.unhexlify('XXXXXXXXXXXXXXXXXXXXXXXX')

# attempt join - continues attempts background
lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0)

# wait for a connection
print('Waiting for LoRaWAN network connection...')
while not lora.has_joined():
	utime.sleep(1)
	# if no connection in a few seconds, then reboot
	if utime.time() > 15:
		print("possible timeout")
		machine.reset()
	pass

# we're online, set LED to green and notify via print
pycom.rgbled(0x004600)
print('Network joined!')

# setup the socket
s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
s.setblocking(False)
s.bind(1)

count = 0
# limit to 200 packets; just in case power is left on
while count < 200:

	# take light measurment, turn the light blue when measuring
	pycom.rgbled(0x00007d)
	utime.sleep(1)
	light = light_measure()
	pycom.rgbled(0x004600)

	print("light:  ", light)
	# encode the packet, so that it's in BYTES (TTN friendly)
	# could be extended like this struct.pack('f', light) + struct.pack('c',"example text")
    # 'h' packs it into a short, 'f' packs it into a float, must be decoded in TTN
	packet = ustruct.pack('h', light)

	# send the prepared packet via LoRa
	s.send(packet)

	# example of unpacking a payload - unpack returns a sequence of
	#immutable objects (a list) and in this case the first object is the only object
	print ("Unpacked value is:", ustruct.unpack('h',packet)[0])

	# check for a downlink payload, up to 64 bytes
	rx_pkt = s.recv(64)

	# check if a downlink was received
	if len(rx_pkt) > 0:
		print("Downlink data on port 200:", rx_pkt)
		pycom.rgbled(0xffa500)
		input("Downlink recieved, press Enter to continue")
		pycom.rgbled(0x004600)

	count += 1
	utime.sleep(10)

Decoding the Payload

Now we have our data arriving in The Things Network as payloads, but we need to decode them! Under Payload Formats in TTN we will use the following javascript code to decode our payloads:

function Decoder(bytes, port) {
  // Decode an uplink message from a buffer
  // (array) of bytes to an object of fields.
  var decoded = {};

  // Decode bytes to int
  var testShort = (bytes[1] << 8) | bytes[0];

  // Decode int 
  decoded.Light = testShort;

  return decoded;
}

Going Further

If you want to learn more about Pycom check out our Pycom Tutorials. If you want to learn more about connecting to The Things Network and using LoRaWAN check out our The Things Network Tutorials. There are many more sensors and devices that can be used with the Pycom Lopy4, get out there and experiment!

Have a question? Ask the Author of this guide today!

Please enter minimum 20 characters

Your comment will be posted (automatically) on our Support Forum which is publicly accessible. Don't enter private information, such as your phone number.

Expect a quick reply during business hours, many of us check-in over the weekend as well.

Comments


Loading...
Feedback

Please continue if you would like to leave feedback for any of these topics:

  • Website features/issues
  • Content errors/improvements
  • Missing products/categories
  • Product assignments to categories
  • Search results relevance

For all other inquiries (orders status, stock levels, etc), please contact our support team for quick assistance.

Note: click continue and a draft email will be opened to edit. If you don't have an email client on your device, then send a message via the chat icon on the bottom left of our website.

Makers love reviews as much as you do, please follow this link to review the products you have purchased.