TMF8701 ToF Distance Sensor from AMS with Python - python
I am trying to send a command to the command register from my TMF8701 sensor from AMS with Python code from a Raspberry Pi. I have to of these sensors connected to the I2C Bus of the Raspberry Pi. One for channel 1 and one for channel 0. I am writing the 0x10 register with 0x0A and trying to do the factory calibration. But after this command is written, the 0x1E register does not have the correct value. I also tried to write another command, for example 0x0B, but also the 0x1E register does not return the correct value. Can anyone help me?
import smbus
from time import sleep
CMD_DATA0=0x0F
CMD_DATA1=0x0E
CMD_DATA2=0x0D
CMD_DATA3=0x0C
CMD_DATA4=0x0B
CMD_DATA5=0x0A
CMD_DATA6=0x09
CMD_DATA7=0x08
CMD_DATA8=0x07
CMD_DATA9=0x06
#14 Byte
FACTORY_CALIBRATION=0x28
class tmf8701_distanceSensor():
# by default, this assumes that the device is at 0x41
def __init__(self, channel, address=0x41):
self.address = address
self.channel = channel
self.bus = smbus.SMBus(self.channel)
#self.reset()
sleep(1) # wait 1 sec
self.setup()
#def reset(self):
#0x10 - command
#factoryCalibrationValue=""
def factoryCalibration(self):
sleep(2)
self.bus.write_i2c_block_data(self.address, 0x10, [0x0A])
#while (self.bus.read_byte_data(self.address, 0x1E))!=0x0A:
#sleep(1)
#print("while")
sleep(10)
#print("factory calibration")
#print(str(int(self.bus.read_byte_data(self.address, 0x1E))), str(int(0x0A)))
#Factory Calibration begins 0x20 und dann 14 byte
block=self.bus.read_i2c_block_data(self.address, 0x20, 14)
print(block)
print(self.bus.read_byte_data(self.address, 0x2c))
print(self.bus.read_byte_data(self.address, 0x2d))
print(self.bus.read_byte_data(self.address, 0x01))
"""def bootloaderReadyForNewCommand(self):
#CMD_STAT register - 0x0 - READY
#0x10-0xFF - busy - davor error und gut !
read0x10Register=self.bus.read_byte_data(self.address, 0x10)
if read0x10Register == 0:
return("ready")
elif read0x10Register < int(0x10):
return read0x10Register
else:
print("try again later??? ")
return "busy"""""
def readResults(self):
print("erst 0x20")
print(self.bus.read_byte_data(self.address, 0x20))
print("dann 0x1D")
print(self.bus.read_byte_data(self.address, 0x1D))
print("dann 0x20")
print(self.bus.read_byte_data(self.address, 0x20))
print("zuletzt 0x1E")
print(self.bus.read_byte_data(self.address, 0x1E))
def setDeviceInStandBy(self):
self.bus.write_i2c_block_data(self.address, 0xE0, [0x00])
def setup(self):
###bootloader settings:
if not self.bus.read_byte_data(self.address, 0x00)==0x80:
self.bus.write_i2c_block_data(self.address, 0x00, [0x80])
#wake up sensor
self.bus.write_i2c_block_data(self.address, 0xE0, [0x01])
sleep(3)
###
read0xE0Register=self.bus.read_byte_data(self.address, 0xE0)
print("register 0xE0, if 65 => perfect!")
print(read0xE0Register)
### app0 settings:
if not self.bus.read_byte_data(self.address, 0x00)==0xC0:
self.bus.write_i2c_block_data(self.address, 0x00, [0xC0])
self.bus.write_i2c_block_data(self.address, 0x10, [0x0B])
#read serial number
self.bus.write_i2c_block_data(self.address, 0x10, [0x47])
#while (self.bus.read_byte_data(self.address, 0x1E))!=0x0A:
#sleep(1)
#print("while")
sleep(10)
print("serialdata")
print(self.bus.read_byte_data(self.address, 0x1E))
block=self.bus.read_i2c_block_data(self.address, 0x28, 3)
print(block)
#print("factory calibration")
#print(str(int(self.bus.read_byte_data(self.address, 0x1E))), str(int(0x0A)))
#Factory Calibration begins 0x20 und dann 14 byte
#block=self.bus.read_i2c_block_data(self.address, 0x1E, )
#print(block)
self.factoryCalibration()
print("currently running SW register: 128 = 0x80 - bootloader, 192 = 0xC0 - App0 ")
print(self.bus.read_byte_data(self.address, 0x00))
###algorithm state and factory calibration is provided
self.bus.write_i2c_block_data(self.address, CMD_DATA7, [0x03])
###
self.bus.write_i2c_block_data(self.address, CMD_DATA6, [0x23])
### no GPIO control used
self.bus.write_i2c_block_data(self.address, CMD_DATA5, [0x00])
self.bus.write_i2c_block_data(self.address, CMD_DATA4, [0x00])
### needs to be always 00
self.bus.write_i2c_block_data(self.address, CMD_DATA3, [0x00])
### repetition period in ms 64 hex = 100ms
self.bus.write_i2c_block_data(self.address, CMD_DATA2, [0x64])
### needs to be always ff
self.bus.write_i2c_block_data(self.address, CMD_DATA1, [0xFF])
self.bus.write_i2c_block_data(self.address, CMD_DATA0, [0xFF])
import csv,os
import numpy as np
import threading
#import max30102
import TMF8701_distanceSensor
import datetime
import time
from numpy import number
print("start")
print("sensor finger")
sensorTMF_finger=TMF8701_distanceSensor.tmf8701_distanceSensor(0)
#sensorTMF_finger.factoryCalibration()
print("sensor hand")
sensorTMF_hand=TMF8701_distanceSensor.tmf8701_distanceSensor(1)
#sensorTMF_hand.factoryCalibration()
number=0
while number<10:
print("hand")
#sensorTMF_hand.readResults()
print("finger")
sensorTMF_finger.readResults()
number=number+1
The output I get on the Raspberry Pi looks like that:
start
sensor finger
register 0xE0, if 65 => perfect!
65
serialdata
0
[0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
0
0
16
currently running SW register: 128 = 0x80 - bootloader, 192 = 0xC0 - App0
192
sensor hand
register 0xE0, if 65 => perfect!
65
serialdata
0
[0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
0
0
16
currently running SW register: 128 = 0x80 - bootloader, 192 = 0xC0 - App0
192
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
hand
finger
erst 0x20
0
dann 0x1D
0
dann 0x20
0
zuletzt 0x1E
0
Related
Python, HEX, Serial, and Print
Using Python 3, I need to write data 0x00 - 0xff through serial one byte at a time and also want to print on the screen the current byte in Hex where it is in the loop. Now that I've been working on this, it seems like I can just make a simple for loop counting from 0 - 255 and send that. But, for learning purposes is the way I declared this variable correct? # Characters to test, all 255 chars mytest = { '\00', '\01', '\02', '\03', '\04', '\05', '\06', '\07', '\08', '\09', '\0a', '\0b', '\0c', '\0d', '\0e', '\0f', \ '\10', '\11', '\12', '\13', '\14', '\15', '\16', '\17', '\18', '\19', '\1a', '\1b', '\1c', '\1d', '\1e', '\1f', \ '\20', '\21', '\22', '\23', '\24', '\25', '\26', '\27', '\28', '\29', '\2a', '\2b', '\2c', '\2d', '\2e', '\2f', \ '\30', '\31', '\32', '\33', '\34', '\35', '\36', '\37', '\38', '\39', '\3a', '\3b', '\3c', '\3d', '\3e', '\3f', \ '\40', '\41', '\42', '\43', '\44', '\45', '\46', '\47', '\48', '\49', '\4a', '\4b', '\4c', '\4d', '\4e', '\4f', \ '\50', '\51', '\52', '\53', '\54', '\55', '\56', '\57', '\58', '\59', '\5a', '\5b', '\5c', '\5d', '\5e', '\5f', \ '\60', '\61', '\62', '\63', '\64', '\65', '\66', '\67', '\68', '\69', '\6a', '\6b', '\6c', '\6d', '\6e', '\6f', \ '\70', '\71', '\72', '\73', '\74', '\75', '\76', '\77', '\78', '\79', '\7a', '\7b', '\7c', '\7d', '\7e', '\7f', \ '\80', '\81', '\82', '\83', '\84', '\85', '\86', '\87', '\88', '\89', '\8a', '\8b', '\8c', '\8d', '\8e', '\8f', \ '\90', '\91', '\92', '\93', '\94', '\95', '\96', '\97', '\98', '\99', '\9a', '\9b', '\9c', '\9d', '\9e', '\9f', \ '\a0', '\a1', '\a2', '\a3', '\a4', '\a5', '\a6', '\a7', '\a8', '\a9', '\aa', '\ab', '\ac', '\ad', '\ae', '\af', \ '\b0', '\b1', '\b2', '\b3', '\b4', '\b5', '\b6', '\b7', '\b8', '\b9', '\ba', '\bb', '\bc', '\bd', '\be', '\bf', \ '\c0', '\c1', '\c2', '\c3', '\c4', '\c5', '\c6', '\c7', '\c8', '\c9', '\ca', '\cb', '\cc', '\cd', '\ce', '\cf', \ '\d0', '\d1', '\d2', '\d3', '\d4', '\d5', '\d6', '\d7', '\d8', '\d9', '\da', '\db', '\dc', '\dd', '\de', '\df', \ '\e0', '\e1', '\e2', '\e3', '\e4', '\e5', '\e6', '\e7', '\e8', '\e9', '\ea', '\eb', '\ec', '\1e', '\ee', '\ef', \ '\f0', '\f1', '\f2', '\f3', '\f4', '\f5', '\f6', '\f7', '\f8', '\f9', '\fa', '\fb', '\fc', '\fd', '\fe', '\ff' } for c in mytest: print (" ".join(hex(ord(n)) for n in c)) serial.write(c) # Let's pretend this sends the same to the serial port I defined somewhere. Reading posts here, I have come up with the above to print the hex to screen. Which works, sort of.. when I put in one char at a time to test with. However instead of 0x00 it is printing 0x0 I am expecting two 00's well, three I guess 0x00. AND when I run it in the loop, I get all sorts of unexpected output. lol Test output using single bytes.. 0x0 0x1 0x2 Output when running in the for loop... 0x5c 0x38 0x39 0xc 0x8 0x7 0x30 0x5c 0x63 0x65 0x5c 0x39 0x36 0x5c 0x38 0x35 0x5c 0x64 0x36 0x5c 0x65 0x35 0x5c 0x38 0x37 0xc 0x30 0x5c 0x63 0x61 0x4 0x39 0x5c 0x64 0x64 0x0 0x65 0x1e 0x5c 0x63 0x31 0x24 0x4 0x61 0x8 0x37 0x7 0x37 0x8 0x38 0x1b 0x4 0x38 0x26 0x4 0x66 0x2e 0x5c 0x38 0x64 0x5c 0x39 0x64 0x5c 0x64 0x38 0x0 0x2 0x63 0x5c 0x39 0x61 0x27 0x5 0x65 0x3 0x64 0x3 0x15 0x2 0x39 0x19 0x5 0x63 0x5c 0x64 0x35 0x7 0x39 0x8 0x66 0xc 0x31 0x5c 0x64 0x63 0x5 0x3 0x66 0x5c 0x63 0x62 0x5c 0x65 0x63 0x5c 0x63 0x38 0x2a 0x1d 0x5c 0x38 0x63 0x8 0x63 0x5c 0x65 0x30 0x2 0x61 0x1 0x66 0xc 0x64 0x5c 0x65 0x62 0x5c 0x64 0x31 0x0 0x64 0xe 0x5 0x64 0x5c 0x65 0x37 0x5c 0x38 0x38 0x5c 0x65 0x39 0x5c 0x63 0x36 0xc 0x36 0x7 0x36 0x5c 0x65 0x31 0xb 0x2f 0x8 0x62 0x1 0x31 0x5c 0x38 0x61 0x1 0x39 0x2 0x38 0x6 0x38 0x1 0x62 0x3b 0x5c 0x63 0x33 0x5c 0x64 0x65 0x6 0x63 0x2b 0x5 0x66 0x8 0x64 0x5c 0x65 0x38 0x5c 0x64 0x62 0x6 0x64 0x5c 0x38 0x34 0x6 0x62 0x5c 0x39 0x30 0x6 0x61 0x16 0x1c 0x4 0x64 0xc 0x37 0x5c 0x64 0x66 0x5c 0x39 0x39 0x5c 0x63 0x39 0x8 0x32 0x3 0x65 0x11 0x28 0x5c 0x38 0x62 0x0 0x66 0xd 0x5 0x62 0x8 0x34 0x33 0x7 0x38 0x7 0x66 0x5c 0x39 0x32 0x4 0x63 0x2 0x66 0x1 0x38 0x7 0x31 0x5c 0x64 0x37 0x36 0x8 0x35 0x1 0x64 0x5c 0x39 0x31 0x5c 0x65 0x66 0x0 0x61 0x2 0x62 0x22 0x5c 0x64 0x32 0x0 0x38 0x25 0x5c 0x65 0x33 0x32 0xf 0x8 0x61 0x2 0x64 0x5c 0x63 0x34 0xc 0x38 0x7 0x61 0x8 0x36 0x2 0x65 0x1f 0x7 0x35 0x0 0x63 0xc 0x65 0x5c 0x63 0x30 0x5c 0x64 0x61 0x3 0x62 0x7 0x62 0x7 0x65 0x4 0x62 0x8 0x65 0x7 0x63 0x6 0x5c 0x39 0x66 0x5c 0x64 0x39 0x2 0xa 0x3 0x39 0x5 0x39 0x5c 0x64 0x30 0x5 0x38 0x3 0x63 0x3c 0x5c 0x63 0x37 0x7 0x64 0x9 0xc 0x63 0x3e 0x0 0x62 0x17 0xc 0x61 0x5c 0x63 0x35 0x5c 0x38 0x66 0x38 0x5c 0x64 0x33 0x5c 0x63 0x66 0x5c 0x38 0x30 0x5c 0x63 0x64 0x5c 0x65 0x65 0xc 0x34 0x5c 0x39 0x37 0x5c 0x63 0x32 0x8 0x30 0x1 0x65 0xc 0x32 0xc 0x35 0x6 0x39 0x5c 0x38 0x32 0x5c 0x65 0x61 0x3 0x38 0x5c 0x64 0x34 0x5c 0x65 0x32 0x1 0x61 0x5c 0x63 0x63 0x4 0x65 0x13 0x23 0x2c 0x3a 0x6 0x65 0x3f 0x8 0x39 0x34 0x39 0x5c 0x39 0x65 0x7 0x12 0x35 0xc 0x33 0x8 0x31 0x6 0x66 0x3 0x61 0x5c 0x38 0x36 0x18 0x0 0x39 0x37 0xc 0x39 0x5c 0x65 0x36 0x5c 0x39 0x63 0x3d 0x7 0x33 0x5c 0x38 0x33 0x5c 0x38 0x65 0x5c 0x39 0x34 0x21 0x5c 0x39 0x62 0x14 0x1a 0x7 0x34 0x5c 0x39 0x33 0x5c 0x65 0x34 0x4 0x2d 0x10 0x29 0x5c 0x39 0x35 0x1 0x63 0x20 0xc 0x62 0x7 0x32 0x5 0x61 0x8 0x33 0xc 0x66 0x30 0x5c 0x39 0x38 0x5c 0x38 0x31 Let's say the device on the other end of the serial connection is looking for "0x01, 0x02, 0x03, 0xbb" Questions: Is there a difference between 0x0 and 0x00 when sending over serial? I think it is just a representation of the same information. Therefore, 0x00 IS the same as 0x0, or 0x01 and 0x1. What is wrong with my variable declaration to make the garbage come out when I print in the loop? I think something like this will accomplish what I want, assuming 0x01 and 0x1 are the same: for x in range(256) print (" ".join(hex(ord(n)) for n in x)) serial.write(x) Thank you.
Well, for one you need to use [ and ] in the variable declaration. In Python, { makes a set, which is unordered. [ makes a list, which is ordered. Then for the actual content, you need to use \x00, not just \00. So your declaration should be mytest = [ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', \ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', \ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', \ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', \ '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', \ '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', \ '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', \ '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', \ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', \ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', \ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7', '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf', \ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7', '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf', \ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf', \ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7', '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', \ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\x1e', '\xee', '\xef', \ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' ] I'm not sure what the intention was with the line print (" ".join(hex(ord(n)) for n in c)) If there is only one character in the string c, which there is, you can just do print(hex(ord(c))) The code you had looks like it was intended to print every character as hex in a big single string. That's why it had the for n in x. That's also why the output you were getting before looked so wrong. Notice, on all the lines with multiple value, the first part was 0x5c, which is the ASCII code for \. So it was printing out the hex for \, a, b. In your simplified loop, it would be as simple as for x in range(256): print (hex(x)) serial.write(x) And as for the equivalence of 0x00 and 0x0, they are the same. The hex function in Python just returns a string that has the number in that notation. They are the same just like how the number 042 is the same as 42 in decimal. Anything you send to the serial won't even look like that. It will just be a number. But depending on the whatever serial library you are using, it probably wants a number not a string like c currently is. So you need to do serial.write(ord(c)) if you want to continue storing data as characters like that. In fact, in Python you can have numeric literals directly written as hex. So you could say x = 0x32 just fine, which would be converted to 52 when the program is run. Or your whole list could be expressed like mytest = [0x00, 0x01, 0x02, etc. Then you wouldn't need any ord at all since everything would already be a number.
SF30 Controller Bluez Programming
Bluez Question: I have a Raspberry Pi Z W, an 8bitdo SF30 bluetooth controller and a robot my employer mass produces. I am looking to control the robot from the RPI through the remote. I have the RPi connecting to the controller using bluetoothctl, and I can see the messages from the controller through btmon (bluetooth monitor). It becomes obvious that the four "80" values below correspond to the two joysticks at their mid points. > ACL Data RX: Handle 11 flags 0x02 dlen 15 #30 [hci0] 2.555574 Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535} a1 03 0f 80 80 12 31 00 00 00 00 ......1.... > ACL Data RX: Handle 11 flags 0x02 dlen 15 #31 [hci0] 2.587293 Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535} a1 03 0f 80 80 27 4b 00 00 00 00 .....'K.... > ACL Data RX: Handle 11 flags 0x02 dlen 15 #32 [hci0] 2.613543 Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535} a1 03 0f 80 80 61 7b 00 00 00 00 .....a{.... > ACL Data RX: Handle 11 flags 0x02 dlen 15 #33 [hci0] 2.615552 Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535} a1 03 0f 80 80 80 80 00 00 00 00 ........... > ACL Data RX: Handle 11 flags 0x02 dlen 15 #34 [hci0] 74.653567 Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535} a1 03 0f 80 80 80 80 00 00 00 08 ........... I have also been reading in data from the two resulting /dev/input/ files (/dev/input/js0 and /dev/input/event0) in python using format LLHHQ. I thought that the same data from btmon (which is easy to interpret) would be represented in the Q section of that format (the last number below). (470898350, 155732, 22190, 7185, 16919435) (470898350, 160124, 22190, 7185, 16916057) (470898380, 162488, 22220, 7185, 163502) (470898380, 16915382, 22260, 7185, 16910652) (470898420, 16908288, 22290, 7185, 161137) (470898450, 16971797, 22300, 7185, 155732) (470898460, 16966392, 22330, 7185, 154043) (470898490, 16966054, 22340, 7185, 147287) (470898500, 16967405, 22340, 7185, 131072) (470898500, 16908288, 22740, 7185, 151060481) (470899070, 151060480, 22970, 7185, 134283265) (470899320, 134283264, 23200, 7185, 117506049) (470899550, 117506048, 23420, 7185, 100728833) (470899750, 100728832, 23590, 7185, 117506049) (470899910, 117506048, 23930, 7185, 134283265) (470900310, 134283264, 25110, 7185, 100728833) (470901380, 117506049, 25250, 7185, 134283265) (470901490, 100728832, 25390, 7185, 117506048) (470901710, 134283264, 25580, 7185, 100728833) (470901750, 117506049, 25720, 7185, 117506048) (470901940, 134283265, 25810, 7185, 100728832) (470902160, 100728833, 26070, 7185, 134283264) (470902400, 100728832, 26690, 7185, 134283265) (470903070, 134283264, 27130, 7185, 151060481) (470903430, 151060480, 27360, 7185, 100728833) However these outputs don't appear to correspond when read into binary, for example the two joysticks seem to change the same bits. The basic of my question is how do I get the same data which is read in the btmon in a bluez-based code. This is the python code I am using at the moment. f = open( "/dev/input/js0", "rb" ); # Open the file in the read-binary mode EVENT_SIZE = struct.calcsize("LLHHQ") while 1: data = f.read(EVENT_SIZE) unpacked_data = struct.unpack('llHHQ',data) # print("Length:" + str(len(unpacked_data))) # print(unpacked_data) remote_data = unpacked_data[4] print(format(remote_data, '064b'))
It might be helpful to use a library like evdev as it will do much of the heavy lifting for you. Example of using this might be: from time import sleep from pydbus import SystemBus import evdev # For testing # python3 -m evdev.evtest class Controller: def __init__(self, adapter_int=0): adapter_path = '/org/bluez/hci{}'.format(adapter_int) self.dbus = SystemBus() self.adapter = self.dbus.get('org.bluez', adapter_path) # Use bluetoothctl to find out what the path is for your controller self.controller = self.dbus.get('org.bluez', '/org/bluez/hci0/dev_DC_0C_2D_20_DA_E8') print('Waiting for connection from DC:0C:2D:20:DA:E8') # self.controller.Discoverable = True while not self.controller.Connected: sleep(1) print('Connected') sleep(6) # https://python-evdev.readthedocs.io/en/latest/tutorial.html to get path of your controller self.device = evdev.InputDevice('/dev/input/event2') self.max_value = 0 self.min_value = 255 self.max_throttle = 1 self.min_throttle = -1 self.right_steering = 1 self.left_steering = -1 def map_throttle(self, value): input_range = self.max_value - self.min_value output_range = self.max_throttle - self.min_throttle input_percentage = (value - self.min_value) / input_range output_value = (output_range * input_percentage) + self.min_throttle return round(output_value, 2) def map_steering(self, value): input_range = self.max_value - self.min_value output_range = self.right_steering - self.left_steering input_percentage = (value - self.min_value) / input_range output_value = (output_range * input_percentage) + self.left_steering return round(output_value, 2) def get_events(self): for event in self.device.read_loop(): ly = None rx = None btn = None if event.type == evdev.ecodes.EV_ABS: if event.code == 1: # print('Left:', event.value) ly = self.map_throttle(event.value) if event.code == 3: # print('Right:', event.value) rx = self.map_steering(event.value) if event.type == evdev.ecodes.EV_KEY: if event.code == evdev.ecodes.BTN_SOUTH and event.value == 0: btn = 'BTN_SOUTH' elif event.code == evdev.ecodes.BTN_WEST and event.value == 0: btn = 'BTN_WEST' elif event.code == evdev.ecodes.BTN_NORTH and event.value == 0: btn = 'BTN_NORTH' elif event.code == evdev.ecodes.BTN_EAST and event.value == 0: btn = 'BTN_EAST' yield ly, rx, btn if __name__ == '__main__': ctrl = Controller() for speed, steer, action in ctrl.get_events(): print('Speed: {}, Steer: {}, Button: {}'.format(speed, steer, action)) If you wanted to go a little higher level, then a library like https://github.com/ApproxEng/approxeng.input is a popular one.
How to create EddyStone Beacon using BlueZ and Python?
I'm working on BLE(BlueTooth Low Energy) on an Embedded Linux board. We use BlueZ and Python. I need to create EddyStone Beacon. I found there is a way to create iBeacon: https://scribles.net/creating-ibeacon-using-bluez-example-code-on-raspberry-pi/. I tried it. It worked. But we need to create EddyStone Beacon. So I use the Beacon data format from here(https://ukbaz.github.io/howto/beacon_scan_cmd_line.html) to create the manufacturer data. But my code doesn't work. What is wrong with my code? Here is my code: def __init__(self, bus, index): eddystone_id = 0xAAFE beacon_type = [0x14, 0x16] # Length = 0x14, EddyStone type = 0x16 uuid = [0xAA, 0xFE] # EddyStone UUID = 0xAAFE frame_type = [0x10] # Frame Type = 0x10 power = [0x00] # Power = 0x00 prefix = [0x02] # URL scheme = 0x02 (http://) url = [0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x07] Advertisement.__init__(self, bus, index, 'peripheral') self.add_manufacturer_data(eddystone_id, beacon_type + uuid + frame_type + power + prefix + url) However, if I use this command, the EddyStone Beacon is created. I can see it shows EddyStone Beacon in nRF mobile app: sudo hcitool -i hci0 cmd 0x08 0x0008 1c 02 01 06 03 03 aa fe 14 16 aa fe 10 00 02 73 61 6d 70 6c 65 77 65 62 73 69 74 65 07 00 00 00 As you can see, the data I put in the add_manufacturer_data() function is the same as the data in the command. But why the Python code doesn't work?
iBeacon uses manufacturer_data while Eddystone beacons use service_data so I would expect your code to look more like this: def __init__(self, bus, index): Advertisement.__init__(self, bus, index, 'broadcast') self.add_service_uuid('FEAA') frame_type = [0x10] # Eddystone frame Type = 0x10 power = [0x00] # Beacon broadcast power = 0x00 prefix = [0x02] # URL scheme = 0x02 (http://) url = [0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x07] eddystone_data = frame_type + power + prefix + url self.add_service_data('FEAA', eddystone_data) As a side note, hcitool is one of the tools that has been deprecated by the BlueZ developers. The currently supported way to create the Eddystone beacon from the command line would be with bluetoothctl. The sequence of commands would be: bluetoothctl menu advertise uuids 0xFEAA service 0xFEAA 0x10 0x00 0x02 0x73 0x61 0x6D 0x70 0x6C 0x65 0x77 0x65 0x62 0x73 0x69 0x74 0x65 0x07 back advertise broadcast discoverable on I changed the advertisement type from peripheral to broadcast because typically people don't want beacons to be connectable, but it depends on your application.
OEM non printable characters in Python strings
I´m trying to port some Delphi code that sends data to a Universe database. In order to make the text legible by the DB we need to encode it in OEM. In Delphi is done this way: procedure TForm1.GenerarTablasNLS; var i: integer; begin for i := 0 to 255 do begin TablaUV_NLS[i] := AnsiChar(i); TablaNLS_UV[i] := AnsiChar(i); end; // Nulo final TablaUV_NLS[256] := #0; TablaNLS_UV[256] := #0; OemToCharA(#TablaUV_NLS[1], #TablaUV_NLS[1]); CharToOemA(#TablaNLS_UV[1], #TablaNLS_UV[1]); And then we translate our text simply like this function StringToUniverse(const Value: string): AnsiString; var p: PChar; q: PAnsiChar; begin SetLength(Result, Length(Value)); if Value = '' then Exit; p := Pointer(Value); q := Pointer(Result); while p^ <> #0 do begin q^ := TablaNLS_UV[Ord(AnsiChar(p^))]; Inc(p); Inc(q); end; end; I follow the same logic in Python using a dictionary that stores each character translation class StringUniverseDict(dict): def __missing__(self, key): return key TablaString2UV = StringUniverseDict() def rellenar_tablas_codificacion(): TablaString2UV['á'] = ' ' # chr(225) = chr(160) TablaString2UV['é'] = '‚' # chr(233) = chr(130) TablaString2UV['í'] = '¡' # chr(237) = chr(161) TablaString2UV['ó'] = '¢' # chr(243) = chr(162) TablaString2UV['ú'] = '£' # chr(250) = chr(163) TablaString2UV['ñ'] = '¤' # chr(241) = chr(164) TablaString2UV['ç'] = '‡' # chr(231) = chr(135) TablaString2UV['Á'] = 'µ' # chr(193) = chr(181) TablaString2UV['É'] = chr(144) # chr(201) = chr(144) TablaString2UV['Í'] = 'Ö' # chr(205) = chr(214) TablaString2UV['Ó'] = 'à' # chr(211) = chr(224) TablaString2UV['Ñ'] = '¥' # chr(209) = chr(165) TablaString2UV['Ç'] = '€' # chr(199) = chr(128) TablaString2UV['ü'] = chr(129) # chr(252) = chr(129) TablaString2UV[chr(129)] = '_' # chr(129) = chr(095) TablaString2UV[chr(141)] = '_' # chr(141) = chr(095) TablaString2UV['•'] = chr(007) # chr(149) = chr(007) TablaString2UV['Å'] = chr(143) # chr(197) = chr(143) TablaString2UV['Ø'] = chr(157) # chr(216) = chr(157) TablaString2UV['ì'] = chr(141) # chr(236) = chr(141) This works "fine" as long as I translate using printable characters. For example, the string "á é í ó ú ñ ç Á Í Ó Ú Ñ Ç" is translated, in Delphi, to the following bytes: 0xa0 0x20 0x82 0x20 0xa1 0x20 0xa2 0x20 0xa3 0x20 0xa4 0x20 0x87 0x20 0xb5 0x20 0xd6 0x20 0xe0 0x20 0xe9 0x20 0xa5 0x20 0x80 0xfe 0x73 0x64 0x73 (á translates to ' ', which is chr(160) or 0xA0 in hexa. é is '‚' or chr(130), 0x82 in hexa, í is '¡', char(161) or 0xA1 in hexa and so on) In Python, when I try to encode this to OEM I do the following: def convertir_string_a_universe(cadena_python): resultado = '' for letra in cadena_python: resultado += TablaString2UV[letra] return resultado And then, to get the bytes txt_registro = convertir_string_a_universe(txt_orig) datos = bytes(txt_registro, 'cp1252') With this I get the following bytes: b'\xa0 \x82 \xa1 \xa2 \xa3 \xa4 \x87 \xb5 \xd6 \xe0 \xe9 \xa5 \x80 \x9a' My problem is that this OEM encoding uses non-printable characters, like in 'É' = chr(144) (0x90 in hexa). If I try to call bytes(txt_registro, 'cp1252') with an array where I hava translated 'É' into chr(0x90) I get this error: caracteres_mal = 'Éü' txt_registro = convertir_string_a_universe(txt_orig) datos = bytes(txt_registro, 'cp1252') File "C:\Users\Hector\PyCharmProjects\pyuniverse\pyuniverse\UniverseRegister.py", line 138, in reconstruir_registro_universe datos = bytes(txt_registro, 'cp1252') File "C:\Users\Hector\AppData\Local\Programs\Python\Python36-32\lib\encodings\cp1252.py", line 12, in encode return codecs.charmap_encode(input,errors,encoding_table) UnicodeEncodeError: 'charmap' codec can't encode character '\x90' in position 0: character maps to <undefined> How can I do this OEM encoding without raising this UnicodeEncodeError?
This is because cp1252 does not know about chr(0x90). If you try with utf-8 instead, it will work. >>> chr(0x90).encode("utf8") b'\xc2\x90' I don't understand why you are trying to convert to cp1252 though: you have applied a custom conversion map and then, with bytes(txt_registro, 'cp1252'), you are converting your result again to cp1552. I think what you are looking for is something like: datos = bytes(txt_orig, 'uv') where uv is your cutom codec. So you would have to write an encoder and a decoder for it (which is basically what you have done already). Take a look at https://docs.python.org/3/library/codecs.html#codecs.register to register a new codec. The function you will register with it should return a CodecInfo object described upper in the documentation. import codecs def buscar_a_uv(codec): if codec == "uv": return codecs.CodecInfo( convertir_string_a_universe, convertir_universe_a_string, name="uv") else: return None codecs.register(buscar_a_uv) datos = bytes(txt_orig, 'uv') EDIT The encoder/decoder functions should return bytes, so you would need to update convertir_string_a_universe a bit.
nrf24l01 communication raspberry pi not able to connect
I am new to Stackoverflow. I have searched for answer, but didn't find anything. I have two Raspberry Pi 2B+, each with nRF24l01 connected. I found few libraries to make this connect, only one give any results, but not connections. This one: Github BLavery I write script to send and to recv: send.py: import RPi.GPIO as GPIO from lib_nrf24 import NRF24 import time import spidev GPIO.setmode(GPIO.BCM) pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]] radio = NRF24(GPIO, spidev.SpiDev()) radio.begin(0, 17) radio.setPayloadSize(32) radio.setChannel(0x60) radio.setDataRate(NRF24.BR_2MBPS) radio.setPALevel(NRF24.PA_MIN) radio.setAutoAck(True) radio.enableDynamicPayloads() radio.enableAckPayload() radio.openWritingPipe(pipes[1]) radio.printDetails() while True: message = list("Hello World") radio.write(message) print("We sent the message of {}".format(message)) # Check if it returned a ackPL if radio.isAckPayloadAvailable(): returnedPL = [] radio.read(returnedPL, radio.getDynamicPayloadSize()) print("Our returned payload was {}".format(returnedPL)) else: print("No payload received") time.sleep(1) recv.py: import RPi.GPIO as GPIO from lib_nrf24 import NRF24 import time import spidev GPIO.setmode(GPIO.BCM) pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]] radio = NRF24(GPIO, spidev.SpiDev()) radio.begin(0, 17) radio.setPayloadSize(32) radio.setChannel(0x60) radio.setDataRate(NRF24.BR_2MBPS) radio.setPAlevel(NRF24.PA_MIN) radio.setAutoAck(True) radio.enableDynamicPayloads() radio.enableAckPayload() radio.openReadingPipe(1, pipes[1]) radio.printDetails() radio.startListening() while True: ackPL = [1] while not radio.available (0): time.sleep(1/100) receivedMessage = [] radio.read(receivedMessage, radio.getDynamicPayloadSize()) print("Received: {}".format(receivedMessage)) print("Translating the receivedMessage into unicode characters...") string = "" for n in receivedMessage: # Decode into standard i=unicode set if (n >=32 and n <= 126): string += chr(n) print(string) radio.writeAckPayload(1, ackPL, len(ackPL)) print("Loaded payload reply of {}".format(ackPL)) Everything seems to be alright, below are code returned by both scripts: send: STATUS = 0x03 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=1 TX_FULL=1 RX_ADDR_P0-1 = 0xf8f8f8f8f8 0xf8f8f8f8f8 RX_ADDR_P2-5 = 0xf8 0xf9 0xf9 0xf9 TX_ADDR = 0xf8f8f8f8f8 RX_PW_P0-6 = 0x0c 0x00 0x00 0x00 0x00 0x00 EN_AA = 0x0f EN_RXADDR = 0x00 RF_CH = 0x1c RF_SETUP = 0x00 CONFIG = 0x03 DYNPD/FEATURE = 0x03 0x01 Data Rate = 1MBPS Model = nRF24L01 CRC Length = Disabled PA Power = PA_MIN We sent the message of ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'] No payload received recv.py: STATUS = 0x03 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=1 TX_FULL=1 RX_ADDR_P0-1 = 0xf8f8f8f8f8 0xf8f8f8f8f8 RX_ADDR_P2-5 = 0xf8 0xf9 0xf9 0xf9 TX_ADDR = 0xf8f8f8f8f8 RX_PW_P0-6 = 0x0c 0x0c 0x00 0x00 0x00 0x00 EN_AA = 0x0f EN_RXADDR = 0x00 RF_CH = 0x1c RF_SETUP = 0x00 CONFIG = 0x03 DYNPD/FEATURE = 0x03 0x01 Data Rate = 1MBPS Model = nRF24L01 CRC Length = Disabled PA Power = PA_MIN Received: [] Translating the receivedMessage into unicode characters... Loaded payload reply of [1] I don't really understand why it won't connect one to other, Both have the same wiring: nRF24L01-Raspberry Pi (Pin#) GND - GND (6) VCC - 3,3V (1) CE - GPIO17 (11) CSN - GPIO08(24) SCK - GPIO11 (23) MOSI - GPIO10 (19) MISO - GPIO25 (22) IRQ - unconnected I need to send information from one RPi to second to control engine via PWM. Can i ask for help