diff --git a/pypozyx/lib.py b/pypozyx/lib.py index ef47483..b4bc789 100755 --- a/pypozyx/lib.py +++ b/pypozyx/lib.py @@ -9,7 +9,7 @@ from pypozyx.core import PozyxCore -from pypozyx.structures.generic import Data, SingleRegister, dataCheck +from pypozyx.structures.generic import Data, SingleRegister, dataCheck, Buffer from pypozyx.structures.device import * from pypozyx.structures.sensor_data import * @@ -884,6 +884,63 @@ def getDeviceRangeInfo(self, device_id, device_range, remote_id=None): assert device_id[0] != 0, 'getDeviceRangeInfo: device ID = 0' return self.useFunction(POZYX_DEVICE_GETRANGEINFO, device_id, device_range, remote_id) + def getDeviceCir(self, list_offset, data_length, cir_buffer, remote_id=None): + """ + Obtain the CIR buffer of the device + Args: + list_buffer_offset: list of different values of the buffer offset + to start reading the the data bytes. Possible values range + between 0 and 1015. Type: uint16_t + data_length : Data length. The number of coefficients to read from the CIR buffer. + possible values range between 1 and 49. + Kwargs: + remote_id: Remote Pozyx ID. Not et implemented + Returns: + POZYX_SUCCESS, POZYX_FAILURE, POZYX_TIMEOUT + + Example usage: + + >>> list_offset = range(600,1015,49) + >>> cirbuff = Buffer([0]*96,size=2,signed=1) + >>> self.getDeviceCir(list_offset,49,Buff) + >>> print Buff + """ + if not dataCheck(cir_buffer): + cir_buffer = Buffer(cir_buffer) + if not isinstance(list_offset, list): + list_offset = [list_offset] + status = [] + for uoff, offset in enumerate(list_offset): + buff_tmp = Buffer([0] * 96, size=2, signed=1) + status.append(self.getDeviceCirData(offset, data_length, buff_tmp,remote_id)) + cir_buffer.fill(uoff * len(buff_tmp.data), buff_tmp.data) + return sum(status) / len(list_offset) + + def getDeviceCirData(self, buffer_offset, data_length, cir_buffer, remote_id=None): + """ + Obtain the CIR buffer of the device at a given buffer_offset and a given data_length. + Args: + buffer_offset: CIR buffer offset. This value indicates where the offset inside the CIR + buffer to start reading the the data bytes. Possible values range + between 0 and 1015. Type: uint16_t + data_length : Data length. The number of coefficients to read from the CIR buffer. + possible values range between 1 and 49. + Kwargs: + remote_id: Remote Pozyx ID. Not et implemented + Returns: + POZYX_SUCCESS, POZYX_FAILURE, POZYX_TIMEOUT + + Example usage: + + >>> cirbuff = Buffer([0]*96,size=2,signed=1) + >>> self.getDeviceCirData(0,49,Buff) + >>> print Buff + """ + if not dataCheck(cir_buffer): + cir_buffer = Buffer(cir_buffer) + params = Data([buffer_offset, data_length], 'Hb') + return self.useFunction(POZYX_CIR_DATA, params, cir_buffer, remote_id) + def setInterruptMask(self, mask, remote_id=None): """ Set the Pozyx's interrupt mask. diff --git a/pypozyx/pozyx_serial.py b/pypozyx/pozyx_serial.py index 6dad08e..3b86946 100644 --- a/pypozyx/pozyx_serial.py +++ b/pypozyx/pozyx_serial.py @@ -59,6 +59,7 @@ class PozyxSerial(PozyxLib): def __init__(self, port, baudrate=115200, timeout=0.1, print_output=False): """Initializes the PozyxSerial object. See above for details.""" self.print_output = print_output + try: self.ser = Serial(port, baudrate, timeout=timeout) except: @@ -174,6 +175,7 @@ def regFunction(self, address, params, data): """ params.load_hex_string() s = 'F,%0.2x,%s,%i\r' % (address, params.byte_data, data.byte_size + 1) + try: r = self.serialExchange(s) except: diff --git a/pypozyx/structures/device.py b/pypozyx/structures/device.py index cb07494..650e7a7 100755 --- a/pypozyx/structures/device.py +++ b/pypozyx/structures/device.py @@ -175,6 +175,7 @@ def load(self, data): self.data[i] = data[i] + class UWBSettings(ByteStructure): """ Container for a device's UWB settings. diff --git a/pypozyx/structures/generic.py b/pypozyx/structures/generic.py index 721ef90..9d8672d 100755 --- a/pypozyx/structures/generic.py +++ b/pypozyx/structures/generic.py @@ -222,3 +222,50 @@ def __str__(self): return bin(self.data[0]) else: return str(self.data[0]) + + + +class Buffer(Data): + """ + Buffer is container for the data from a Pozyx buffer. + + By default, this represents a UInt8 register. Used for both reading and writing. + The size and whether the data is a 'signed' integer are both changeable by the + user using the size and signed keyword arguments. + + Kwargs: + value: list of values of the buffer. + size: Size of each data of the buffer. 1, 2, or 4. Default 0. + signed: Whether the data is signed. unsigned by default. + print_hex: How to print the register output. Hex by default. Special options are 'hex' and 'bin' + other things, such as 'dec', will return decimal output. + """ + + def __init__(self, value=[0], size=1, signed=0, print_style='hex'): + self.print_style = print_style + if size == 1: + data_format = 'b' + elif size == 2: + data_format = 'h' + elif size == 4: + data_format = 'i' + if signed == 0: + data_format = data_format.capitalize() + extend_data_format = ''.join([data_format]*len(value)) + Data.__init__(self, value, extend_data_format) + + def load(self, data, convert=1): + self.data = data + + def __str__(self): + if self.print_style is 'hex': + return str([hex(d).capitalize() for d in self.data]) + elif self.print_style is 'bin': + return str([bin(d) for d in self.data]) + else: + return str([d for d in self.data]) + + def fill(self,offset,values): + if not isinstance(values,list): + values = [values] + self.data[offset:offset+len(values)] = values \ No newline at end of file diff --git a/setup.py b/setup.py index f94f9c3..800cabb 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from distutils.core import setup +from setuptools import setup setup( name='pypozyx', diff --git a/tutorials/get_cir.py b/tutorials/get_cir.py new file mode 100644 index 0000000..6db5ace --- /dev/null +++ b/tutorials/get_cir.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +ready_to_range.py - Tutorial intended to show how to perform ranging between two Pozyx devices. + +It is planned to make a tutorial on the Pozyx site as well just like there is now +one for the Arduino, but their operation is very similar. +You can find the Arduino tutorial here: + https://www.pozyx.io/Documentation/Tutorials/ready_to_range +""" +from pypozyx import * + +from pypozyx.definitions.registers import * + + +port = '/dev/ttyACM1' +p = PozyxSerial(port) + +remote_id = 0x6830 # the network ID of the remote device +remote = False # whether to use the given remote device for ranging +if not remote: + remote_id = None + +destination_id = 0x6830 # network ID of the ranging destination +range_step_mm = 1000 # distance that separates the amount of LEDs lighting up. + + +device_range = DeviceRange() +status = p.doRanging(destination_id, device_range, remote_id) +if status: + list_offset = range(0, 1015, 49) + data_length = 49 + cir_buffer = Buffer([0] * 98 * len(list_offset), size=2, signed=1) + status_cir = p.getDeviceCir(list_offset, data_length, cir_buffer, remote_id) + if status_cir: + try: + import matplotlib.pyplot as plt + import numpy as np + #  get real and imaginarypart of the cir buffer + real = np.array(cir_buffer.data[0::2]) + imag = np.array(cir_buffer.data[1::2]) + # create an image of the CIR + cira = real + 1j*imag + # That plots the CIR contains in the buffer. + # It still requires post-procesing to + # re-align delay and received power level. + plt.plot(20*np.log10(abs(cira[:-36]))) + plt.show() + except: + print cir_buffer + else: + print 'error in getting cir' +else: + print 'Ranging failed' \ No newline at end of file diff --git a/tutorials/ready_to_range.py b/tutorials/ready_to_range.py index 6b18e6b..9afffb3 100644 --- a/tutorials/ready_to_range.py +++ b/tutorials/ready_to_range.py @@ -51,14 +51,14 @@ def ledControl(self, distance): return status if __name__ == "__main__": - port = 'COM1' # COM port of the Pozyx device + port = '/dev/ttyACM0' # COM port of the Pozyx device remote_id = 0x605D # the network ID of the remote device remote = False # whether to use the given remote device for ranging if not remote: remote_id = None - destination_id = 0x1000 # network ID of the ranging destination + destination_id = 0x6830 # network ID of the ranging destination range_step_mm = 1000 # distance that separates the amount of LEDs lighting up. pozyx = PozyxSerial(port)