Can not read more than 32 blocks in a single READ MULTIPLE BLOCKS command from M24LR - tags

I am trying to read multiple blocks (all of them in a single READ MULTIPLE BLOCKS command) from a M24LR chip through NFC-V.
let writeData = new Uint8Array(5);
writeData[0] = 0x0A; // Flags
writeData[1] = 0x23; // Read multiple block
writeData[2] = 0x00; // Address of starting block (first 8bit)
writeData[3] = 0x00; // Address (second 8bit)
writeData[4] = 0x1F; // Numbers of block (0x20 is not working)
nfc.transceive(writeData.buffer)
.then(response => {
console.log('response: ' + response);
})
.catch(error => {
console.log('error transceive: ' + JSON.stringify(error));
});
If I am asking for 32 blocks it works well, if I ask for 33 blocks, the command fails with an error.
Is it something that I am doing wrong? Does the READ MULTIPLE BLOCKS command have a limit?

See the datasheet (M24LR64-R: Dynamic NFC/RFID tag IC with 64-Kbit EEPROM
with I²C bus and ISO 15693 RF interface, DocID15170 Rev 16, section 26.5; the same also applies to M24LR64E-R, M24LR16E-R, and M24LR04E-R):
The maximum number of blocks is fixed at 32 assuming that they are all located in the same sector. If the number of blocks overlaps sectors, the M24LR64-R returns an error code.
Thus, the READ MULTIPLE BLOCKS command for these chips is limited to 32 blocks.

Related

MPU-6050: Correctly reading data from the FIFO register

