lenz-flashtool Library API Reference#
FlashTool library for BiSS C Firmware Update and Calibration.
This library provides functions for interfacing with BiSS C encoders using LENZ FlashTool, performing firmware updates, and executing calibration routines.
- Author:
LENZ ENCODERS, 2020-2025
- class lenz_flashtool.BiSSBank(*values)#
Bases:
IntEnum
Enumeration of BiSS C encoder register indices and banking constants.
Defines indices for programmable registers (0-63), fixed-address registers (64-127), and constants for the banking system. Each constant represents either a register index or a size/bank definition used for device configuration, operation, and data access.
- BANKS_PER_PAGE = 32#
Number of banks per page.
- Type:
int
- BISS_BANK_SERV = 2#
Service bank index.
- Type:
int
- BISS_USERBANK_END = 37#
End index of user banks.
- Type:
int
- BISS_USERBANK_START = 5#
Start index of user banks.
- Type:
int
- BOOTLOADER_VER_REG_INDEX = 108#
Bootloader version register index.
- Type:
int
- BOOTLOADER_VER_SIZE = 4#
Bootloader version size in bytes.
- Type:
int
- BSEL_REG_INDEX = 64#
Bank select register index.
- Type:
int
- CMD_REG_INDEX = 72#
Command register index - 2 bytes.
- Type:
int
- CMD_STATE_FLAG_REG_INDEX = 97#
Command state flag register index.
- Type:
int
- CRC32_REG_INDEX = 12#
Index for the CRC32 register for data integrity checks while programming.
- Type:
int
- CRC_ARRAY_REG_INDEX = 24#
CRC array programming register index.
- Type:
int
- DEVID_CRC_REG_INDEX = 27#
Device ID CRC programming register index.
- Type:
int
- DEVID_H_REG_INDEX = 58#
Higher part of device ID programming register index.
- Type:
int
- DEVID_L_REG_INDEX = 54#
Lower part of device ID programming register index.
- Type:
int
- DEV_ID_H_REG_INDEX = 120#
Device ID (high part) register index.
- Type:
int
- DEV_ID_H_SIZE = 4#
Device ID (high part) size in bytes.
- Type:
int
- DEV_ID_L_REG_INDEX = 124#
Device ID (low part) register index.
- Type:
int
- DEV_ID_L_SIZE = 2#
Device ID (low part) size in bytes.
- Type:
int
- DEV_SN_REG_INDEX = 68#
Device serial number index.
- Type:
int
- DEV_SN_SIZE = 4#
Device serial number size in bytes.
- Type:
int
- ENC_DATA_REG_INDEX = 74#
Encoder data register index (calibration state, temperature, Vcc, Signal Mod).
- Type:
int
- FIRSTHARMAMP_REG_INDEX = 80#
First harmonic amplitude register index.
- Type:
int
- FIRSTHARMANGLE_REG_INDEX = 82#
First harmonic angle register index.
- Type:
int
- FIXED_ADDRESSES_START_INDEX = 64#
Start index of fixed address registers.
- Type:
int
- FIXED_BANK_SIZE = 64#
Fixed bank size in bytes.
- Type:
int
- KEY_CRC_REG_INDEX = 26#
Key CRC programming register index.
- Type:
int
- KEY_REG_INDEX = 28#
Key programming register index.
- Type:
int
- MFG_ID_SIZE = 2#
Manufacturer ID size in bytes.
- Type:
int
- MFG_REG_INDEX = 116#
Manufacturing date register index.
- Type:
int
- MFG_REG_SIZE = 4#
Manufacturer date register size in bytes.
- Type:
int
- MFR_ID_REG_INDEX = 126#
Manufacturer ID register index.
- Type:
int
- NONCE_REG_INDEX = 0#
Index for the nonce register while programming.
- Type:
int
- PAGENUM_REG_INDEX = 24#
Page number programming register index.
- Type:
int
- PRODDATE_REG_INDEX = 20#
Index for the production date programming register.
- Type:
int
- PROGVER_REG_INDEX = 112#
Program version register index.
- Type:
int
- PROGVER_REG_SIZE = 4#
Program version size in bytes.
- Type:
int
- REGISTER_PLUS_BSEL_SIZE = 65#
Size of each bank in bytes (64) plus BSEL reg size (1) (data + bank number).
- Type:
int
- REGISTER_PLUS_FIXED_BANK_SIZE = 128#
Register bank (64) and Fixed Addresses (64) size.
- Type:
int
- REV_RES_REG_INDEX = 84#
Revolution and resolution register index.
- Type:
int
- SERIALNUM_CRC_REG_INDEX = 25#
Serial number CRC programming register index.
- Type:
int
- SERIALNUM_REG_INDEX = 16#
Index for the serial number programming register.
- Type:
int
- SHIFT_REG_INDEX = 85#
Shift register index (3 bytes for 180° shift).
- Type:
int
- STATE_FLAG_REG_INDEX = 98#
State flag register index.
- Type:
int
- class lenz_flashtool.FlashTool(port_description_prefixes=('XR21V',), baud_rate=12000000)#
Bases:
object
Main interface for interacting with BiSS C encoders via FlashTool device, connected to a serial port. FlashTool device has 2 channels for encoder connection. Commands perform on channel 2 if not mentioned.
This class provides methods for: - Establishing serial communication with FlashTool device - Sending commands and data to the encoder - Reading encoder status and data - Performing firmware updates - Executing calibration routines
The class implements the singleton pattern to ensure only one connection exists.
- Typical usage:
>>> with FlashTool() as ft: ... ft.biss_read_snum() # Read serial number of the encoder (on channel 2) ... ft.encoder_power_cycle() # Perform power cycle on channel 2 ... ft.biss_write_command('reboot2bl') # Reboot to bootloader
- biss_addr_read(addr, length)#
Reads a specific range of registers from the current BiSS bank.
Sends a read command for the given address and length, and returns the data as a NumPy array after checksum validation.
- Parameters:
addr (
int
) – The starting BiSS register address (0-127).length (
int
) – The number of registers to read.
- Returns:
A NumPy array of uint8 values containing the register data.
- Return type:
np.ndarray
- Raises:
FlashToolError – If the read operation times out or a checksum error occurs.
ValueError – If the address is out of range.
Example
>>> ft = FlashTool() >>> data = ft.biss_addr_read(0x10, 4) >>> print(data) array([0x01, 0x02, 0x03, 0x04], dtype=uint8)
- biss_addr_readb(bissbank, addr, length)#
Reads a specific range of registers from the specified BiSS bank.
Selects the specified bank, sends a read command for the given address and length, and returns the data as a NumPy array after checksum validation.
- Parameters:
bissbank (
int
) – The BiSS bank number to read from (0-255).addr (
int
) – The starting BiSS register address (0-127).length (
int
) – The number of registers to read.
- Returns:
A NumPy array of uint8 values containing the register data.
- Return type:
np.ndarray
- Raises:
FlashToolError – If the read operation times out or a checksum error occurs.
ValueError – If the address or bank number is out of range.
Example
>>> ft = FlashTool() >>> data = ft.biss_addr_readb(1, 0x10, 4) >>> print(data) array([0x01, 0x02, 0x03, 0x04], dtype=uint8)
- biss_cmd_reboot2bl()#
Sends the BiSS command to reboot the device into bootloader mode.
Issues the ‘reboot2bl’ command to the BiSS encoder, initiating a reboot into bootloader mode for firmware updates. Note: This method is deprecated and should be replaced with biss_write_command(‘reboot2bl’).
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_cmd_reboot2bl() WARNING: Deprecated method. Use biss_write_command('reboot2bl') instead.
- biss_read_HSI()#
Reads the HSI (Harmonic Signal Indicator) data from the BiSS encoder.
Sends a read command to retrieve encoder metadata, including the HSI value, and logs the result. Returns the HSI value as a single-element tuple.
- Returns:
A tuple containing the HSI value as a string, or None if the read fails.
- Return type:
Optional[Tuple[str]]
- Raises:
FlashToolError – If the read operation times out or a communication error occurs.
Example
>>> ft = FlashTool() >>> hsi = ft.biss_read_HSI() >>> print(hsi) ('1A',)
- biss_read_angle_once()#
Reads the encoder angle once and prints it in degrees, minutes, and seconds.
Retrieves a single angle reading from encoder 2, converts it to degrees, and prints the formatted output.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_read_angle_once() [2119664]: 45° 30' 15"
- biss_read_calibration_temp_vcc()#
Continuously reads and prints encoder calibration state, signal modulation, temperature, and VCC.
Retrieves calibration data, including calibration state, signal modulation, temperature, and supply voltage, and prints them in a loop with a 1-second interval.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_read_calibration_temp_vcc() CalState: 32, SignalMod: [3671, 4362], EncTemp = 27 °C, Vcc = 4.98 V ...
- biss_read_command_state()#
Reads the command state from the BiSS encoder.
Sends a read command to retrieve the command state, validates the response with a checksum check, and returns the state as a NumPy array.
- Returns:
A NumPy array of uint8 values containing the command state, or None if the read fails.
- Return type:
Optional[np.ndarray]
- Raises:
FlashToolError – If the checksum validation fails or no data is received within the timeout.
Example
>>> ft = FlashTool() >>> state = ft.biss_read_command_state() >>> print(state) array([0x01], dtype=uint8)
- biss_read_flags()#
Reads and interprets state flags and command state from the BiSS encoder.
Retrieves state flags and command state, interprets them using helper functions, and logs the results. Returns the interpreted error flags and command state descriptions.
- Returns:
- A tuple containing:
A list of active error flag descriptions.
A list containing the command state description.
- Return type:
Tuple[List[str], List[str]]
- Raises:
FlashToolError – If reading state flags or command state fails.
Example
>>> ft = FlashTool() >>> flags, cmd_state = ft.biss_read_flags() >>> print(flags, cmd_state) ['FLASH_CRC_ERROR'], ['IDLE']
- biss_read_flags_flashCRC()#
Reads the flash CRC error flag from the BiSS encoder.
Retrieves the state flags and extracts the flash CRC error flag (bit 1).
- Returns:
The flash CRC flag value (0 or 1).
- Return type:
int
- Raises:
FlashToolError – If the read operation fails or CRC validation fails.
Example
>>> ft = FlashTool() >>> crc_flag = ft.biss_read_flags_flashCRC() >>> print(crc_flag) 0
- biss_read_progver()#
Reads and logs the encoder’s program version.
Retrieves the program version from the BiSS encoder and logs it in a formatted string (e.g., “1.1.0.4”).
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_read_progver() INFO: Encoder's program version: 1.1.0.4
- biss_read_registers(bissbank)#
Reads all registers from the specified BiSS bank and logs the results.
Selects the specified bank, sends a read command for all registers, validates the response with a checksum check, and logs the received data as NumPy arrays. Does not return the data, only logs it for debugging purposes.
- Parameters:
bissbank (
int
) – The BiSS bank number to read from (0-255).- Raises:
FlashToolError – If the read operation times out or a communication error occurs.
- Return type:
None
Example
>>> ft = FlashTool() >>> ft.biss_read_registers(1) INFO: BiSS registers: ...
- biss_read_snum()#
Reads the serial number and metadata from the BiSS encoder.
Sends a read command to retrieve encoder metadata, including bootloader version, serial number, manufacturing date, and program version. Parses and logs the data, returning it as a tuple.
- Returns:
A tuple containing the bootloader version, serial number, manufacturing date, and program version as hex strings, or None if the read fails.
- Return type:
Optional[Tuple[str, str, str, str]]
- Raises:
FlashToolError – If the read operation times out or a communication error occurs.
Example
>>> ft = FlashTool() >>> data = ft.biss_read_snum() >>> print(data) ('0100', '12345678', '20230101', '0200')
- biss_read_state_flags()#
Reads the state flags from the BiSS encoder.
Sends a read command to retrieve the state flags, validates the response with a checksum check, and returns the flags as a NumPy array.
- Returns:
A NumPy array of uint8 values containing the state flags.
- Return type:
np.ndarray
- Raises:
FlashToolError – If the checksum validation fails or no data is received within the timeout.
Example
>>> ft = FlashTool() >>> flags = ft.biss_read_state_flags() >>> print(flags) array([0x01, 0x00], dtype=uint8)
- biss_set_bank(bank_num)#
Sets the active BiSS bank for subsequent read/write operations.
Selects the specified bank number for BiSS register operations, ensuring it is within the valid range (0-255).
- Parameters:
bank_num (
int
) – The BiSS bank number to select.- Raises:
ValueError – If the bank number is out of the valid range (0-255).
TypeError – If the bank number is not an integer.
- Return type:
None
Example
>>> ft = FlashTool() >>> ft.biss_set_bank(1)
- biss_set_dir_ccw()#
Sets the encoder direction to counterclockwise.
Resets the FlashTool, power cycles the encoder, unlocks setup and flash, issues the counterclockwise direction command, saves to flash, and power cycles again.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_set_dir_ccw()
- biss_set_dir_cw()#
Sets the encoder direction to clockwise.
Resets the FlashTool, power cycles the encoder, unlocks setup and flash, issues the clockwise direction command, saves to flash, and power cycles again.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_set_dir_cw()
- biss_set_shift(shift_angle)#
Sets the encoder shift angle and verifies the operation.
Reads the current angle, unlocks setup and flash, writes the shift angle, saves to flash, power cycles the encoder, and verifies the new shift angle.
- Parameters:
shift_angle (
int
) – The shift angle value to set.- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_set_shift(1000) [12345]: 45° 30' 15" # TODO [1000]: 0° 0' 0"
- biss_write(addr, data)#
Writes a single byte to a BiSS register at the specified address.
Sends a single 8-bit value to the specified BiSS register address. Note: This method is deprecated and may be removed in future versions.
- Parameters:
addr (
int
) – The BiSS register address (0-127).data (
int
) – The 8-bit integer value to write.
- Raises:
ValueError – If the address is out of range (0-127) or if the data is negative.
TypeError – If the data is not an integer.
- Return type:
None
Example
>>> ft = FlashTool() >>> ft.biss_write(0x10, 0xFF) WARNING: Deprecated method. Consider using biss_write_word instead.
- biss_write_command(command)#
Sends a specific BiSS command to the encoder.
Issues a command from the biss_commands dictionary to the BiSS encoder, such as rebooting, setting direction, or initiating calibration. Commands are written to the command register.
- Parameters:
command (
str
) –The command key from biss_commands. Supported commands include:
’non’: No operation command. Device remains in current state with no action taken.
’load2k’: Load 2 KB of data from registers into device memory. Used for firmware updates.
’staybl’: Force device to stay in bootloader mode.
’run’: Exit bootloader mode and execute the main application program. Initiates normal encoder operation.
’zeroing’: Perform encoder zeroing procedure. Resets position counter to zero at current mechanical position.
’set_dir_cw’: Configure encoder direction sensing for clockwise rotation.
’set_dir_ccw’: Configure encoder direction sensing for counterclockwise rotation.
’saveflash’: Commit current configuration parameters to flash memory.
’ampcalibrate’: Initiate amplitude calibration routine. Automatically adjusts signal amplitudes.
’cleardiflut’: Clear differential lookup table (DifLUT). Resets all offset compensation values to default state.
’set_fast_biss’: Enable high-speed BiSS communication mode.
’set_default_biss’: Revert to standard BiSS communication mode.
’reboot’: Perform device reboot.
’reboot2bl’: Reboot device directly into bootloader mode.
’loadseriald’: Write serial number and manufacturing date to OTP memory.
’loaddevid’: Program DevID into OTP memory.
’loadkey’: Store key in secure flash memory.
’savediftable’: Save differential compensation table to memory.
’unlockflash’: Enable write access to protected flash memory regions.
’unlocksetup’: Disable configuration write protection.
’enarccal’: Enable arc-based calibration mode.
’clearcalflash’: Erase all high-speed oscillator (HSI) and differential calibration data from flash.
- Raises:
FlashToolError – If the specified command is not found in biss_commands.
Example
>>> ft = FlashTool() >>> ft.biss_write_command('reboot2bl')
- biss_write_word(addr, word)#
Writes one or more 8, 16, or 32-bit words to BiSS registers starting at the specified address.
Converts the provided word(s) to bytes, handles endianness, and writes them to the BiSS encoder. Supports single integers or lists of integers, automatically determining the word size (8, 16, or 32 bits) based on the maximum value.
- Parameters:
addr (
int
) – The starting BiSS register address (0-127).word (
Union
[int
,List
[int
]]) – A single integer or a list of integers to write.
- Raises:
ValueError – If the address is out of range, the word list is empty, a word is negative,
or a word exceeds the 32-bit limit. –
TypeError – If any word is not an integer.
FlashToolError – If a hardware communication error occurs.
- Return type:
None
Example
>>> ft = FlashTool() >>> ft.biss_write_word(0x10, 0xABCD) # Write a 16-bit word >>> ft.biss_write_word(0x20, [0x01, 0x02]) # Write two 8-bit words
- biss_zeroing()#
Performs a zeroing calibration on the BiSS encoder.
Resets the FlashTool, power cycles the encoder, unlocks setup and flash, issues the zeroing command, saves to flash, and power cycles again.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.biss_zeroing()
- close()#
Closes the serial port connection and performs cleanup.
Executes all registered cleanup handlers, closes the serial port, restores original signal handlers, and resets the singleton instance. Logs the closure of the connection.
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.close() INFO: FlashTool: COM3 closed.
- enable_signal_handling(signals=(Signals.SIGINT,))#
Enables signal handling for the specified signals to ensure proper cleanup.
Registers signal handlers to call the close method when the specified signals are received, preserving the original handlers for restoration during cleanup.
- Parameters:
signals (
Tuple
[int
,...
]) – Tuple of signal numbers to handle (e.g., signal.SIGINT). Defaults to (signal.SIGINT,).- Returns:
The FlashTool instance for method chaining.
- Return type:
Example
>>> ft = FlashTool().enable_signal_handling((signal.SIGINT, signal.SIGTERM))
- encoder_ch1_power_cycle()#
Performs a power cycle on the encoder on channel 1.
Powers off the encoder, waits 0.1 seconds, powers it back on, and waits another 0.1 seconds to ensure stabilization.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.encoder_ch1_power_cycle()
- encoder_ch1_power_off()#
Powers off the encoder on channel 1.
Sends a POWER_OFF command to the BiSS encoder connected to channel 1 of the FlashTool device.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.encoder_ch1_power_off()
- encoder_ch1_power_on()#
Powers on the encoder on channel 1.
Sends a POWER_ON command to the BiSS encoder connected to channel 1 of the FlashTool device.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.encoder_ch1_power_on()
- encoder_power_cycle()#
Performs a power cycle on the encoder on channel 2.
Powers off the encoder, waits 0.1 seconds, powers it back on, and waits another 0.1 seconds to ensure stabilization.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.encoder_power_cycle()
- encoder_power_off()#
Powers off the encoder on channel 2.
Sends a POWER_OFF command to the BiSS encoder connected to channel 2 of the FlashTool device.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.encoder_power_off()
- encoder_power_on()#
Powers on the encoder on channel 2.
Sends a POWER_ON command to the BiSS encoder connected to channel 2 of the FlashTool device.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.encoder_power_on()
- flashtool_rst()#
Resets the FlashTool device.
Sends a RESET command to the FlashTool, reinitializing its internal state.
- Return type:
None
- Returns:
None
Example
>>> ft = FlashTool() >>> ft.flashtool_rst()
- hex_line_send(hex_line)#
Sends a hex-formatted line to the FlashTool device.
Converts the provided hex line (starting with ‘:’) to bytes and transmits it to the FlashTool device via the serial port.
- Parameters:
hex_line (
str
) – A string representing a hex line, including the leading ‘:’.- Returns:
The transmitted bytes.
- Return type:
bytes
Example
>>> ft = FlashTool() >>> ft.hex_line_send(':0100400C0AA9') b'\x01\x00@\x0c\n\xa9'
- port_read(length)#
Reads data from the serial port and validates it with a checksum check.
Waits for the specified number of data bytes plus a checksum byte, reads the data, and verifies the checksum. Logs the received data and checksum status, returning the data as a NumPy array.
- Parameters:
length (
int
) – The number of data bytes to read (excluding the checksum byte).- Returns:
A NumPy array of uint8 values containing the received data (excluding header and checksum).
- Return type:
np.ndarray
- Raises:
FlashToolError – If the data is not received within the timeout period or if checksum validation fails.
Example
>>> ft = FlashTool() >>> data = ft.port_read(10) >>> print(data) array([0x01, 0x02, ..., 0x0A], dtype=uint8)
- read_data(read_time)#
Reads encoder data via SPI over USB for a specified duration.
Sends a command to read data, collects incoming packets, validates them with checksums, and extracts encoder values. Prints progress indicators during reading.
- Parameters:
read_time (
float
) – The duration in seconds to read data.- Returns:
A NumPy array of int32 values containing the encoder readings.
- Return type:
np.ndarray
- Raises:
ValueError – If a checksum or command error occurs in the received data.
Example
>>> ft = FlashTool() >>> data = ft.read_data(2.0) Read USB data for 2.0 seconds: ..... OK! >>> print(data) array([12345, 12346, ...], dtype=int32)
- read_data_enc1_AB_enc2_SPI(read_time, status=True)#
Read data from Encoder SPI (SIB, IRS) and AB over USB for a specified duration.
Sends a command to read data from both encoders, processes incoming packets, validates checksums, and extracts encoder values for both channels. Optionally prints progress indicators.
Data frame: 6 bytes 0 byte 1 byte 2 byte 3 byte 4 byte 5 byte Enc2 *256 *65536 Cou Enc1 *256
- Returns:
- Two np.ndarrays containing:
Encoder2 data.
Encoder1 data.
- Return type:
tuple[np.ndarray, np.ndarray]
- Raises:
ValueError – If a checksum or command error occurs in the received data.
- read_data_enc1_enc2_SPI(read_time, status=True)#
Reads data from two encoders via SPI over USB for a specified duration.
Sends a command to read data from both encoders, processes incoming packets, validates checksums, and extracts encoder values for both channels. Optionally prints progress indicators.
- Parameters:
read_time (
float
) – The duration in seconds to read data.status (
bool
) – If True, prints progress indicators (dots and status messages). Defaults to True.
- Returns:
Two lists containing the readings from encoder 1 and encoder 2, respectively.
- Return type:
Tuple[List[int], List[int]]
- Raises:
ValueError – If a checksum or command error occurs in the received data.
Example
>>> ft = FlashTool() >>> enc1, enc2 = ft.read_data_enc1_enc2_SPI(2.0) Read USB data for 2.0 seconds: ..... OK! >>> print(enc1[:5], enc2[:5]) [12345, 12346, ...], [54321, 54322, ...]
- register_cleanup(handler)#
Registers a cleanup function to be executed during close or on SIGINT.
Allows scripts to define custom cleanup operations, such as resetting hardware states or closing additional resources, which are called when the FlashTool connection is closed.
- Parameters:
handler (
Callable
[[],None
]) – A callable with no arguments that performs cleanup operations.- Returns:
The FlashTool instance for method chaining.
- Return type:
Example
>>> def custom_cleanup(): ... elmo.motor_off() ... print("Cleaning up resources. Stopping motor.") >>> ft = FlashTool().register_cleanup(custom_cleanup)
- select_FlashTool_mode(mode)#
Select FlashTool mode.
Sends a SELECT Flashtool mode command to the FlashTool.
- There are three modes:
0 –> BISS_MODE_SPI_SPI. 1 –> BISS_MODE_AB_UART. 2 –> BISS_MODE_SPI_UART_IRS. 3 –> BISS_MODE_AB_SPI.
- Parameters:
mode (uint8) – The mode number (must be 0, 1, 2, 3).
- Returns:
None
- Raises:
ValueError – If the mode is not 0, 1, 2, 3.
Example
>>> ft = FlashTool() >>> ft.select_FlashTool_mode(0)
- select_SPI_channel(channel)#
Select SPI communication channel.
Sends a SELECT CHANNEL command to the FlashTool.
- There are two channels:
0 –> channel 1; 1 –> channel 2.
- Parameters:
channel (uint8) – The channel number (must be 0 or 1).
- Return type:
None
- Returns:
None
- Raises:
ValueError – If the mode is not 0 or 1.
Example
>>> ft = FlashTool() >>> ft.select_SPI_channel(0)
- send_data_to_device(pages, crc_values, page_numbers, start_page, end_page, pbar=None, difmode=False)#
Transmits organized data pages to the BiSS encoder with CRC verification.
Sends pages of data to the encoder, writing CRC and page numbers as needed, and verifies each page with a flash CRC check. Supports a progress bar and differential mode for specific use cases.
- Parameters:
pages (
List
[List
[bytes
]]) – A list of pages, where each page is a list of byte arrays.crc_values (
List
[int
]) – A list of CRC checksums for each page.page_numbers (
List
[int
]) – A list of page numbers corresponding to each page.start_page (
int
) – The index of the first page to transmit.end_page (
int
) – The index of the last page to transmit.pbar (
Optional
[Any
]) – An optional progress bar object for tracking transmission progress.difmode (
bool
) – If True, uses differential table transmission mode. Defaults to False.
- Raises:
SystemExit – If transmission fails after the maximum number of retries.
FlashToolError – If a hardware communication error occurs.
- Return type:
None
Example
>>> ft = FlashTool() >>> pages = [[b'\x01\x02', b'\x03\x04'], [b'\x05\x06', b'\x07\x08']] >>> crc_values = [0x1234, 0x5678] >>> page_numbers = [1, 2] >>> ft.send_data_to_device(pages, crc_values, page_numbers, 0, 1) INFO: Done uploading!
- exception lenz_flashtool.FlashToolError#
Bases:
Exception
Custom exception for FlashTool errors.
Raised when a critical error occurs within the FlashTool library.
- class lenz_flashtool.LenzEncoderProcessor#
Bases:
object
Main class for LENZ encoder signal processing operations.
Provides static methods for differential signal calculation, compensation table generation, harmonic analysis, and calibration routines for LENZ encoders.
- static analyze_harmonics(diff_table)#
Analyzes frequency components of the difference table using FFT.
- Parameters:
diff_table (np.array) – Difference table array.
- Returns:
Amplitude of first harmonic
Angle of first harmonic
Full FFT result
- Return type:
Tuple containing
- static as_filt(data, depth)#
Applies a custom filter to smooth the data.
- Parameters:
data (np.array) – Input data to filter.
depth (int) – Filter depth parameter
- Returns:
Filtered data
- Return type:
np.array
- static calc_diff(encoder_1, encoder_2, coarse_red)#
Computes the differential signal between two encoder readings with scaling.
This function calculates the difference between two encoder signals, applies mean centering, and scales the result according to the coarse reduction factor. The output represents the relative error between the two encoders, normalized.
- Parameters:
encoder_1 (
int32
) – First encoder readings array (24-bit values)encoder_2 (
int32
) – Second encoder readings array (24-bit values)coarse_red (
int
) – Scaling factor for coarse reduction (typically 2^11 for 24-bit encoders)
- Return type:
ndarray
- Returns:
Differential signal array with mean removed and scaled by coarse_red/2048
- static clip_to_int8(data)#
Clips and converts data to 8-bit integers.
- Parameters:
data (np.array) – Input data.
- Returns:
Clipped and converted data.
- Return type:
np.array
- static comp_diff(encoder_in, diff_table_in, coarse_red)#
Compensates encoder data using a difference table for error correction.
This function applies a compensation table to raw encoder data to correct systematic errors, using linear interpolation between table entries.
- Parameters:
encoder_in (
ndarray
) – Raw encoder input data (24-bit values as int32)diff_table_in (
ndarray
) – Difference compensation table (int16 values)coarse_red (
int
) – Coarse reduction factor (scaling parameter)
- Returns:
Compensated encoder data (24-bit values as int32)
- Return type:
np.ndarray
- static compute_difftable(diff, lenz_fix, coarse_red)#
Computes a difference compensation table by averaging error values at each encoder position.
- Parameters:
diff (
ndarray
) – Array of measured error values (difference between reference and raw encoder values)lenz_fix (
ndarray
) – Array of fixed LENZ encoder positions corresponding to the error measurements.coarse_red (
int
) – Coarse reduction factor.
- Returns:
- Difference compensation table where each index corresponds to an encoder
position and contains the average error at that position.
- Return type:
np.ndarray
- static diff_gen(enc_filt, enc_in, coarse_red)#
Generates difference signal between filtered and raw encoder data.
- Parameters:
enc_filt (
ndarray
) – Filtered encoder dataenc_in (
ndarray
) – Raw encoder input datacoarse_red (
int
) – Coarse reduction factor
- Returns:
Difference signal (double)
- Return type:
np.ndarray
- static diff_table_gen(diff_in, enc_fix, coarse_red)#
Generates a difference compensation table from error measurements.
The table is created by averaging error measurements at each position, then applying FFT-based filtering to remove noise.
- Parameters:
diff_in (
ndarray
) – Array of measured errors (double)enc_fix (
ndarray
) – Array of fixed encoder positions corresponding to errors (int32)coarse_red (
int
) – Coarse reduction factor (scaling parameter)
- Returns:
Generated difference table (int16 values)
- Return type:
np.ndarray
- static diff_table_gen_motor_harm(diff_in, enc_fix, coarse_red, motor_harm)#
Generates difference table with additional motor harmonic suppression.
Similar to DifTableGen but specifically removes motor-related harmonics from the compensation table.
- Parameters:
diff_in (
ndarray
) – Array of measured errors (double)enc_fix (
ndarray
) – Array of fixed encoder positions (int32)coarse_red (
int
) – Coarse reduction factormotor_harm (
int
) – Motor harmonic frequency to suppress
- Returns:
Generated difference table with motor harmonics removed (int16)
- Return type:
np.ndarray
- static ext_gen(data_in)#
Extends 24-bit encoder data to 32-bit by handling overflow correctly.
This function processes raw 24-bit encoder data by maintaining proper sign extension when converting to 32-bit values, ensuring correct handling of overflow cases.
- Parameters:
data_in (
ndarray
) – Input array of 24-bit encoder values (as int32)- Returns:
Array of extended 32-bit encoder values with proper overflow handling
- Return type:
np.ndarray
- static extrapolate(data, res)#
Extrapolates data to handle discontinuities or wrap-around effects.
- Parameters:
data (np.array) – Input data to extrapolate.
res (int) – Bit resolution for extrapolation.
- Returns:
Extrapolated data.
- Return type:
np.array
- static filt_enc(encoder_in, window_size)#
Applies a bidirectional moving average filter to encoder data.
The filter processes data both forwards and backwards to minimize phase distortion, then averages both results for the final output.
- Parameters:
encoder_in (
ndarray
) – Raw encoder input data (int32 values)window_size (
int
) – Size of the moving average window
- Returns:
Filtered encoder data (int32 values)
- Return type:
np.ndarray
- static lenz_cal(encoder_in, coarse_red)#
Main calibration routine for LENZ encoder compensation.
Performs a two-stage calibration process to generate a final compensation table.
- Parameters:
encoder_in (
ndarray
) – Raw encoder input datacoarse_red (
int
) – Coarse reduction factor
- Returns:
Final compensation table (int8 values)
- Return type:
np.ndarray
- static lenz_cal_motor_harm(encoder_in, coarse_red, motor_harm)#
LENZ encoder calibration with additional motor harmonic suppression.
Similar to lenz_cal method but includes motor harmonic removal in the compensation table.
- Parameters:
encoder_in (
ndarray
) – Raw encoder input datacoarse_red (
int
) – Coarse reduction factormotor_harm (
int
) – Motor harmonic frequency to suppress
- Returns:
Final compensation table with motor harmonics removed (int8)
- Return type:
np.ndarray
- class lenz_flashtool.MockFlashTool(*args, **kwargs)#
Bases:
object
A mock implementation of FlashTool for testing purposes without hardware access. Simulates the behavior of the real FlashTool class.
- biss_addr_read(addr, length)#
Mock address reading
- Return type:
ndarray
- biss_addr_readb(bissbank, addr, length)#
Mock address reading with bank
- Return type:
ndarray
- biss_cmd_reboot2bl()#
Mock reboot to bootloader command
- biss_read_HSI()#
Mock HSI reading
- Return type:
Optional
[Tuple
[str
]]
- biss_read_angle_once()#
Mock single angle reading
- Return type:
None
- biss_read_calibration_temp_vcc()#
Mock calibration data reading
- Return type:
None
- biss_read_command_state()#
Mock command state reading
- Return type:
Optional
[ndarray
]
- biss_read_flags()#
Mock flags reading
- Return type:
Tuple
[List
[str
],List
[str
]]
- biss_read_flags_flashCRC()#
Mock flash CRC flag reading
- Return type:
int
- biss_read_progver()#
Mock program version reading
- Return type:
None
- biss_read_registers(bissbank)#
Mock register reading
- biss_read_snum()#
Mock serial number reading
- Return type:
Optional
[Tuple
[str
,str
,str
,str
]]
- biss_read_state_flags()#
Mock state flags reading
- Return type:
ndarray
- biss_set_bank(bank_num)#
Mock bank selection
- biss_set_dir_ccw()#
Mock set direction counter-clockwise
- Return type:
None
- biss_set_dir_cw()#
Mock set direction clockwise
- Return type:
None
- biss_set_shift(shift_angle)#
Mock set shift angle
- Return type:
None
- biss_write(addr, data)#
Mock write operation
- biss_write_command(command)#
Mock command writing
- biss_write_word(addr, word)#
Mock word writing
- Return type:
None
- biss_zeroing()#
Mock zeroing calibration
- Return type:
None
- close()#
Mock close method
- enable_signal_handling(signals=(Signals.SIGINT,))#
- Return type:
- encoder_ch1_power_cycle()#
Mock channel 1 power cycle
- Return type:
None
- encoder_ch1_power_off()#
Mock channel 1 power off
- Return type:
None
- encoder_ch1_power_on()#
Mock channel 1 power on
- Return type:
None
- encoder_power_cycle()#
Mock power cycle
- Return type:
None
- encoder_power_off()#
Mock power off
- Return type:
None
- encoder_power_on()#
Mock power on
- Return type:
None
- flashtool_rst()#
Mock reset
- Return type:
None
- hex_line_send(hex_line)#
Mock hex line sending
- Return type:
bytes
- port_read(length)#
Mock port read with simulated data
- Return type:
ndarray
- read_data(read_time)#
Mock data reading
- read_data_enc1_enc2_SPI(read_time, status=True)#
Mock dual encoder reading
- Return type:
Tuple
[List
[int
],List
[int
]]
- register_cleanup(handler)#
- Return type:
- send_data_to_device(pages, crc_values, page_numbers, start_page, end_page, pbar=None, difmode=False)#
Mock data sending to device
- Return type:
None
- class lenz_flashtool.TermColors#
Bases:
object
- BOLD = '\x1b[1m'#
- BackgroundBlack = '\x1b[40m'#
- BackgroundBlue = '\x1b[44m'#
- BackgroundCyan = '\x1b[46m'#
- BackgroundDarkGray = '\x1b[100m'#
- BackgroundDefault = '\x1b[49m'#
- BackgroundGreen = '\x1b[42m'#
- BackgroundLightBlue = '\x1b[104m'#
- BackgroundLightCyan = '\x1b[106m'#
- BackgroundLightGray = '\x1b[47m'#
- BackgroundLightGreen = '\x1b[102m'#
- BackgroundLightMagenta = '\x1b[105m'#
- BackgroundLightRed = '\x1b[101m'#
- BackgroundLightYellow = '\x1b[103m'#
- BackgroundMagenta = '\x1b[45m'#
- BackgroundRed = '\x1b[41m'#
- BackgroundWhite = '\x1b[107m'#
- BackgroundYellow = '\x1b[43m'#
- Black = '\x1b[30m'#
- Blink = '\x1b[5m'#
- Blue = '\x1b[34m'#
- Bold = '\x1b[1m'#
- Cyan = '\x1b[36m'#
- DarkGray = '\x1b[90m'#
- Default = '\x1b[39m'#
- Dim = '\x1b[2m'#
- ENDC = '\x1b[0m'#
- FAIL = '\x1b[91m'#
- GRAY = '\x1b[90m'#
- Green = '\x1b[32m'#
- HEADER = '\x1b[95m'#
- Hidden = '\x1b[8m'#
- LightBlue = '\x1b[94m'#
- LightCyan = '\x1b[96m'#
- LightGray = '\x1b[37m'#
- LightGreen = '\x1b[92m'#
- LightMagenta = '\x1b[95m'#
- LightRed = '\x1b[91m'#
- LightYellow = '\x1b[93m'#
- Magenta = '\x1b[35m'#
- OKBLUE = '\x1b[94m'#
- OKGREEN = '\x1b[92m'#
- Red = '\x1b[31m'#
- ResetBlink = '\x1b[25m'#
- ResetBold = '\x1b[21m'#
- ResetDim = '\x1b[22m'#
- ResetHidden = '\x1b[28m'#
- ResetReverse = '\x1b[27m'#
- ResetUnderlined = '\x1b[24m'#
- Reverse = '\x1b[7m'#
- UNDERLINE = '\x1b[4m'#
- Underlined = '\x1b[4m'#
- WARNING = '\x1b[93m'#
- White = '\x1b[97m'#
- Yellow = '\x1b[33m'#
- class lenz_flashtool.UartCmd(*values)#
Bases:
IntEnum
Enumeration of UART commands for communication with the FlashTool system.
This class defines all the hexadecimal command codes used for controlling power, channel selection, and data communication with the FlashTool hardware.
- CMD_CH1_POWER_OFF = 8#
Command to power off encoder on channel 1.
- Usage:
Sent to deactivate power to the secondary encoder (channel 1)
Useful for power management in dual-encoder systems
Typically used during maintenance or reconfiguration
Expects no additional parameters
- Packet Structure:
Request: [DUMMY_DATA_SIZE][REG_ADDR][0x08][DUMMY_DATA][CHECKSUM] Response: None
Examples
>>> :01004008DDDA >>> :04000008DDAADDAAE6
- Type:
int
- CMD_CH1_POWER_ON = 9#
Command to power on the encoder on channel 1.
- Usage:
Sent to activate power to the secondary encoder (channel 1)
Should be preceded by channel selection if needed
Requires stabilization time (0.1s) before encoder communication
Expects no additional parameters
- Packet Structure:
Request: [DUMMY_DATA_SIZE][REG_ADDR][0x09][DUMMY_DATA][CHECKSUM] Response: None
Examples
>>> :0100000903F3 >>> :0300A009A0A0A173
- Type:
int
- CMD_NVRST = 131#
Command to perform a non-volatile reset of the FlashTool.
- Usage:
Clears any temporary settings
Requires stabilization time (0.1s) before encoder communication
Data and address in packet doesn’t matter
- Packet Structure:
Request: [DUMMY_DATA_SIZE][REG_ADDR][0x83][DUMMY_DATA][CHECKSUM] Response: None
Examples
>>> :01004083221A >>> :0400408311111111F5
- Type:
int
- CMD_POWER_OFF = 11#
Command to power off encoder on channel 2.
- Usage:
Sent to deactivate power to the encoder connected to channel 2
Typically used during maintenance or reconfiguration
Expects no additional parameters
Data and address in packet doesn’t matter
- Packet Structure:
Request: [DUMMY_DATA_SIZE][REG_ADDR][0x0B][DUMMY_DATA][CHECKSUM] Response: None
Examples
>>> :0100400BFFB5 >>> :0400400B111111116D
- Type:
int
- CMD_POWER_ON = 12#
Command to power on the encoder on channel 2.
- Usage:
Sent to activate power to the encoder connected to channel 2
Should be followed by a stabilization delay (0.1s) before communication
Expects no additional parameters
Data and address in packet doesn’t matter
- Packet Structure:
Request: [DUMMY_DATA_SIZE][REG_ADDR][0x0C][DUMMY_DATA][CHECKSUM] Response: None
Examples
>>> :0100400C0AA9 >>> :0300400CAABBCC80
- Type:
int
- CMD_SELECT_FLASHTOOL_MODE = 1#
Command to select FlashTool mode for communication.
- Usage:
Sent before any channel-specific operations
- Parameter:
0x00 for BISS_MODE_SPI_SPI, 0x01 for BISS_MODE_AB_UART, 0x02 for BISS_MODE_SPI_UART_IRS, 0x03 for BISS_MODE_AB_SPI
Defines all subsequent communications via SPI, AB (incremental), UART for channels 1 and 2 until changed
Address in packet doesn’t matter
Note
FlashTool mode is persistent until changed or power cycled Default: BISS_MODE_SPI_SPI (0x00)
- Packet Structure:
Request: [01][REG_ADDR][0x01][CHANNEL_BYTE][CHECKSUM] Where CHANNEL_BYTE is 0x00, 0x01, 0x02 or 0x03
Example
>>> :0100000100FE Select FlashTool mode - BISS_MODE_SPI_SPI
- Type:
int
- CMD_SELECT_SPI_CH = 10#
Command to select SPI communication channel.
- Usage:
Sent before any channel-specific operations
Parameter: 0x00 for channel 1, 0x01 for channel 2
Affects all subsequent SPI communications until changed
Note
Channel selection is persistent until changed or power cycled Default: Channel 2 (0x01)
- Packet Structure:
Request: [01][REG_ADDR][0x0A][CHANNEL_BYTE][CHECKSUM] Where CHANNEL_BYTE is 0x00 or 0x01
Example
>>> :0100400A00F4 Select channel 1
- Type:
int
- HEX_READ_ANGLE_TWO_ENC_AB_SPI = 120#
Command to read angle data via AB (incremental) interface over SPI.
- Usage:
SPI angle reading
Provides quadrature-encoded equivalent output
Note
channel 1 - AB channel 2 - SPI
- Type:
int
- HEX_READ_ANGLE_TWO_ENC_AB_UART = 121#
Command to read angle data via AB (incremental) interface over UART.
- Usage:
Alternative to SPI angle reading
Provides quadrature-encoded equivalent output
Faster update rate than SPI in some implementations
- Type:
int
- HEX_READ_ANGLE_TWO_ENC_SPI = 128#
Command to read angle data from two encoders via SPI.
- Usage:
Continuous streaming mode for dual-encoder reading
Requires both encoders to be powered on
Returns multiple measurement frames in each response packet
- Response Format:
Each 245-byte packet contains:
>>> [Header][FrameCount][Reserved][DataFrames...][Checksum]
Where:
Header: [0xF0, 0x00, 0x00, 0x90] (fixed pattern)
FrameCount: Number of valid data frames (typically 30)
DataFrames: 30 measurement frames (8 bytes each):
>>> [ENC1_LOW][ENC1_MID][ENC1_HIGH][ENC1_COUNTER] >>> [ENC2_LOW][ENC2_MID][ENC2_HIGH][ENC2_COUNTER]
Checksum: 1 byte (sum of first 244 bytes modulo 256)
- Data Interpretation:
>>> Encoder Angle = (HIGH << 16) | (MID << 8) | LOW
Counter = Single byte turn counter
- Example Packet Structure:
>>> F0 00 00 90 [30 frames...] [checksum]
- Type:
int
- HEX_READ_CMD = 130#
Generic read command for encoder data.
- Usage:
Followed by register address and dummy data with size equal to required read data size
Can read various status and configuration registers
Response length depends on target register
- Packet Structure:
Request: [DUMMY_DATA_SIZE][REG_ADDR][0x82][DUMMY_DATA][CHECKSUM]
Response: [DATA_SIZE][REG_ADDR][0x92][DATA][CHECKSUM]
Examples
- Read Example:
>>> :01004082013C
- Response:
>>> 0x10040920528
Another example writing 3 to BSEL register (changing BiSS Bank to 3):
- Requests:
>>> :0100400D03AF Writing 3 to register 0x40 >>> :01004082013C Reading register 0x40
- Response:
>>> 0x1004092032A Register 0x40 keeps 0x03
- Type:
int
- HEX_WRITE_CMD = 13#
Command to write data to encoder registers.
- Usage:
Used for configuration and parameter setting
- Packet Structure:
Request: [DATA_SIZE][REG_ADDR][0x0D][DATA_MSB][DATA_LSB][CHECKSUM] Response: None
Example
>>> :0100400D05AD
- Type:
int
- lenz_flashtool.biss_send_dif(file_path, pbar=None)#
Main function for transmitting DIF tables to BiSS device.
- Parameters:
file_path (
str
) – Path to input DIF CSV filepbar (
Optional
[Any
]) – Optional progress bar object
- Return type:
None
- lenz_flashtool.biss_send_hex(file_path, nonce=None, pbar=None)#
Main function for transmitting HEX files to BiSS device.
- Parameters:
file_path (
str
) – Path to input HEX filenonce (
Optional
[int
]) – Optional security nonce valuepbar (
Optional
[Any
]) – Optional progress bar object
- Return type:
None
- lenz_flashtool.calculate_checksum(hex_data)#
Calculate Intel HEX-style checksum for a hex string.
- Parameters:
hex_data (
str
) – Hex string without leading ‘:’ or ending checksum- Return type:
int
- Returns:
Checksum byte (0-255)
Example
>>> calculate_checksum("10010000214601360121470136007EFE09D21901") 64
- lenz_flashtool.generate_hex_line(address, command, data)#
Generate a formatted hex line for communication with a device.
- Parameters:
address (int) – The 16-bit address field.
command (int) – The command byte.
data (List[int]) – A list of data bytes to include in the hex line.
- Returns:
The formatted hex line string, including the starting ‘:’ and checksum.
- Return type:
str
- lenz_flashtool.get_nonce(filename)#
Retrieve the nonce values from a binary file.
- Parameters:
filename (str) – The base filename (without extension) of the nonce file.
- Returns:
A list of 32-bit unsigned integers representing the nonces.
- Return type:
List[int]
- lenz_flashtool.init_logging(logfilename=None, stdout_level=20, file_level=10, logger_name='lenz_flashtool')#
Initializes the logging system with console and optional file handlers.
This function sets up a logger with a stdout handler and, if a filename is provided, a file handler. Each handler has its own logging level and formatter.
- Parameters:
logfilename (Optional[str]) – The name of the file to log messages to. If None, no file logging occurs.
stdout_level (int) – The logging level for the stdout handler (default: INFO).
file_level (int) – The logging level for the file handler (default: DEBUG).
logger_name (str) – The name of the logger to configure (default: “lenz_flashtool”). If None, the root logger is configured.
- Returns:
The configured logger instance.
- Return type:
logging.Logger
- Raises:
ValueError – If logging levels are invalid.
- lenz_flashtool.plot(data, filename=None, directory=None)#
Plots a single dataset with annotated max and min values.
- Parameters:
data (
Union
[Sequence
[float
],ndarray
]) – Input data to visualize (list or numpy array of numerical values)filename (
Optional
[str
]) – Name for the output file (including extension). If None, plot won’t be saved.directory (
Optional
[str
]) – Target directory for saving. If None, uses current working directory.
- Returns:
Displays interactive plot and optionally saves to file.
- Return type:
None
Example
>>> data = [1, 3, 2, 4, 3] >>> plot(data, 'trend.png', 'plots') # Saves to 'plots/trend.png'
- lenz_flashtool.plot2(a, b, filename=None, directory=None, label1='After calibration', label2='Before calibration')#
Plots two datasets for comparison with annotated statistics.
- Parameters:
a (
Union
[Sequence
[float
],ndarray
]) – First dataset (list or numpy array)b (
Union
[Sequence
[float
],ndarray
]) – Second dataset (list or numpy array)filename (
Optional
[str
]) – Output filename (including extension). None prevents saving.directory (
Optional
[str
]) – Target directory. None uses current directory.label1 (
str
) – Legend label for first datasetlabel2 (
str
) – Legend label for second dataset
- Returns:
Displays interactive comparison plot
- Return type:
None