Pycom Pysense Getting Started Guide

Updated 24 April 2018

The Pysense expansion board from Pycom has many sensors. In Pycom Pytrack Getting Started, I showed how with some Processing code we can see the real-time position of the board in 3D. That project works with the Pysense too. How about we show a real-time display on screen of the light sensor and we push temperature and humidity data out to Adafruit IO to make a nice graph from!

If you're not yet familiar with the Pysense, have a quick look at the Pycom Pysense Overview first to get a grounding. We'll need one of the range of Pycom microcontroller boards. I'm using a WiPy so I don't have to attach an antenna!

You'll need to do a firmware upgrade on your Pysense to ensure you select the region for the LoRa radio. That’s documented that separately in Pycom Pysense & Pytrack: How to Update Firmware. If you haven't set up the Atom IDE with the pymakr package before, have a look at Internet of Things with Pycom and Adafruit IO - From Zero to Hero.

To quick recap of the sensors available on Pysense:

  • Temperature
  • Humidity
  • Light level
  • Accelerometer (movement in 3D) including roll and pitch
  • Barometric pressure which can be used to infer altitude
  • Battery volts

Hardware

To work along with this tutorial, you'll need the following:

  • Pycom Pysense
  • Any Pycom microcontroller
  • Antennae for radios not using on-board antennae
  • A micro-USB cable connected to a PC
Pycom Pysense
The Pysense from Pycom

Code

Sample code for all the Pycom devices is available from Github. You don't need to worry about what Github is or how to use it:

  1. Click the green Clone or Download button, then click Download ZIP. I'll assume you’ve downloaded this into your Downloads folder.
  2. Open your Downloads folder and extract the pycom-libraries-master.zip file.
  3. Now we'll open Atom IDE
  4. In Atom, from the File menu, click Open Folder and navigate to Downloads\pycom-libraries-master\pycom-libraries-master\pysense
  5. In between the two panels on the right, there's a More button. Click that, then Get Serial Ports
  6. Since I haven't yet plugged in my Pycom device there are no serial ports listed. Plug in your Pycom device if you haven't already.
  7. Get Serial Ports now shows me the serial port number for my Pysense.
  8. Click Settings then Project Settings and make sure the appropriate COM port number is entered in the "address" field. Then save the settings (Ctrl-S)
  9. Hit Connect
  10. If you get the triple greater-than prompt, you're on!
  11. Hit Upload to get the sample code started on your device.
Atom IDE
Sample code in the Atom IDE

When I do this I get the following error:

Traceback (most recent call last):
  File "main.py", line 3, in 
  File "/flash/lib/pysense.py", line 1, in 
ImportError: no module named 'pycoproc'
MicroPython v1.8.6-849-83e2f7f on 2018-03-19; FiPy with ESP32
Type "help()" for more information.

We need to get the file pycoproc.py from Downloads\pycom-libraries-master\pycom-libraries-master\lib and copy it into the lib folder within our Pysense project. That should fix the issue. Upload again. When the upload completes you should get output like this:

MPL3115A2 temperature: 25.875
Altitude: -31.9375
Pressure: 101721.0
Temperature: 28.81557 deg C and Relative Humidity: 51.65915 %RH
Dew point: 17.86834 deg C
Humidity Ambient for 24.4 deg C is 67.08653%RH
Light (channel Blue lux, channel Red lux): (49, 31)
Acceleration: (-0.04541016, 0.01843262, 0.9946289)
Roll: 2.614045
Pitch: -1.060588
Battery voltage: 4.62147
MicroPython v1.8.6-849-83e2f7f on 2018-03-19; FiPy with ESP32
Type "help()" for more information.

Lovely!

Code Walkthrough

Let's do a quick walk-though of the code. The work is getting done by main.py. Remember that when a Pycom device boots it looks for boot.py. If it finds that it runs that first. Then it looks for main.py and runs that. Since we have code in main.py that is run every time the device resets. Let's look at that file.

At the top of the file we have a list of import statements. These pull in the necessary parts of the Python files in the project's lib folder. As we discovered with the error we had to fix, pysense.py needs procproc.py. Other than that, we can see how files like SI7006A20 are imported. The reason these files have strange names is that they directly control a particular chip on the Pysense and are named after the microchip part numbers.

After importing the libraries we need, we create objects to represent the physical devices with the Pysense() object being first because it's needed to initialize the four other devices. We can then see mp, si, lt and li are used to access the relevant values from those devices. mpp appears a few rows down to access the barometer but using PRESSURE mode instead of ALTITUDE mode.

Most of the following code is self-explanatory. The accelerometer data is covered in detail in Pycom Pytrack Getting Started including an on-screen 3D visualization of the orientation of the Pytrack board. Check that out, it's cool and gives me lots of ideas about what I can build around a 3D accelerometer.

Adding Adafruit IO

To send data to Adafruit IO I went back to my IoT From Scratch video and copied all that code and the libraries into my project. The final code file is a bit messy, but here it is!

from network import WLAN      # For operation of WiFi network
import time                   # Allows use of time.sleep() for delays
import pycom                  # Base library for Pycom devices
from umqtt import MQTTClient  # For use of MQTT protocol to talk to Adafruit IO
import ubinascii              # Needed to run any MicroPython code
import machine                # Interfaces with hardware components
import micropython            # Needed to run any MicroPython code

