Example 7: FIFO

examples/ex7_qwiic_adxl313_fifo.py
  1#!/usr/bin/env python
  2#-----------------------------------------------------------------------------
  3# ex7_qwiic_adxl313_fifo.py
  4#
  5# Simple Example for the Qwiic ADXL313 DeviceSet that shows how to setup the FIFO on the ADXL313.
  6# One key advantage of using the FIFO is that it allows us to
  7# let the ADXL313 store up to 32 samples in it's FIFO "buffer".
  8# While it is doing this, we can use our microcontroller to do other things,
  9# Then, when the FIFO is full (or close to), we can quickly read in the 32 samples.
 10
 11# In order to use the FIFO in this way, we need to set it up to fire an interrupt
 12# when it gets "almost full". This threshold of samples is called the "watermark".
 13# When the watermark level is reached, it will fire the interrupt INT1.
 14# Our raspi will be monitoring the watermark int source bit, and then quickly
 15# read whatevers in the FIFO and save it to a log file.
 16# Note, we can't print the data in real time to the terminal
 17# because python terminal is too slow.
 18
 19# Some timestamps of each stage of this cycle will also be printed.
 20# This will allow us to fine tune bandwidth and watermark settings.
 21# The "Entries" of the FIFO_STATUS register will also be printed before each read.
 22# This will tell us how many samples are currently held in the FIFO.
 23# This will allow us to read the entire contents and keep an eye on how full it is
 24# getting before each read. This will help us fine tune how much time we have
 25# between each read to do other things. (in this example, we are simplly going to do
 26# a delay and print dots, but you could choose to do more useful things).
 27
 28# **SPI app note***
 29# Note, this example uses I2C to communicate the the sensor.
 30# If you are going to use SPI, then you will need to add in a sufficient
 31# delay in between reads (at least 5uSec), to allow the FIFO to "pop" the next
 32# reading in the data registers. See datasheet page 16 for more info.
 33
 34# ///// FIFO setup //////
 35# Stream mode
 36# Trigger INT1, Note, this example does not utilize monitoring this hardware interrupt.
 37# We will be monitoring via software by reading the int source and watching the 
 38# watermark bit.
 39# Watermark Threshold (aka (samples in FIFO_CTL register)): 30
 40
 41# ///// Interrupt setup //////
 42# Enable watermark interrupt.
 43# Map watermark interrupt to "int pin 1".
 44# This harware interrupt pin setup could be monitored by a GPIO on the raspi,
 45# or external system, however, for this example, we will simply
 46# poll the interrupt register via software to monitor its status.
 47
 48#------------------------------------------------------------------------
 49#
 50# Written by  SparkFun Electronics, October 2020
 51# 
 52# This python library supports the SparkFun Electroncis qwiic 
 53# qwiic sensor/board ecosystem on a Raspberry Pi (and compatable) single
 54# board computers. 
 55#
 56# More information on qwiic is at https://www.sparkfun.com/qwiic
 57#
 58# Do you like this library? Help support SparkFun. Buy a board!
 59#
 60#==================================================================================
 61# Copyright (c) 2019 SparkFun Electronics
 62#
 63# Permission is hereby granted, free of charge, to any person obtaining a copy 
 64# of this software and associated documentation files (the "Software"), to deal 
 65# in the Software without restriction, including without limitation the rights 
 66# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 67# copies of the Software, and to permit persons to whom the Software is 
 68# furnished to do so, subject to the following conditions:
 69#
 70# The above copyright notice and this permission notice shall be included in all 
 71# copies or substantial portions of the Software.
 72#
 73# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 74# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 75# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 76# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 77# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 78# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 79# SOFTWARE.
 80#==================================================================================
 81# Example 7
 82#
 83
 84from __future__ import print_function
 85import qwiic_adxl313
 86import time
 87import sys
 88
 89lastWatermarkTime = 0 # used for printing timestamps in debug
 90fifoEntriesAmount = 0 # used to know how much is currently in the fifo and make sure to read it all out.
 91
 92def micros():
 93	return round(time.time_ns()/1000)
 94
 95# Open a log file in "append mode", We must log data here because printing to terminal is too slow
 96logfile = open("log.txt","a")
 97
 98def runExample():
 99