Introduction
The MPU-6050 is a popular module that contains a temperature sensor, accelerometer, and gyroscope. A user may read the sensor information over I2C or SPI. Two documents are publicly available for reading data out of the IC registers. These are:
The MPU-6000 and MPU-6050 Register Map and Descriptions Document
The MPU-6000 and MPU-6050 Product Specification
Context
Reading individual registers of the IMU over I2C skews samples across time because of bus communication latency. Consequently, a sequential read of the X, Y, and Z axis registers of a sensor are not synchronized. To address this, the device provides a 1024-byte internal FIFO queue. Data configured to be pushed to the queue are pushed together at the sample rate. Hence reading the FIFO yields synchronized data.
See (2), section 7.17:
The MPU-60X0 contains a 1024-byte FIFO register that is accessible via the Serial Interface. The FIFO configuration register determines which data is written into the FIFO. Possible choices include gyro data, accelerometer data, temperature readings, auxiliary sensor readings, and FSYNC input. A FIFO counter keeps track of how many bytes of valid data are contained in the FIFO. The FIFO register supports burst reads. The interrupt function may be used to determine when new data is available
Problem
The datasheets specify that in order to read from the FIFO, you must perform the following:
Enable the FIFO (bit 6, register 0x6A, Document (1), Section 4.29)
Configure the FIFO with what sensor information to push (register 0x23, Document (1), Section 4.7). I enable XG_FIFO_EN, YG_FIFO_EN, ZG_FIFO_EN, and ACCEL_FIFO_EN by setting bits 6, 5, 4, and 3 respectively.
If you have performed these steps, then it claims (Document (1), Section 4.33) that:
Data is written to the FIFO in order of register number (from lowest to highest). If all the FIFO enable flags (see below) are enabled and all External Sensor Data registers (Registers 73 to 96) are associated with a Slave device, the contents of registers 59 through 96 will be written in order at the Sample Rate.
The contents of the sensor data registers (Registers 59 to 96) are written into the FIFO buffer when their corresponding FIFO enable flags are set to 1 in FIFO_EN (Register 35).
However, I find that this does not hold true. Given the flags I have enabled in the configuration register, I expect the following sequence to come from the FIFO:
* ----------------------------------------------------------- *
* BYTE # | VALUE | Register (dec) *
* ----------------------------------------------------------- *
* 0 | ACCEL_XOUT[15:8] | 59 *
* 1 | ACCEL_XOUT[7:0] | 60 *
* ----------------------------------------------------------- *
* 2 | ACCEL_YOUT[15:8] | 61 *
* 3 | ACCEL_YOUT[7:0] | 62 *
* ----------------------------------------------------------- *
* 4 | ACCEL_ZOUT[15:8] | 63 *
* 5 | ACCEL_ZOUT[7:0] | 64 *
* ----------------------------------------------------------- *
* 6 | GYRO_XOUT[15:8] | 67 *
* 7 | GYRO_XOUT[7:0] | 68 *
* ----------------------------------------------------------- *
* 8 | GYRO_YOUT[15:8] | 69 *
* 9 | GYRO_YOUT[7:0] | 70 *
* ----------------------------------------------------------- *
* 10 | GYRO_ZOUT[15:8] | 71 *
* 11 | GYRO_ZOUT[7:0] | 72 *
* ----------------------------------------------------------- *
Yet reading 12 bytes from the FIFO does not correspond with the same data when reading individual registers. It also doesn't seem to make much sense when I accelerate the IMU, or rotate it. I therefore am not sure how exactly to read the FIFO. This is the problem I face
Q&A
Are you sure you are correctly writing to registers?: Yes, I am able to set various configurations such as the sampling rate, interrupts, etc. I am confident I am correctly able to read from the FIFO
Are you sure there is anything in the FIFO to read?: Yes, I have enabled FIFO overflow interrupts. I currently wait for an interrupt, and then read from the FIFO register.
Are you checking the FIFO length register before reading? Yes, it contains 1024 bytes (maximum capacity) when the FIFO-overflow interrupt occurs.
Haven't other people done this before?: Nobody has a concrete explanation on how to read the FIFO (e.g: this similar question on another forum that gets an RTFM). A majority of searchable questions related to reading the FIFO are (a) unanswered, (b) told to use generic XYZ Arduino library (I cannot use it), (c) told to read the data sheet (I have).
Okay, so I've figured out the problem. The issue was that I was failing to reset the FIFO prior to reading it - otherwise everything was more or less okay. I'll show you exactly how I setup the IMU now.
Source Files
I created a source file to read the MPU-6050 registers. I've attached them here for reference in the following explanation:
Header File
Source File
Setup
In order to setup the IMU, I performed the following steps within a FreeRTOS task (prior to the main loop).
// Performs the I2C configuration for the MPU-6050 IMU. Saves handle
static mpu6050_err_t init_imu (mpu6050_i2c_cfg_t **handle) {
mpu6050_err_t err = MPU6050_ERR_OK;
uint8_t flags;
// Configure the MPU-6050 I2C data structure
static mpu6050_i2c_cfg_t i2c_cfg = (mpu6050_i2c_cfg_t) {
.sda_pin = I2C_SDA_PIN,
.scl_pin = I2C_SCL_PIN,
.slave_addr = I2C_IMU_SLAVE_ADDR,
.i2c_port = I2C_IMU_PORT_NUM,
.clk_speed = I2C_APB_CLK_FREQ / 200, // Requires 400kHz
.sda_pullup_en = IMU_ENABLE_INTERNAL_PULLUPS,
.scl_pullup_en = IMU_ENABLE_INTERNAL_PULLUPS
};
// Initialize I2C
if ((err = mpu6050_init(&i2c_cfg)) != MPU6050_ERR_OK) {
return err;
}
// Configure Power Management 1 to wake the IMU (don't reset)
flags = 0x0;
if ((err = mpu6050_configure_power(&i2c_cfg, flags)) != MPU6050_ERR_OK) {
return err;
}
// Configure accelerometer sensitivity
flags = A_CFG_8G;
if ((err = mpu6050_configure_accelerometer(&i2c_cfg, flags))
!= MPU6050_ERR_OK) {
return err;
}
// Configure gyro sensitivity
flags = G_CFG_500;
if ((err = mpu6050_configure_gyroscope(&i2c_cfg, flags))
!= MPU6050_ERR_OK) {
return err;
}
// Configure the Digital-Low-Pass-Filter
flags = DLFP_CFG_FILTER_2;
if ((err = mpu6050_configure_dlfp(&i2c_cfg, flags))
!= MPU6050_ERR_OK) {
return err;
}
// Set the sampling rate to ~50Hz
flags = 19;
if ((err = mpu6050_set_sample_rate_divider(&i2c_cfg, flags))
!= MPU6050_ERR_OK) {
return err;
}
// Configure interrupt behavior
flags = 0x0;
if ((err = mpu6050_configure_interrupt(&i2c_cfg, flags))
!= MPU6050_ERR_OK) {
return err;
}
// Enable interrupts after every sensor refresh
flags = INTR_EN_DATA_RDY;
if ((err = mpu6050_enable_interrupt(&i2c_cfg, flags))
!= MPU6050_ERR_OK) {
return err;
}
// Enable + Reset the FIFO
flags = USER_CTRL_FIFO_EN | USER_CTRL_FIFO_RST;
if ((err = mpu6050_enable_fifo(&i2c_cfg, flags))
!= MPU6050_ERR_OK) {
return err;
}
// Configure the data pushed to the FIFO
flags = FIFO_CFG_GX | FIFO_CFG_GY | FIFO_CFG_GZ | FIFO_CFG_AXYZ;
if ((err = mpu6050_configure_fifo(&i2c_cfg, flags)) != MPU6050_ERR_OK) {
return err;
}
// Save the configuration
*handle = &i2c_cfg;
return err;
}
If you configure as I described, then it should work. Of course, you may be using a different library or wrapper for the device, but the functions you can enable should be similarly accessible. Once I had done all this, I was able to read the FIFO at each interrupt as follows:
// Read the FIFO length
if (mpu6050_get_fifo_length(i2c_cfg_p, &len) != MPU6050_ERR_OK) {
ERR("FIFO length fetch error!");
break;
}
// Check if enough samples are ready - else continue (check later)
if (len < FIFO_BURST_LEN) {
continue;
}
// Fetch data from FIFO
if (mpu6050_receive_fifo(i2c_cfg_p, &data) != MPU6050_ERR_OK) {
ERR("FIFO data fetch error!");
break;
}

