Saturday, November 26, 2016

Python Code To Record Sequence

Many uses of chip sets like the MiniMu9 are for robotics, so it's necessary to convert the readings into valuable properties like pitch and yaw.  Whilst that may be useful down the road,  because I don't plan to handle the data in real time I want to simply capture the data and store it for offline processing.  I therefore must write Python code that will read each sensor in turn, and write the data to a file on the Raspberry Pi's USB drive.

Requirements

Here are my requirements for the code:
  • Take a parameter for the number of seconds to run the sampling (this will subsequently be replaced with start/stop switch)
  • Sample each of the three devices in sequence
  • Write the data to arrays
  • At the end of the run, write the arrays to a json file for offline reading
Format of the json file:

[
   {
    "header" = {"type": "header", "Month": 12, "Day": 4, "Year": 2016},
    "r1" = {"type": "reading",
            "timestamp": {"Second": 39, "Microsecond": 998934, "Minute": 34, "Hour": 12},
            "gyro": {"y0": 162, "x0": 7, "z0": 162}, "id": 0,
            "accel": {"y0": 171, "x0": 21, "z0": 161},
            "magno": {"y1": 255, "y0": 56, "x0": 46, "x1": 5, "z0": 110, "z1": 4}
           },
...
    "r2" = {"type": "reading",
            "timestamp": {"Second": 40, "Microsecond": 39239, "Minute": 34, "Hour": 12},
            "gyro": {"y0": 161, "x0": 255, "z0": 162}, "id": 1,
            "accel": {"y0": 170, "x0": 1, "z0": 158},
            "magno": {"y1": 255, "y0": 72, "x0": 20, "x1": 5, "z0": 66, "z1": 4}
           }
    }
]

Rationale

I want to write this code and review the resulting data with three objectives in mind:
  1. Calibrate each of the sensors - work out what needs to be added or subtracted to get to zero,
  2. Work out how stable the data is from each of the 9 sensors - I will do statistical analysis of the data sets arising from the sensors.
  3. Based on (2.) work out how to combine data from the accelerometer and gyro to get an accurate reading (by combining them and also by taking a trailing average to smooth erratic readings)

Python Code

import smbus
import datetime
import os
import time
import json


def get_magnetometer():
    # activate Magnetometer (address, ctrl_reg, value)
    bus.write_byte_data(0x1e, 0x20, 0x10) 
    bus.write_byte_data(0x1e, 0x21, 0x00)
    bus.write_byte_data(0x1e, 0x22, 0x00) 
    time.sleep(0.01)
    readings_m = dict()
    # Read back the Magnetometer values (addr, data_reg)
    readings_m["x0"] = bus.read_byte_data(0x1e, 0x28)
    readings_m["x1"] = bus.read_byte_data(0x1e, 0x29)
    readings_m["y0"] = bus.read_byte_data(0x1e, 0x2a)
    readings_m["y1"] = bus.read_byte_data(0x1e, 0x2b)
    readings_m["z0"] = bus.read_byte_data(0x1e, 0x2c)
    readings_m["z1"] = bus.read_byte_data(0x1e, 0x2d)

    return(readings_m)


def get_gyro():
    # activate gyro (address, ctrl_reg, value)
    bus.write_byte_data(0x6b, 0x16, 0x38)
    bus.write_byte_data(0x6b, 0x11, 0x40)
    time.sleep(0.01)
    readings_g = dict()
    # Read back the gyro values (addr, data_reg)
    readings_g["x0"] = bus.read_byte_data(0x6b, 0x22)
    readings_g["x1"] = bus.read_byte_data(0x6b, 0x23)
    readings_g["y0"] = bus.read_byte_data(0x6b, 0x24)
    readings_g["y1"] = bus.read_byte_data(0x6b, 0x25)
    readings_g["z0"] = bus.read_byte_data(0x6b, 0x26)
readings_g["z1"] = bus.read_byte_data(0x6b, 0x27) return(readings_g) def get_accel(): # activate accel (address, ctrl_reg, value)
    bus.write_byte_data(0x6b, 0x18, 0x38) # set freq /dps
    bus.write_byte_data(0x6b, 0x10, 0x40) # turn 3d accel on
    time.sleep(0.01)
    readings_a = dict()
    # Read back the gyro values (addr, data_reg)
    readings_a["x0"] = bus.read_byte_data(0x6b, 0x28)
    readings_a["x1"] = bus.read_byte_data(0x6b, 0x29)
readings_a["y0"] = bus.read_byte_data(0x6b, 0x2A)
    readings_a["y1"] = bus.read_byte_data(0x6b, 0x2B)
    readings_a["z0"] = bus.read_byte_data(0x6b, 0x2C)
    readings_a["z1"] = bus.read_byte_data(0x6b, 0x2D)
return(readings_a) def write_data(filename, data): # assumes directory already set in main (avoids repeated sets) f = open(filename, "w") json.dump(data, f) f.close() ## Maintry: os.chdir("/usbdrv/data/sensor_data") except: os.mkdir("/usbdrv/data/sensor_data") # confirm which when running i2c-detect second parameterbus = smbus.SMBus(1) dt = datetime.datetime # wait for the pin to go high header = dict() header["type"] = "header"header["Year"] = dt.today().year header["Month"] = dt.today().month header["Day"] = dt.today().day file_data = dict() file_data["header"] = header for i in (range(0, 20)): timestamp = dict() timestamp["Hour"] = dt.today().hour timestamp["Minute"] = dt.today().minute timestamp["Second"] = dt.today().second timestamp["Microsecond"] = dt.today().microsecond readings = dict() readings["type"] = "reading" readings["id"] = i readings["timestamp"] = timestamp readings["magno"] = get_magnetometer() readings["gyro"] = get_gyro() readings["accel"] = get_accel() file_data["r" + str(i)] = readings to_json = [file_data] # encapsulate dict in list print(file_data) write_data("readings.data", to_json)