100	print("\nSparkFun Adxl313  Example 7 - FIFO reading with debug info about timing.\n")
101	myAdxl = qwiic_adxl313.QwiicAdxl313()
102
103	if myAdxl.connected == False:
104		print("The Qwiic ADXL313 device isn't connected to the system. Please check your connection", \
105			file=sys.stderr)
106		return
107	else:
108		print("Device connected successfully.")        
109  
110	myAdxl.standby()	# Must be in standby before changing settings.
111						# This is here just in case we already had sensor powered and/or
112						# configured from a previous setup.
113
114	myAdxl.setRange(myAdxl.ADXL313_RANGE_4_G)
115
116	# set bandwidth
117	# note, 12.5Hz was chosen for this example to highlight the FIFO wait/read cycle
118	# you can tweak BW and the fifo sample threshhold to suit your application.
119	myAdxl.setBandwidth(myAdxl.ADXL313_BW_12_5)
120	# also try:
121	# myAdxl.bandwidth = myAdxl.ADXL313_BW_12_5
122
123	# setup activity sensing options
124	myAdxl.setActivityX(False)		# disable x-axis participation in detecting activity
125	myAdxl.setActivityY(False)		# disable y-axis participation in detecting activity
126	myAdxl.setActivityZ(False)		# disable z-axis participation in detecting activity
127
128	# setup inactivity sensing options
129	myAdxl.setInactivityX(False)		# disable x-axis participation in detecting inactivity
130	myAdxl.setInactivityY(False)		# disable y-axis participation in detecting inactivity
131	myAdxl.setInactivityZ(False)		# disable z-axis participation in detecting inactivity
132
133	# FIFO SETUP
134	myAdxl.setFifoMode(myAdxl.ADXL313_FIFO_MODE_STREAM)
135	myAdxl.setFifoSamplesThreshhold(30) # can be 1-32
136
137	# Interrupt Mapping
138	# when fifo fills up to watermark level, it will effect the int1 pin on the sensor
139	myAdxl.setInterruptMapping(myAdxl.ADXL313_INT_WATERMARK_BIT, myAdxl.ADXL313_INT1_PIN)
140
141	# enable/disable interrupts
142	# note, we set them all here, just in case there were previous settings,
143	# that need to be changed for this example to work properly.
144	myAdxl.ActivityINT(0)		# disable activity
145	myAdxl.InactivityINT(0)		# disable inactivity
146	myAdxl.DataReadyINT(0)		# disable dataready
147	myAdxl.WatermarkINT(1)		# enable watermark
148
149	myAdxl.autosleepOff()		# just in case it was set from a previous setup
150	
151	myAdxl.measureModeOn()		# wakes up sensor from stanby and puts into measurement mode
152
153	# print int enable statuses, to verify we're setup correctly
154	print("activity int enable: ", myAdxl.isInterruptEnabled(myAdxl.ADXL313_INT_ACTIVITY_BIT))
155	print("inactivity int enable: ", myAdxl.isInterruptEnabled(myAdxl.ADXL313_INT_INACTIVITY_BIT))
156	print("dataReady int enable: ", myAdxl.isInterruptEnabled(myAdxl.ADXL313_INT_DATA_READY_BIT))
157	print("FIFO watermark int enable: ", myAdxl.isInterruptEnabled(myAdxl.ADXL313_INT_WATERMARK_BIT))
158	print("FIFO watermark Samples Threshhold: ", myAdxl.getFifoSamplesThreshhold())
159	print("FIFO mode: ", myAdxl.getFifoMode())
160	
161	lastWatermarkTime = micros()
162
163	myAdxl.clearFifo() # clear FIFO for a fresh start on this example.
164	# The FIFO may have been full from previous use
165	# and then would fail to cause an interrupt when starting this example.
166
167	uSecTimer = 0 # used to print some "dots" during down time in cycle
168	while True:
169		myAdxl.updateIntSourceStatuses() # this will update all INTSOURCE statuses.
170		if myAdxl.ADXL313_INTSOURCE_WATERMARK:
171			entries = myAdxl.getFifoEntriesAmount()
172			timegap_us = (micros() - lastWatermarkTime)
173			timegap_ms = round(timegap_us / 1000)
174			
175			print("\nWatermark Interrupt! Time since last read: ", timegap_us, "us ", timegap_ms, "ms Entries:", entries)
176			lastWatermarkTime = micros()
177			while entries > 0:
178				myAdxl.updateIntSourceStatuses() # this will update all INTSOURCE statuses.
179				if myAdxl.ADXL313_INTSOURCE_DATAREADY:
180					myAdxl.readAccel() # read all axis from sensor, note this also updates all instance variables
181
182					# Gotta log data to a text file, because printing to terminal is too slow
183					logfile.write(str(myAdxl.x))
184					logfile.write("\t")
185					logfile.write(str(myAdxl.y))
186					logfile.write("\t")
187					logfile.write(str(myAdxl.z))
188					logfile.write("\n")
189					entries -= 1 # we've read one more entry, so let's keep track and keep going until we're done
190				else:
191					print("Waiting for Data.")
192		
193		time.sleep(0.000001) # sleep 1 microsecond
194		uSecTimer += 1
195		if uSecTimer > 100:
196			print(".", end = '')
197			uSecTimer = 0
198
199
200if __name__ == '__main__':
201	try:
202		runExample()
203	except (KeyboardInterrupt, SystemExit) as exErr:
204		print("\nEnding Example 1")
205		logfile.close() 
206		sys.exit(0)
207
208