I2C returning Busy or Error on memory reading

I started the following code to handle a Bosch BME280 sensor with a Nucleo-F446ZE and a Nucleo-F411RE boards.
with STM32.Device; use STM32.Device;
with STM32.GPIO; use STM32.GPIO;
with STM32; use STM32;
with STM32.I2C;
with HAL.I2C; use HAL.I2C;
use HAL;
procedure Simple_I2C_Demo is
-- I2C Bus selected
Selected_I2C_Port : constant access STM32.I2C.I2C_Port := I2C_1'Access;
Selected_I2C_Port_AF : constant GPIO_Alternate_Function := GPIO_AF_I2C1_4;
Selected_I2C_Clock_Pin : GPIO_Point renames PB8;
Selected_I2C_Data_Pin : GPIO_Point renames PB9;
Port : constant HAL.I2C.Any_I2C_Port := Selected_I2C_Port;
-- Shift one because of 7-bit addressing
I2C_Address : constant HAL.I2C.I2C_Address := 16#76# * 2;
procedure SetupHardware is
GPIO_Conf_AF : GPIO_Port_Configuration (Mode_AF);
Selected_Clock_Speed : constant := 10_000;
begin
Enable_Clock (Selected_I2C_Clock_Pin);
Enable_Clock (Selected_I2C_Data_Pin);
Enable_Clock (Selected_I2C_Port.all);
STM32.Device.Reset (Selected_I2C_Port.all);
Configure_Alternate_Function (Selected_I2C_Clock_Pin, Selected_I2C_Port_AF);
Configure_Alternate_Function (Selected_I2C_Data_Pin, Selected_I2C_Port_AF);
GPIO_Conf_AF.AF_Speed := Speed_100MHz;
GPIO_Conf_AF.AF_Output_Type := Open_Drain;
GPIO_Conf_AF.Resistors := Pull_Up;
Configure_IO (Selected_I2C_Clock_Pin, GPIO_Conf_AF);
Configure_IO (Selected_I2C_Data_Pin, GPIO_Conf_AF);
STM32.I2C.Configure
(Selected_I2C_Port.all,
(Clock_Speed => Selected_Clock_Speed,
Addressing_Mode => STM32.I2C.Addressing_Mode_7bit,
Own_Address => 16#00#, others => <>));
STM32.I2C.Set_State (Selected_I2C_Port.all, Enabled => True);
end SetupHardware;
ID : HAL.I2C.I2C_Data (1 .. 1);
Status : HAL.I2C.I2C_Status;
begin
SetupHardware;
HAL.I2C.Mem_Read (This => Port.all,
Addr => I2C_Address,
Mem_Addr => 16#D0#,
Mem_Addr_Size => HAL.I2C.Memory_Size_8b,
Data => ID,
Status => Status,
Timeout => 15000);
if Status /= Ok then
raise Program_Error with "I2C read error:" & Status'Img;
end if;
end Simple_I2C_Demo;
In this simple example, I always get an error status at the end of reading. In the context of a more complete code, I always get a Busy status after waiting 15secs.
I really don't see what is going on as my code is largely inspired from the code I found on Github for a I2C sensor.
Maybe I forgot a specific code for I2C init but as I'm not an expert, I prefer to ask to experts :)
Finally found what was wrong. After testing with C using STM HAL and investigating the Ada configuration code, I found that a line was missing:
GPIO_Conf_AF.AF_Speed := Speed_100MHz;
GPIO_Conf_AF.AF_Output_Type := Open_Drain;
GPIO_Conf_AF.Resistors := Pull_Up;
-- Missing configuration part of the record
GPIO_Conf_AF.AF := Selected_I2C_Port_AF;
-- That should be present even though there was a call to configure
-- each pin few lines above
Configure_IO (Selected_I2C_Clock_Pin, GPIO_Conf_AF);
Configure_IO (Selected_I2C_Data_Pin, GPIO_Conf_AF);
Using Configure_IO after Configure_Alternate_Function crushes the configuration and, as there was a part of the record which was left uninitialized, the GPIO were incorrectly configured.
To be more precise, after looking at the code inside the GPIO handling, Configure_IO calls Configure_Alternate_Function using the AF part of the GPIO_Port_Configuration record. In my case, it was resetting it.
With the missing line, the code now runs correctly with Mem_Read and Master_Transmit/Master_Receive.
A big thanks to ralf htp for advising me to dive into the generated C code.
No, between HAL_I2C_Mem_Read and the HAL_I2C_Master_Transmit, wait, HAL_I2C_Master_Receive procedure is only a nuance cf How do I use the STM32CUBEF4 HAL library to read out the sensor data with i2c? . If you know what size of data you want to receive you can use the HAL_I2C_Master_Transmit, wait, HAL_I2C_Master_Receive procedure.
A C++ HAL I2C example is in https://letanphuc.net/2017/05/stm32f0-i2c-tutorial-7/
//Trigger Temperature measurement
buffer[0]=0x00;
HAL_I2C_Master_Transmit(&hi2c1,0x40<<1,buffer,1,100);
HAL_Delay(20);
HAL_I2C_Master_Receive(&hi2c1,0x40<<1,buffer,2,100);
//buffer[0] : MSB data
//buffer[1] : LSB data
rawT = buffer[0]<<8 | buffer[1]; //combine 2 8-bit into 1 16bit
Temperature = ((float)rawT/65536)*165.0 -40.0;
//Trigger Humidity measurement buffer[0]=0x01;
HAL_I2C_Master_Transmit(&hi2c1,0x40<<1,buffer,1,100);
HAL_Delay(20);
HAL_I2C_Master_Receive(&hi2c1,0x40<<1,buffer,2,100);
//buffer[0] : MSB data
//buffer[1] : LSB data
rawH = buffer[0]<<8 | buffer[1]; //combine 2 8-bit into 1 16bit
Humidity = ((float)rawH/65536)*100.0; HAL_Delay(100); }
Note that it uses HAL_I2C_Master_Transmit, waits 20 ms until the slave puts the data on the bus and then receives it with HAL_I2C_Master_Receive. This code is working, i tested it myself.
Possibly the problem is that the BME280 supports single byte reads and multi-byte reads (until it sends a NOACK and stop). HAL_I2C_Mem_Read waits for the ACK or stop but for some reasons it does not get it what causes the Busy and then Timeout behavior, cf page 33 of the datasheet http://www.embeddedadventures.com/datasheets/BME280.pdf for the multibyte read. You specified timeout to 15 sec and you get the timeout after 15 secs. So it appears that the BME280 simply does not stop sending or it sends nothing including not a NOACK and Stop condition ...
HAL_I2C_Mem_Read sometimes causes problems, this depends on the slave https://community.arm.com/developer/ip-products/system/f/embedded-forum/7989/trouble-getting-values-with-i2c-using-hal_library
By the way with the
HAL.I2C.Mem_Read (This => Port.all,
Addr => I2C_Address,
Mem_Addr => 16#D0#,
Mem_Addr_Size => HAL.I2C.Memory_Size_8b,
Data => ID,
Status => Status,
Timeout => 15000);
you try to read 1 byte the chip identification number from register D0 cf http://www.embeddedadventures.com/datasheets/BME280.pdf page 26

Would my solution work for 8-bit bus addressing using BSRR and BRR?

I have set an 8-bit bus on (PD0:PD7) on the stm32 MCU to send addresses to another chip (0:255). I am interested if a function like below would work for fast change in addresses. I could not find an example directly showing register to be equal to integer so I want to confirm it would work. I need a function to which I will give an integer value for the address (0:255) and it will set the 8 pins of the bus with this value:
void chipbus(uint16_t bus8){
GPIOD->regs->BSRR = bus8; // set all the '1' in bus8 to high
GPIOD->regs->BRR = 255-bus8; // 255-bus8 inverts the 8 bits
// BRR to set the new '1' to low
}
If this solution works, I am curious also if I change the bus to ports PD5:PD12 would my function work as:
void chipbus(uint16_t bus8){
GPIOD->regs->BSRR = bus8*32; // set all '1' in bus8 to high
// multiply by 32 to shift 5 bits/pins
GPIOD->regs->BRR = (255-bus8)*32; // 255-bus8 inverts the 8 bits
// BRR to set the new '1' to low
}
Thank you!
Yes, both should work. However, a more recognisable but equivalent formulation would be:
void chipbus(uint16_t bus8) {
GPIOD->regs->BSRR = bus8; // set all the '1' in bus8 to high
GPIOD->regs->BRR = (~bus8) & 0xFF; // inverts the 8 bits // BRR to set the new '1' to low
}
void chipbus(uint16_t bus8) {
GPIOD->regs->BSRR = bus8<<5; // set all '1' in bus8 to high, shift 5 bits
GPIOD->regs->BRR = ((~bus8)&0xFF)<<5; // inverts the 8 bits
}
But, there is an even faster way. BSRR is a 32bit register than can both set and reset. You can combine the two write accesses into one:
void chipbus(uint16_t bus8) {
GPIOD->regs->BSRR =
(bus8<<5) | (((~bus8) & 0xFF) << (16+5));
}
Happy bit-fiddling!
Yes, it'd definitely work. However, as others have noted, it's advisable to set the outputs in a single operation.
Taking advantage of the full 32 bit BSRR register, it can be done without inverting the data bits:
GPIOD->regs->BSRR = bus8 | (0xFF << 16);
or
GPIOD->regs->BSRR = (bus8 << 5) | (0xFF << (16 + 5));
because BSRR has the functionality to set some bits and reset some others in a single write operation, and when both the set and reset bits for a particular pin is set, the output becomes 1.
I wouldn't recommend using this approach. Writing to BSRR and BRR as two separate steps means that the bus will transition through an unintended state where some bits are still set from the previous value.
Instead, consider writing directly to the GPIO output data register (ODR). If you need to preserve the original value of the upper bits in the port, you can do that on the CPU side:
GPIOD->regs->ODR = (GPIOD->regs->ODR & 0xff00) | (bus8 & 0x00ff);

STM32 SPI data is sent the reverse way

I've been experimenting with writing to an external EEPROM using SPI and I've had mixed success. The data does get shifted out but in an opposite manner. The EEPROM requires a start bit and then an opcode which is essentially a 2-bit code for read, write and erase. Essentially the start bit and the opcode are combined into one byte. I'm creating a 32-bit unsigned int and then bit-shifting the values into it. When I transmit these I see that the actual data is being seen first and then the SB+opcode and then the memory address. How do I reverse this to see the opcode first then the memory address and then the actual data. As seen in the image below, the data is BCDE, SB+opcode is 07 and the memory address is 3F. The correct sequence should be 07, 3F and then BCDE (I think!).
Here is the code:
uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint32_t write_package = (ERASE << 24 | mem_addr << 16 | data);
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_SPI_Transmit(&hspi1, &write_package, 2, HAL_MAX_DELAY);
HAL_Delay(10);
}
/* USER CODE END 3 */
It looks like as your SPI interface is set up to process 16 bit halfwords at a time. Therefore it would make sense to break up the data to be sent into 16 bit halfwords too. That would take care of the ordering.
uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint16_t write_package[2] = {
(ERASE << 8) | mem_addr,
data
};
HAL_SPI_Transmit(&hspi1, (uint8_t *)write_package, 2, HAL_MAX_DELAY);
EDIT
Added an explicit cast. As noted in the comments, without the explicit cast it wouldn't compile as C++ code, and cause some warnings as C code.
You're packing your information into a 32 bit integer, on line 3 of your code you have the decision about which bits of data are placed where in the word. To change the order you can replace the line with:
uint32_t write_package = ((data << 16) | (mem_addr << 8) | (ERASE));
That is shifting data 16 bits left into the most significant 16 bits of the word, shifting mem_addr up by 8 bits and or-ing it in, and then adding ERASE in the least significant bits.
Your problem is the Endianness.
By default the STM32 uses little edian so the lowest byte of the uint32_t is stored at the first adrress.
If I'm right this is the declaration if the transmit function you are using:
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
It requires a pointer to uint8_t as data (and not a uint32_t) so you should get at least a warning if you compile your code.
If you want to write code that is independent of the used endianess, you should store your data into an array instead of one "big" variable.
uint8_t write_package[4];
write_package[0] = ERASE;
write_package[1] = mem_addr;
write_package[2] = (data >> 8) & 0xFF;
write_package[3] = (data & 0xFF);

