I am using Python to build a script for a program to be ran by Artisan-Scope roasting software. The program already works with my device (the Phidgets 1045_1B) but I need to do more filtering on the temperature readings. I would like the program to sample at 32ms and organize those 30 samples per second in ascending order. I would then like the lowest 10 samples to be average and returned to Artisan software to be graphed.

This is what I have so far but I need help figuring out how to organize the samples and average them before giving one temperature reading to Artisan.

import sys
import time
import traceback

from Phidget22.Devices.TemperatureSensor import *
from Phidget22.PhidgetException import *
from Phidget22.Phidget import *
from Phidget22.Net import *

try:
    from PhidgetHelperFunctions import *
except ImportError:
    sys.stderr.write("\nCould not find PhidgetHelperFunctions. Either add PhdiegtHelperFunctions.py to your project folder "
                      "or remove the import from your project.")
    sys.stderr.write("\nPress ENTER to end program.")
    readin = sys.stdin.readline()
    sys.exit()


def onAttachHandler(self):

    ph = self
    try:
        #If you are unsure how to use more than one Phidget channel with this event, we recommend going to
        #www.phidgets.com/docs/Using_Multiple_Phidgets for information

        print("\nAttach Event:")


        channelClassName = ph.getChannelClassName()
        serialNumber = ph.getDeviceSerialNumber()
        channel = ph.getChannel()



        ph.setDataInterval(32)


        ph.setTemperatureChangeTrigger(0)



    except PhidgetException as e:
        print("\nError in Attach Event:")
        DisplayError(e)
        traceback.print_exc()
        return


def onDetachHandler(self):

    ph = self
    try:





    except PhidgetException as e:
        print("\nError in Detach Event:")
        DisplayError(e)
        traceback.print_exc()
        return


def onErrorHandler(self, errorCode, errorString):

    sys.stderr.write("[Phidget Error Event] -> " + errorString + " (" + str(errorCode) + ")\n")

"""
* Outputs the TemperatureSensor's most recently reported temperature.
* Fired when a TemperatureSensor channel with onTemperatureChangeHandler registered meets DataInterval and ChangeTrigger criteria
*
* @param self The TemperatureSensor channel that fired the TemperatureChange event
* @param temperature The reported temperature from the TemperatureSensor channel
"""
def onTemperatureChangeHandler(self, temperature):

    #If you are unsure how to use more than one Phidget channel with this event, we recommend going to
    #www.phidgets.com/docs/Using_Multiple_Phidgets for information

    print("[Temperature Event] -> Temperature: " + str(temperature))


"""
* Prints descriptions of how events related to this class work
"""
def PrintEventDescriptions():

    print("\n--------------------\n"
        "\n  | Temperature change events will call their associated function every time new temperature data is received from the device.\n"
        "  | The rate of these events can be set by adjusting the DataInterval for the channel.\n"
        "  | Press ENTER once you have read this message.")
    readin = sys.stdin.readline(1)

    print("\n--------------------")

"""
* Creates, configures, and opens a TemperatureSensor channel.
* Displays Temperature events for 10 seconds
* Closes out TemperatureSensor channel
*
* @return 0 if the program exits successfully, 1 if it exits with errors.
"""
def main():
    try:

        ch = TemperatureSensor()
        ch.setOnAttachHandler(onAttachHandler)

        ch.setDeviceSerialNumber(424909)
        ch.setChannel(0)
        ch.openWaitForAttachment(5000)
        ch.setTemperatureChangeTrigger(0)



        ch.setOnDetachHandler(onDetachHandler)

        ch.setOnErrorHandler(onErrorHandler)

        #This call may be harmlessly removed
        PrintEventDescriptions()

        ch.setOnTemperatureChangeHandler(onTemperatureChangeHandler)


        try:
            ch.openWaitForAttachment(5000)
        except PhidgetException as e:
            PrintOpenErrorMessage(e, ch)
            raise EndProgramSignal("Program Terminated: Open Failed")


        time.sleep(1)

        return 0

    except PhidgetException as e:
        sys.stderr.write("\nExiting with error(s)...")
        DisplayError(e)
        traceback.print_exc()
        print("Cleaning up...")
        ch.close()
        return 1
    except EndProgramSignal as e:
        print(e)
        print("Cleaning up...")
        ch.close()
        return 1
    except RuntimeError as e:
         sys.stderr.write("Runtime Error: \n\t" + e)
         traceback.print_exc()
         return 1
    finally:
        print("Press ENTER to end program.")
        readin = sys.stdin.readline()

main()
1

There are 1 best solutions below

0
Torben Klein On

The first thing that you need is some kind of buffer to hold recorded values until you have enough of them to process them. You can for instance use a python list::

# in onAttachHandler:
# init buffer
global buffer
buffer = []

In onTemperatureChangeHandler, store the values in the buffer. Once the buffer is full, calculate your average, then pass that value on.

# in onTEmperatureChangeHandler
global buffer
buffer.append(temperature)
if len(buffer) > 30:
    buffer.sort()
    mean_temperature = sum(buffer[:10]) / 10.0
    buffer = []
    # Do something with mean_temperature here

That said, global variables as used here are considered bad style for good reasons. The code should be improved by defining a class, which has the buffer and all the handlers as attributes. There are plenty of Python tutorials about this.