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:

FlashTool

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:

FlashTool

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 data

  • enc_in (ndarray) – Raw encoder input data

  • coarse_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 factor

  • motor_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 data

  • coarse_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 data

  • coarse_red (int) – Coarse reduction factor

  • motor_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:

MockFlashTool

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:

MockFlashTool

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'#
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'#
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 file

  • pbar (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 file

  • nonce (Optional[int]) – Optional security nonce value

  • pbar (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 dataset

  • label2 (str) – Legend label for second dataset

Returns:

Displays interactive comparison plot

Return type:

None