How do I get the per-spec output of a LV-MaxSonar LV-EZ0 rangefinder with Android Things?

I'm using this sensor with a Raspberry Pi B 3 and Android Things 1.0
I have it connected as per these instructions
The spec for its output suggests I should receive "an ASCII capital “R”, followed by three ASCII character digits representing the range in inches up to a maximum of 255, followed by a carriage return (ASCII 13)"
I have connected to the device and configured it as follows (connection parameters map to the "Serial, 0 to Vcc, 9600 Baud, 81N" in that spec, I think):
PeripheralManager manager = PeripheralManager.getInstance();
mDevice = manager.openUartDevice(name);
mDevice.setBaudrate(9600);
mDevice.setDataSize(8);
mDevice.setParity(UartDevice.PARITY_NONE);
mDevice.setStopBits(1);
mDevice.registerUartDeviceCallback(mUartCallback);
I am reading from its buffer in that callback as follows:
public void readUartBuffer(UartDevice uart) throws IOException {
// "The output is an ASCII capital “R”, followed by three ASCII character digits
// representing the range in inches up to a maximum of 255, followed by a carriage return
// (ASCII 13)
ByteArrayOutputStream bout = new ByteArrayOutputStream();
final int maxCount = 1024;
byte[] buffer = new byte[maxCount];
int total = 0;
int cycles = 0;
int count;
bout.write(23);
while ((count = uart.read(buffer, buffer.length)) > 0) {
bout.write(buffer, 0, count);
total += count;
cycles++;
}
bout.write(0);
byte[] buf = bout.toByteArray();
String bufStr = Arrays.toString(buf);
Log.d(TAG, "Got " + total + " in " + cycles + ":" + buf.length +"=>" + bufStr);
}
private UartDeviceCallback mUartCallback = new UartDeviceCallback() {
#Override
public boolean onUartDeviceDataAvailable(UartDevice uart) {
// Read available data from the UART device
try {
readUartBuffer(uart);
} catch (IOException e) {
Log.w(TAG, "Unable to access UART device", e);
}
// Continue listening for more interrupts
return true;
}
When I connect the sensor and use this code I get readings back of the form:
05-10 03:59:59.198 1572-1572/org.tomhume.blah D/LVEZ0: Got 7 in 1:9=>[23, 43, 0, 6, -77, -84, 15, 0, 0]
05-10 03:59:59.248 1572-1572/org.tomhume.blah D/LVEZ0: Got 7 in 1:9=>[23, 43, 0, 6, 102, 101, 121, 0, 0]
05-10 03:59:59.298 1572-1572/org.tomhume.blah D/LVEZ0: Got 7 in 1:9=>[23, 43, 0, 6, 102, 99, 121, 0, 0]
The initial 23 and the final 0 on each line are values I have added. Instead of an expected R\d\d\d\13 I expect between them, I'm getting 7 signed bytes. The variance in some of these byte values appears when I move my hand towards and away from the sensor - i.e. the values I'm getting back vary in a way I might expect, even though the output is completely wrong in form and size.
Any ideas what I'm doing wrong here? I suspect it's something extremely obvious, but I'm stumped. Examining the binary values themselves it doesn't look like bits are shifted around by e.g. a mistake in protocol configuration.
I can't test it on a hardware now, but seems algorithm for reading serial data from a LV-MaxSonar LV-EZ0 rangefinder should be slightly different: you should find "an ASCII capital “R” in UART sequence buffer (because LV-EZ0 starts sending data after power on and not synchronized with Raspberry Pi board and first received byte may be not “R” and quantity of received bytes can be less or more then 5 bytes of LV-MaxSonar response^ in one buffer can be several (or part)of LV-MaxSonar responses) and THAN try to parse 3 character digits representing the range in inches and ending CR symbol (if there is no all 3 bytes for digits and CR symbol - than start to find capital “R” again because LV-MaxSonar response is broken (it also can be)). For example take a look at GPS contrib driver especially at processBuffer() of NmeaGpsModule.java and processMessageFrame() of NmeaParser.java - the difference is in your have only one "sentence" and its start is not "GPRMC", but only "R" symbol.
And other important thing: seems there no capital “R” (ASCII 82) in your response buffers - may be some issues in LV-MaxSonar LV-EZ0 connection. Your schematics should be exactly like top right picture on page 6 of datasheet: Independent Sensor Operation: Serial Output Sensor Operation. Also try, for example, to connect LV-MaxSonar LV-EZ0 to USB<->UART (with power output) cable (e.g. like that) and test it in terminal with your PC.