Skip to content

Commit fcf6a0d

Browse files
jithinbpmariobehling
authored andcommitted
Improved auto-generated menus in graphical apps. Modified MPU6050.py. Added MPU925x.py . Fixed Sensorpendulum App & I2C oscilloscope (fossasia#57)
* Add support for ADS1115 16-bit ADC Partly Fixes fossasia#45 . * modify Params dict in MPU6050.py as an example for improving sensor Menus refer to fossasia#55 , and fossasia/pslab-desktop#89 * MPU6050.py : remove powerUp function's argument refer to fossasia#55 , and fossasia/pslab-desktop#89 * MPU6050.py : Kalman Filtering's options defined in a dictionary element refer to fossasia#55 , and fossasia/pslab-desktop#89 * Modified Params dictionary in all Sensor files Fixes fossasia#55. Improved GUI menus * Convert I2C sensor oscilloscope into non-blocking method Fixes#58 . Separate methods for starting acquisition, fetching data buffer, and processing data buffer have been implemented in Peripherals.I2C * add support library for MPU925x 10-DOF IMU sensor fixes fossasia#59 * Convert I2C sensor oscilloscope into non-blocking method Fixes fossasia#58 . Separate methods for starting acquisition, fetching data buffer, and processing data buffer have been implemented in Peripherals.I2C * add support library for MPU925x 10-DOF IMU sensor fixes fossasia#59
1 parent d2ec0d6 commit fcf6a0d

File tree

8 files changed

+338
-19
lines changed

8 files changed

+338
-19
lines changed

PSL/Peripherals.py

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from __future__ import print_function
2-
import PSL.commands_proto as CP
2+
import commands_proto as CP
33
import numpy as np
44
import time, inspect
55

@@ -33,7 +33,11 @@ class I2C():
3333
>>> print (x,y,z)
3434
3535
"""
36-
36+
samples = 0
37+
total_bytes=0
38+
channels = 0
39+
tg=100
40+
MAX_SAMPLES = 10000
3741
def __init__(self, H):
3842
self.H = H
3943
from PSL import sensorlist
@@ -375,6 +379,123 @@ def scan(self, frequency=100000, verbose=False):
375379
self.stop()
376380
return addrs
377381

382+
def __captureStart__(self,address,location,sample_length,total_samples,tg):
383+
"""
384+
Blocking call that starts fetching data from I2C sensors like an oscilloscope fetches voltage readings
385+
You will then have to call `__retrievebuffer__` to fetch this data, and `__dataProcessor` to process and return separate channels
386+
refer to `capture` if you want a one-stop solution.
387+
388+
.. tabularcolumns:: |p{3cm}|p{11cm}|
389+
================== ============================================================================================
390+
**Arguments**
391+
================== ============================================================================================
392+
address Address of the I2C sensor
393+
location Address of the register to read from
394+
sample_length Each sample can be made up of multiple bytes startng from <location> . such as 3-axis data
395+
total_samples Total samples to acquire. Total bytes fetched = total_samples*sample_length
396+
tg timegap between samples (in uS)
397+
================== ============================================================================================
398+
399+
:return: Arrays X(timestamps),Y1,Y2 ...
400+
401+
"""
402+
if(tg<20):tg=20
403+
total_bytes = total_samples*sample_length
404+
print ('total bytes calculated : ',total_bytes)
405+
if(total_bytes>self.MAX_SAMPLES*2):
406+
print ('Sample limit exceeded. 10,000 int / 20000 bytes total')
407+
total_bytes = self.MAX_SAMPLES*2
408+
total_samples = total_bytes/sample_length #2* because sample array is in Integers, and we're using it to store bytes
409+
410+
411+
print ('length of each channel : ',sample_length)
412+
self.total_bytes = total_bytes
413+
self.channels = sample_length
414+
self.samples = total_samples
415+
self.tg = tg
416+
417+
self.H.__sendByte__(CP.I2C_HEADER)
418+
self.H.__sendByte__(CP.I2C_START_SCOPE)
419+
self.H.__sendByte__(address)
420+
self.H.__sendByte__(location)
421+
self.H.__sendByte__(sample_length)
422+
self.H.__sendInt__(total_samples) #total number of samples to record
423+
self.H.__sendInt__(tg) #Timegap between samples. 1MHz timer clock
424+
self.H.__get_ack__()
425+
return 1e-6*self.samples*self.tg+.01
426+
427+
def __retrievebuffer__(self):
428+
'''
429+
Fetch data acquired by the I2C scope. refer to :func:`__captureStart__`
430+
431+
'''
432+
total_int_samples = self.total_bytes/2
433+
DATA_SPLITTING = 500
434+
print ('fetchin samples : ',total_int_samples,' split',DATA_SPLITTING)
435+
data=b''
436+
for i in range(int(total_int_samples/DATA_SPLITTING)):
437+
self.H.__sendByte__(CP.ADC)
438+
self.H.__sendByte__(CP.GET_CAPTURE_CHANNEL)
439+
self.H.__sendByte__(0) #starts with A0 on PIC
440+
self.H.__sendInt__(DATA_SPLITTING)
441+
self.H.__sendInt__(i*DATA_SPLITTING)
442+
rem = DATA_SPLITTING*2+1
443+
for a in range(200):
444+
partial = self.H.fd.read(rem) #reading int by int sometimes causes a communication error. this works better.
445+
rem -=len(partial)
446+
data+=partial
447+
#print ('partial: ',len(partial), end=",")
448+
if rem<=0:
449+
break
450+
data=data[:-1]
451+
#print ('Pass : len=',len(data), ' i = ',i)
452+
453+
if total_int_samples%DATA_SPLITTING:
454+
self.H.__sendByte__(CP.ADC)
455+
self.H.__sendByte__(CP.GET_CAPTURE_CHANNEL)
456+
self.H.__sendByte__(0) #starts with A0 on PIC
457+
self.H.__sendInt__(total_int_samples%DATA_SPLITTING)
458+
self.H.__sendInt__(total_int_samples-total_int_samples%DATA_SPLITTING)
459+
rem = 2*(total_int_samples%DATA_SPLITTING)+1
460+
for a in range(20):
461+
partial = self.H.fd.read(rem) #reading int by int sometimes causes a communication error. this works better.
462+
rem -=len(partial)
463+
data+=partial
464+
#print ('partial: ',len(partial), end="")
465+
if rem<=0:
466+
break
467+
data=data[:-1]
468+
print ('Final Pass : len=',len(data))
469+
return data
470+
471+
def __dataProcessor__(self,data,*args):
472+
'''
473+
Interpret data acquired by the I2C scope. refer to :func:`__retrievebuffer__` to fetch data
474+
475+
================== ============================================================================================
476+
**Arguments**
477+
================== ============================================================================================
478+
data byte array returned by :func:`__retrievebuffer__`
479+
*args supply optional argument 'int' if consecutive bytes must be combined to form short integers
480+
================== ============================================================================================
481+
482+
'''
483+
484+
try:
485+
data = [ord(a) for a in data]
486+
if('int' in args):
487+
for a in range(self.channels*self.samples/2): self.buff[a] = np.int16((data[a*2]<<8)|data[a*2+1])
488+
else:
489+
for a in range(self.channels*self.samples): self.buff[a] = data[a]
490+
491+
yield np.linspace(0,self.tg*(self.samples-1),self.samples)
492+
for a in range(int(self.channels/2)):
493+
yield self.buff[a:self.samples*self.channels/2][::self.channels/2]
494+
except Exception as ex:
495+
msg = "Incorrect number of bytes received",ex
496+
raise RuntimeError(msg)
497+
498+
378499
def capture(self, address, location, sample_length, total_samples, tg, *args):
379500
"""
380501
Blocking call that fetches data from I2C sensors like an oscilloscope fetches voltage readings

PSL/SENSORS/BH1750.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class BRIDGE():
2323
# for changing various options of this sensor
2424
# It's a dictionary of the string representations of functions matched with an array
2525
# of options that each one can accept
26-
params = {'init': ['Now'],
26+
params = {'init': None,
2727
'setRange': gain_literal_choices,
2828
}
2929

@@ -35,9 +35,9 @@ class BRIDGE():
3535
def __init__(self, I2C, **args):
3636
self.I2C = I2C
3737
self.ADDRESS = args.get('address', 0x23)
38-
self.init('')
38+
self.init()
3939

40-
def init(self, dummy_variable_to_circumvent_framework_limitation): # I know how to fix this now. remind me.
40+
def init(self):
4141
self.I2C.writeBulk(self.ADDRESS, [self.RES_500mLx])
4242

4343
def setRange(self, g):

PSL/SENSORS/HMC5883L.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class HMC5883L():
3030
# for changing various options of this sensor
3131
# It's a dictionary of the string representations of functions matched with an array
3232
# of options that each one can accept
33-
params = {'init': ['Now'],
33+
params = {'init': None,
3434
'setSamplesToAverage': samplesToAverage_choices,
3535
'setDataOutputRate': dataOutputRate_choices,
3636
'setGain': gain_choices,
@@ -51,9 +51,9 @@ def __init__(self, I2C, **args):
5151
except:
5252
print 'FAILED TO CHANGE BAUD RATE'
5353
'''
54-
self.init('')
54+
self.init()
5555

56-
def init(self, dummy_variable_to_circumvent_framework_limitation): # I know how to fix this now. remind me.
56+
def init(self):
5757
self.__writeCONFA__()
5858
self.__writeCONFB__()
5959
self.I2C.writeBulk(self.ADDRESS, [self.MODE, 0]) # enable continuous measurement mode

PSL/SENSORS/MLX90614.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __init__(self, I2C, **args):
2121
self.source = self.OBJADDR
2222

2323
self.name = 'Passive IR temperature sensor'
24-
self.params = {'readReg': range(0x20),
24+
self.params = {'readReg': {'dataType':'integer','min':0,'max':0x20,'prefix':'Addr: '} ,
2525
'select_source': ['object temperature', 'ambient temperature']}
2626

2727
try:

PSL/SENSORS/MPU6050.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ def __init__(self, I2C, **args):
3333
self.I2C = I2C
3434
self.ADDRESS = args.get('address', self.ADDRESS)
3535
self.name = 'Accel/gyro'
36-
self.params = {'powerUp': ['Go'], 'setGyroRange': [250, 500, 1000, 2000], 'setAccelRange': [2, 4, 8, 16],
37-
'KalmanFilter': [.01, .1, 1, 10, 100, 1000, 10000, 'OFF']}
36+
self.params = {'powerUp': None, 'setGyroRange': [250, 500, 1000, 2000], 'setAccelRange' : [2, 4, 8, 16],
37+
'KalmanFilter': {'dataType':'double','min':0,'max':1000,'prefix':'value: '} }
3838
self.setGyroRange(2000)
3939
self.setAccelRange(16)
4040
'''
@@ -43,11 +43,11 @@ def __init__(self, I2C, **args):
4343
except:
4444
pass
4545
'''
46-
self.powerUp(True)
46+
self.powerUp()
4747
self.K = None
4848

4949
def KalmanFilter(self, opt):
50-
if opt == 'OFF':
50+
if opt == 0:
5151
self.K = None
5252
return
5353
noise = [[]] * self.NUMPLOTS
@@ -64,7 +64,7 @@ def getVals(self, addr, bytes):
6464
vals = self.I2C.readBulk(self.ADDRESS, addr, bytes)
6565
return vals
6666

67-
def powerUp(self, x):
67+
def powerUp(self):
6868
self.I2C.writeBulk(self.ADDRESS, [0x6B, 0])
6969

7070
def setGyroRange(self, rs):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy