Wednesday, December 16, 2020

Raspberry Pi and Circuit Playground Express Temperature Logging using Python

So I tried searching for the above title and well, it gave me this as the top result:

https://learn.adafruit.com/circuit-playground-express-serial-communications/overview

This one wants us to us a USB to serial device and hook up to the physical serial pins, but we are connected via USB, so I was a bit frustrated.

The rest of the search results weren't much better. 

So lets start with, connect your circuit playground express to your raspberry pi. Make sure you can see the folder to plop files into. You might have to hit reset to put it back in the mode.

I did come across this finally: 

https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/circuit-playground-express-library

So we will start there, you can follow along from the start, but the instructions keep pushing to use the mu editor, which I didn't attempt to do as I wasn't sure how it would actually log data for me. Following the instructions ignoring that amounts to updating our board with the circuitpython, once that was on the board we had the following page:

https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/temperature

I then pushed code.py which contained the following:

"""This example uses the temperature sensor on the Circuit Playground, located next to the image of
a thermometer on the board. It prints the temperature in both C and F to the serial console. Try
putting your finger over the sensor to see the numbers change!"""
import time
from adafruit_circuitplayground import cp

while True:
    print("Temperature C:", cp.temperature)
    print("Temperature F:", cp.temperature * 1.8 + 32)
    time.sleep(1) 
source: https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/blob/main/examples/circuitplayground_temperature.py

OK now our board should be outputting temperature data, great. How do we view it?

Now there is a process to view the content on the board not found in the series of steps, instead I came across that here: 

 https://learn.adafruit.com/welcome-to-circuitpython?view=all#whats-the-port-2977243-1

Which we use to find the port our device is communicating over:

 ls /dev/ttyACM*

Then from there we can test out we can see the data. This tells us to use screen (so you might need to apt-get install screen).

 https://learn.adafruit.com/welcome-to-circuitpython?view=all#connect-with-screen-2977916-10

screen /dev/ttyACM0 115200

when I ran the ls command above mine returned /dev/ttyACM0 so yours will *likely* do this unless you have other stuff connected, additionally 115200 is the speed with which to communicate.

This at least got me to the point of making sure I can see the temp. If you get connected via screen you should have to hit Ctrl+d and it'll start showing temps. If it's not it might tell you to hit reset then it'll start running, so do that. If that didn't work, you might need to check the instructions up to this point and make sure you followed them. When you are done with Screen Ctrl+A should get you out.

Ok so we have data through screen but that doesn't help us if we want to save the data. This is where python comes in.

I tried connecting using python earlier but had no luck, it would just print a newline over and over, which wasn't much help, but here is the thing after seeing that we needed ctrl+d to get the temp data, something clicked. We need to send a ctrl+d.

here is how I got it working.

#!/usr/bin/env python
import time
import serial
import sys
import datetime

ser = serial.Serial(
    port='/dev/ttyACM0', # remember earlier we discovered mine is ttyACM0
    baudrate=115200
)
ser.write(b'\x04') # This mimics the Ctrl + D
time.sleep(5) # Wait a few moments for the Ctrl+D to take effect, it'll print a few messages and start telling us temps.
tmp = ser.readline().strip('\n') # One of the messages that gets printed we don't care about so we throw it away.

print (sys.argv[1]) # Check we have a filename
while True:
    tmp = ser.readline().strip('\n') # Read the serial data and toss the newline.
    f = open(sys.argv[1], 'a') # Open our output file
    f.write(str(datetime.datetime.now()) + "," + tmp.split()[2] + "\n") # Print the current date/time and the temp (in F) to the file.
    f.close() # Close the file each time so it writes.
    time.sleep(10) # I collect the data every 10 seconds, you could wait a minute or 10 minutes if you like


One constraint I'm uncertain of is if we wait 10 minutes to read the serial, does it read it at the time, or does it read the "last unread" line? I'm not worrying too much right now but will look into it eventually.

One final note, in the above, I only print out the F temp so my python only accounts for that, so you adjust your temp printing so it matches what you want.  


Thanks for following along I hope this helped!