from pysense import Pysense   # Needed to operate anything on the Pysense expansion
#from LIS2HH12 import LIS2HH12 # Removed to minimise memory consumption
from SI7006A20 import SI7006A20
from LTR329ALS01 import LTR329ALS01
# from MPL3115A2 import MPL3115A2,ALTITUDE,PRESSURE # Removed to minimise memory consumption

# BEGIN SETTINGS
# These need to be change to suit your environment
# Randoms were sent to Adafruit IO for testing
RANDOMS_INTERVAL = 5000     # milliseconds
last_random_sent_ticks = 0  # milliseconds

# Wireless network
WIFI_SSID = "IoT"
WIFI_PASS = "Core123698745+" # No this is not our regular password. :)

# Adafruit IO (AIO) configuration
AIO_SERVER = "io.adafruit.com"
AIO_PORT = 1883
AIO_USER = "CoreChris"
AIO_KEY = "7b2d0601a9694589a52fb2d614122cff"
AIO_CLIENT_ID = ubinascii.hexlify(machine.unique_id())  # Can be anything
AIO_CONTROL_FEED = "CoreChris/feeds/lights"
AIO_RANDOMS_FEED = "CoreChris/feeds/randoms"
AIO_FEEDS = {'temp': 'CoreChris/feeds/temperature', 'humi': 'CoreChris/feeds/humidity'}

do_temp = True

py = 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)

# END SETTINGS

# RGBLED
# Disable the on-board heartbeat (blue flash every 4 seconds)
# We'll use the LED to respond to messages from Adafruit IO
pycom.heartbeat(False)
time.sleep(0.1) # Workaround for a bug.
                # Above line is not actioned if another
                # process occurs immediately afterwards
pycom.rgbled(0xff0000)  # Status red = not working

# WIFI
# We need to have a connection to WiFi for Internet access
# Code source: https://docs.pycom.io/chapter/tutorials/all/wlan.html

wlan = WLAN(mode=WLAN.STA)
wlan.connect(WIFI_SSID, auth=(WLAN.WPA2, WIFI_PASS), timeout=5000)

while not wlan.isconnected():    # Code waits here until WiFi connects
    machine.idle()

print("Connected to Wifi")
pycom.rgbled(0xffd7000) # Status orange: partially working

# FUNCTIONS

# Function to respond to messages from Adafruit IO
# def sub_cb(topic, msg):          # sub_cb means "callback subroutine"
#     print((topic, msg))          # Outputs the message that was received. Debugging use.
#     if msg == b"ON":             # If message says "ON" ...
#         pycom.rgbled(0xffffff)   # ... then LED on
#     elif msg == b"OFF":          # If message says "OFF" ...
#         pycom.rgbled(0x000000)   # ... then LED off
#     else:                        # If any other message is received ...
#         print("Unknown message") # ... do nothing but output that it happened.

# def random_integer(upper_bound):
#     return machine.rng() % upper_bound
#
# def send_random():
#     global last_random_sent_ticks
#     global RANDOMS_INTERVAL
#
#     if ((time.ticks_ms() - last_random_sent_ticks) < RANDOMS_INTERVAL):
#         return; # Too soon since last one sent.
#
#     some_number = random_integer(100)
#     print("Publishing: {0} to {1} ... ".format(some_number, AIO_RANDOMS_FEED), end='')
#     try:
#         client.publish(topic=AIO_RANDOMS_FEED, msg=str(some_number))
#         print("DONE")
#     except Exception as e:
#         print("FAILED")
#     finally:
#         last_random_sent_ticks = time.ticks_ms()
#

# Send temperature and humidity to Adafruit alternately to stay under rate limit
def send_sensors():
    temp = si.temperature()         # Temperature on Pysense
    humi = si.humid_ambient(temp)   # Calculated relative humidity given current temperature
    global do_temp                  # Use a variable defined for the whole program
    try:
        if do_temp:
            client.publish(topic=AIO_FEEDS['temp'], msg=str(temp))  # Send to Adafruit IO
            print("Temp sent")
        else:
            client.publish(topic=AIO_FEEDS['humi'], msg=str(humi))  # Send to Adafruit IO
            print("Humi sent")
        do_temp = not do_temp   # Aternate true/false value
    except Exception as e:
        print("FAILED")

# Use the MQTT protocol to connect to Adafruit IO
client = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY)

# Subscribed messages will be delivered to this callback
# client.set_callback(sub_cb)
client.connect()    # Connects to Adafruit IO using MQTT
# client.subscribe(AIO_CONTROL_FEED)
# print("Connected to %s, subscribed to %s topic" % (AIO_SERVER, AIO_CONTROL_FEED))

pycom.rgbled(0x00ff00)    # Status green: online to Adafruit IO

# try:                      # Code between try: and finally: may cause an error
                          # so ensure the client disconnects the server if
                          # that happens.
while 1:              # Repeat this loop forever
    client.check_msg()# Action a message if one is received. Non-blocking.
    # send_random()     # Send a random number to Adafruit IO if it's time.
    send_sensors()      # Send temp and humidity to Adafruit IO
    for x in range (0, 5):
        time.sleep_ms(1000)
        blue, red = lt.light()
        print('{:5}-Blue  {:5}-Red    Range(0-65535)'.format(blue, red))


# finally:                  # If an exception is thrown ...
client.disconnect()   # ... disconnect the client and clean up.
client = None
wlan.disconnect()
wlan = None
pycom.rgbled(0x000022)# Status blue: stopped
print("Disconnected from Adafruit IO.")

Good luck on your Pycom project! Hit us up on the Core Electronics Forum for help.

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.