I am wondering if there is such interface for LDC1614 EVM in the same way as it implemented in the LDC1000 EVM.
See the following post from FAQ: http://e2e.ti.com/support/sensor/inductive-sensing/f/938/t/295036#Q27
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I am wondering if there is such interface for LDC1614 EVM in the same way as it implemented in the LDC1000 EVM.
See the following post from FAQ: http://e2e.ti.com/support/sensor/inductive-sensing/f/938/t/295036#Q27
Hello John,
Unfortunately we currently dont have a plan to release it in near feauture.
Best Regards,
Natallia Holubeva
John,
Is your primary interest in the protocol definition for the MSP interface, or the actual firmware? If we provided the protocol definition, can you work with that?
Jim
Hello John,
Please see below:
LDC13xx/16xx communication is accomplished via driver-simulated COM protocols. Settings are:
Baud rate 115200
No termination CHAR
Data bits 8
Parity None
Stop bit 1
Flow control: None
Write register command
Write register command is used to set desired register settings. It is formed as follow:
4C 15 01 00 04 2A XX YY YY ZZ
Where
4C 15 01 00 04 2A = Write register command header.
XX is the register address to be written, expressed as HEX. For example, if register 12 is x0C, so XX = 0C
YY YY is the 2 bytes of data to be written, in HEX, MSB 1st.
ZZ is CRC-8 check for the command string, which is explained below.
Each HEX value represents corresponding ASCII character, which is written to COM port.
For example, if we need to write to register 11 (x1B) a value of x820D, the command is
4C 15 01 00 04 2A 1B 82 0D A3. In ASCII it appears as
After writing a register it is required to read back 32 bytes – MCU response to a command. Convert ASCII string into array of 8-bit numbers. It consists of the command sent + 21 bytes of 00 + CRC value. In the above example, correct response is 4C 15 01 00 04 2A 1B 82 0D A3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00A3.
4th byte (indicated in red above) is an error field. If this byte is 00, there is no error.
Read register command
Read register command is used to check LDC register settings. Read process consists of 2 steps:
1) Set register command, which is required to indicate which register is to be read. The command format is: 4C 15 01 00 02 2A XX ZZ, where XX is the register address to be read, and ZZ is CRC-8 check for the command string. For example, to read back register 1B the command is 4C 15 01 00 02 2A 1B 10. After sending this command it is required to read 32 bytes. The 4th byte will indicate an error, if any.
2) Read register command, in the format 4C 14 01 00 02 2A 02 ZZ, where ZZ is CRC-8 check. After sending this command it is required to read 32 bytes, as noted above. The 4th byte will indicate an error, if any. 7th and 8th bytes are MSB and LSB bytes of the register value. For example, if we read register x1B value, the response is 4C 14 01 00 03 2A 82 0D C6 A3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C6
Start streaming command
To optimize data throughput a special command is implemented, which will continuously output data from LDC devices to COM port.
To start streaming, send 4C 05 01 00 06 01 29 04 04 30 2A C1. After sending this command it is required to read 32 bytes. 4th byte will indicate an error, if any.
After the stream is initialized, read 32 bytes at a time. An example read:
4C30 0100 092A 0151 42CB 0150 5FFF 1C00 0000 0000 0000 0000 0000 0000 0000 001C
Bytes 7-10 are the Ch0 data (marked in green), MSB 1st, bytes 11-14 are Ch1 data (marked in blue), MSB 1st. In this example, Ch0 data is x015142CB (22,102,731 in decimal), Ch1 is 01505FFF (22,044,671). Further conversion of the raw data to the frequency of oscillation is described in the LDC161x/131x datasheet
Stop streaming command
To stop the streaming, send the command 4C 06 01 00 01 01 D2. After sending this command it is required to read 32 bytes. 4th byte will indicate an error, if any.
CRC-8 check
CRC check is well described in http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
Please refer to the link for more detailed information.
The LDC 13xx/16xx EVMs use CRC-8 with polynomial coefficient indices of 8, 2, 1, and 0.
Outlined below is one of the possible implementations:
Convert each byte in the command to an array of Booleans (T = 1, F = 0), MSB being index 1. For example, xA7 becomes an array (T,F,T,F,F,T,T,T).
Concatenate the array of bytes, 1st byte being indices 1-8, 2nd – bytes 9-16 etc. For example, xA70F becomes (T,F,T,F,F,T,T,T,F,F,F,F,T,T,T,T). Record the array size N.
Form C = (T,F,F,F,F,F,T,T,T) – CRC array. Note that the indices of the non-zero coefficients are 8, 2, 1, 0.
Append to the Boolean command array an array of 8 False (F,F,F,F,F,F,F,F) at the end. Denote this array A.
For loop for i=1 to N
IF A[i] = True then
Get B = array A subset starting at index i, length 9
B’ = B XOR C
Replace B in A with B’
End IF
End loop
Take the last 8 Booleans of the updated A, convert it to byte (MSB 1st). For example, if last 8 elements in A are (T,F,T,T,F,F,T,T), it converts to xB3
This is desired CRC-8 check value (ZZ value in the document)
Best Regards,
Natallia Holubeva
Hi Natallia,
Thanks for so quick response. I have started to work on my Python script.
As soon as it will be ready I will release it to public.
Thanks,
Jogn
Hi Natallia,
I just wrote a few lines in python just to verify that I have response to write reg command.
But the result is absolutely unexpected. Please see below the python code:
import sys import collections import serial import time import struct import msvcrt serial_port = serial.Serial(port='COM13', baudrate=115200, bytesize=8, stopbits=1, parity=serial.PARITY_NONE) print("aaaa") serial_port.write('4C150100042A1B820DA3') s = serial_port.read(11) print("bbbb") print("Read:", s )
The output of this screen just 11 bytes of text "no stream\r\n"
Can you please advise ?
Thanks,
John
Hi All,
Please see below short Pyhon script to read write LDC1614 registers.
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import collections import serial import time import struct import msvcrt from array import * import binascii ############################################################################################# # LDC1000 addressing space LDC1614_DATA_MSB_CH0 = '00' LDC1614_DATA_LSB_CH0 = '01' LDC1614_DATA_MSB_CH1 = '02' LDC1614_DATA_LSB_CH1 = '03' LDC1614_DATA_MSB_CH2 = '04' LDC1614_DATA_LSB_CH2 = '05' LDC1614_DATA_MSB_CH3 = '06' LDC1614_DATA_LSB_CH3 = '07' LDC1614_RCOUNT_CH0 = '08' LDC1614_RCOUNT_CH1 = '09' LDC1614_RCOUNT_CH2 = '0A' LDC1614_RCOUNT_CH3 = '0B' LDC1614_OFFSET_CH0 = '0C' LDC1614_OFFSET_CH1 = '0D' LDC1614_OFFSET_CH2 = '0E' LDC1614_OFFSET_CH3 = '0F' LDC1614_SETTLECOUNT_CH0 = '10' LDC1614_SETTLECOUNT_CH1 = '11' LDC1614_SETTLECOUNT_CH2 = '12' LDC1614_SETTLECOUNT_CH3 = '13' LDC1614_CLOCK_DIVIDERS_CH0 = '14' LDC1614_CLOCK_DIVIDERS_CH1 = '15' LDC1614_CLOCK_DIVIDERS_CH2 = '16' LDC1614_CLOCK_DIVIDERS_CH3 = '17' LDC1614_STATUS = '18' LDC1614_ERROR_CONFIG = '19' LDC1614_CONFIG = '1A' LDC1614_MUX_CONFIG = '1B' LDC1614_RESET_DEV = '1C' LDC1614_DRIVE_CURRENT_CH0 = '1E' LDC1614_DRIVE_CURRENT_CH1 = '1F' LDC1614_DRIVE_CURRENT_CH2 = '20' LDC1614_DRIVE_CURRENT_CH3 = '21' LDC1614_MANUFACTURER_ID = '7E' LDC1614_DEVICE_ID = '7F' DEBUG_PRINT_TX_DATA = 0 DEBUG_PRINT_RX_DATA = 0 DEBUG_PRINT_READ_DATA = 0 class crc8: def __init__(self): self.crcTable = (0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3) def crc(self, msg): runningCRC = 0 for c in msg: c = ord(str(c)) runningCRC = self.crcByte(runningCRC, c) return runningCRC def crcByte(self, oldCrc, byte): res = self.crcTable[oldCrc & 0xFF ^ byte & 0xFF]; return res def write_reg(serial_port, addr, data): crc = crc8() serial_string = '4C150100042A'+ addr + data serial_string = serial_string.decode('hex') crc_byte = chr(crc.crc(serial_string)) serial_port.write(serial_string+crc_byte) s = serial_port.read(32) if DEBUG_PRINT_RX_DATA: print("Read:%s" % (binascii.hexlify(s))) if (s[3] != '\x00'): print("Error in write register") exit() def read_reg(serial_port, addr): crc = crc8() serial_string = '4C150100022A'+ addr serial_string = serial_string.decode('hex') crc_byte = chr(crc.crc(serial_string)) serial_port.write(serial_string+crc_byte) s = serial_port.read(32) if DEBUG_PRINT_RX_DATA: print("Read:%s" % (binascii.hexlify(s))) if (s[3] != '\x00'): print("Error in set register") exit() serial_string = '4C140100022A02' serial_string = serial_string.decode('hex') crc_byte = chr(crc.crc(serial_string)) serial_port.write(serial_string+crc_byte) s = serial_port.read(32) if DEBUG_PRINT_RX_DATA: print("Read:%s" % (binascii.hexlify(s))) if (s[3] != '\x00'): print("Error in read register") exit() data_read = s[6] + s[7] if DEBUG_PRINT_READ_DATA: print("Addr:", addr,"Data:", binascii.hexlify(data_read) ) return binascii.hexlify(data_read) def ldc_config(serial_port): write_reg(serial_port, LDC1614_MUX_CONFIG, 'C20F') def main(): serial_port = serial.Serial(port='COM13', baudrate=115200) device_id = read_reg (serial_port, LDC1614_DEVICE_ID) print("device_id=%s" % (device_id)) write_reg (serial_port, LDC1614_CONFIG, '0200') ldc_config (serial_port) write_reg (serial_port, LDC1614_CONFIG, '0000') try: while 1: # do loop stuff data_lsb = read_reg (serial_port, LDC1614_DATA_LSB_CH0) data_msb = read_reg (serial_port, LDC1614_DATA_MSB_CH0) status = read_reg (serial_port, LDC1614_STATUS) print("Frequency Counter=%s%s Status=%s " % (data_msb, data_lsb, status)) time.sleep(.5) except KeyboardInterrupt: exit() if __name__ == "__main__": main()
Natalia,
May be you can add this post to FAQ ?
Regards,
John
Hello John,
thank you very much for posting your Python code. I added your example to the inductive sensing FAQ
Hi Chris,
I have some doubts about your reply. I notice that in LDC1000EVM the COM has a 9600 baud rate instead of 115200. My problem is that if I use the protocol above and the Python code writte by John (which is based on the indications and protocol rules above) I have wrong results from serial. I would like to have something like in Putty (see picture below) where I can read directly the L and Rp values without GUI. My target is to read L and Rp measurement with Python with LDC1000 as John did with LDC1614.
Best regards
Alberto
Hi Alberto,
The response you received wouldn't work because the commands you're attempting are for I2C devices, but the LDC1000 uses a SPI interface. You'll need to adjust the read and write register commands to the following format:
Hope this helps!
Best regards,
Blair
Hi Alberto,
Please see below a working code example for LDC1000.
It was originally posted somewhere on TI forums, but I can't find the original thread.
To forum administrators: please add it to FAQ.
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import collections import serial import time import struct import msvcrt from array import * ############################################################################################# # USB CDC commands LDC_READ = '03' LDC_WRITE = '02' LDC_FIRMWARE ='09' LDC_STREAM_ON = '06' LDC_STREAM_OFF = '07' ############################################################################################# ############################################################################################# # LDC1000 addressing space LDC1000_CMD_REVID = '00' LDC1000_CMD_RPMAX = '01' LDC1000_CMD_RPMIN = '02' LDC1000_CMD_SENSORFREQ = '03' LDC1000_CMD_LDCCONFIG = '04' LDC1000_CMD_CLKCONFIG = '05' LDC1000_CMD_THRESHILSB = '06' LDC1000_CMD_THRESHIMSB = '07' LDC1000_CMD_THRESLOLSB = '08' LDC1000_CMD_THRESLOMSB = '09' LDC1000_CMD_INTCONFIG = '0A' LDC1000_CMD_PWRCONFIG = '0B' LDC1000_CMD_STATUS = '20' LDC1000_CMD_PROXLSB = '21' LDC1000_CMD_PROXMSB = '22' LDC1000_CMD_FREQCTRLSB = '23' LDC1000_CMD_FREQCTRMID = '24' LDC1000_CMD_FREQCTRMSB = '25' DEBUG_PRINT_TX_DATA = 0 DEBUG_PRINT_RX_DATA = 0 DEBUG_PRINT_READ_DATA = 0 def write_reg(serial_port, addr, data): serial_port.write('02'+addr+data) s = serial_port.read(32) if DEBUG_PRINT_RX_DATA : print("Read:", s ) def read_reg(serial_port, addr): serial_port.write('03'+addr+'00') s = serial_port.read(32) if DEBUG_PRINT_RX_DATA : print("Read:", s ) data_read = s[8] if DEBUG_PRINT_READ_DATA: print("Addr:", addr,"Data:", data_read ) return data_read.encode('hex') def ldc_config(serial_port): write_reg(serial_port, LDC1000_CMD_RPMAX, '0E') write_reg(serial_port, LDC1000_CMD_RPMIN, '3B') write_reg(serial_port, LDC1000_CMD_SENSORFREQ, '94') write_reg(serial_port, LDC1000_CMD_LDCCONFIG, '17') write_reg(serial_port, LDC1000_CMD_CLKCONFIG, '02') write_reg(serial_port, LDC1000_CMD_INTCONFIG, '04') write_reg(serial_port, LDC1000_CMD_THRESHILSB, '50') write_reg(serial_port, LDC1000_CMD_THRESHIMSB, '14') write_reg(serial_port, LDC1000_CMD_THRESLOLSB, 'C0') write_reg(serial_port, LDC1000_CMD_THRESLOMSB, '12') def main(): serial_port = serial.Serial(port='COM12', baudrate=115200) write_reg (serial_port, LDC1000_CMD_PWRCONFIG, '00') ldc_config (serial_port) write_reg (serial_port, LDC1000_CMD_PWRCONFIG, '01') # Read Proximity Data LSB to update data try: while 1: # do loop stuff read_reg (serial_port, LDC1000_CMD_PROXLSB) data_lsb = read_reg (serial_port, LDC1000_CMD_FREQCTRLSB) data_msb = read_reg (serial_port, LDC1000_CMD_FREQCTRMID) status = read_reg (serial_port, LDC1000_CMD_STATUS) rp_min = read_reg (serial_port, LDC1000_CMD_RPMAX) rp_max = read_reg (serial_port, LDC1000_CMD_RPMIN) freq = read_reg (serial_port, LDC1000_CMD_SENSORFREQ) conf = read_reg (serial_port, LDC1000_CMD_LDCCONFIG) clk = read_reg (serial_port, LDC1000_CMD_CLKCONFIG) int = read_reg (serial_port, LDC1000_CMD_INTCONFIG) th_hi_lsb = read_reg (serial_port, LDC1000_CMD_THRESHILSB) th_hi_msb = read_reg (serial_port, LDC1000_CMD_THRESHIMSB) th_lo_lsb = read_reg (serial_port, LDC1000_CMD_THRESLOLSB) th_lo_msb = read_reg (serial_port, LDC1000_CMD_THRESLOMSB) print("Frequency Counter=%s%s Status=%s rp_min=%s rp_max=%s freq=%s conf=%s clk=%s int=%s th_hi_lsb=%s th_hi_msb=%s th_lo_lsb=%s th_lo_msb=%s" % (data_msb, data_lsb, status, rp_min, rp_max, freq, conf, clk, int, th_hi_lsb, th_hi_msb, th_lo_lsb, th_lo_msb)) time.sleep(.5) except KeyboardInterrupt: exit() if __name__ == "__main__": main()