Skip to content

Status and diagnostics

What the driver tells about itself, from firmware 109: what is in force, who it is, its state in one frame, how long its control loop takes, and recordings of its own signals made inside the control loop. The error flags and what to do about each are on Errors and recovery.

What is in force

#Info ends with the section In force:, and parameter 79 holds the same as bits (What is in force: parameter 79):

Line Says
encoder table: on, error … deg p-p, measured, off or not measured (Encoder table and anti-cogging)
anti-cogging: on (harmonics), on (table), identified, off or not identified, and , saved when it is the saved set
current-sense zero trim: the two trims in counts, and whether the zero measured with the bridge switching is in use
delay compensation: the commutation delay in µs, or off (Commutation delay compensation)
speed estimate: moving average, PLL, … Hz or direct PLL, … Hz (The speed estimate)
fast reading / fast PWM: the two register paths of the control loop, on or off
input filter:, integral deadband: parameters 74 and 75, or off
after #Calangle (parameter 56): what follows a #Calangle: anti-cogging, then save or nothing
running: only while one runs: calibration, encoder table, anti-cogging identification, or the runs after the calibration

Before that section #Info prints, beside what it printed before:

  • Build: the git commit the firmware was built from, 7 hex digits. A + after it means it was built with uncommitted changes. Parameter 84 holds the same, and parameter 85 the build time in Unix seconds.
  • Board ID: the chip's unique number, folded into 8 hex digits. It never changes. Also parameter 86.
  • Calibration ID: a new number at every successful #Cal, #Calonly or #Calangle, in 8 hex digits. Save keeps it, and #Default sets it back to 0. Also parameter 87.
  • CAN RX overruns and CAN TX dropped: frames the driver lost because its receive buffer was full, and answers it gave up after waiting 1 ms for a free transmit mailbox. Both should stay 0; they count from power-up. From firmware 109 the CAN controller passes only the frames addressed to the driver's own node ID, and the driver sends from all three transmit mailboxes, so a busy bus costs it less.
  • Product: this firmware, STEPFOC.
  • Current sense zero: the zeros in use, in ADC counts from 2048, measured at start-up with the bridge off (one count is about 1.6 mA), and what the second measurement with the bridge switching found. A zero more than 200 counts from 2048 is not trusted: the driver then uses 2048 and says not measured or out of range. The current sensors need the motor supply. If the driver starts without it (USB plugged in before the supply), it waits up to half a second for the supply, then uses 2048 and says no motor supply at start-up: 2048 used; measured once the supply is there. When the supply comes, the driver measures the zero by itself at rest, coasting for about 80 ms even if it is set to brake, and the line shows the new zeros. The Vbus error the late supply latched stays until #Clear.
  • Tool ID, Watchdog: … ms, action …, fallback …, Settings block 2: ok and Anti-cogging: …, scale … % with whether it is saved.

Who the drive is: the identity frame

Send_Respond_Identity (ID 39, a remote frame) answers with the product (1 STEPFOC, 2 Spectral Micro), the tool id, the firmware release, the hardware version, the pole pairs, whether it is calibrated, and eight flags: set up as a gripper, brakes in idle, coils reversed, settings block 2 available, wrong product, current-sense zero measured, anti-cogging saved, switching zero in use (Send_Respond_Identity).

A host can read it before it commands or flashes a drive, to know it talks to the drive it expects.

The tool id says what the drive is built into:

  • 0: none (a joint or a bare driver);
  • 1: an SSG-48;
  • 11 to 33: an MSG (the tens digit the rail, 1 = 100, 2 = 150, 3 = 200 mm; the units digit the stepper, 1 = 21.5, 2 = 40, 3 = 60 mm);
  • 200 to 254: your own tools.

Set it with #Tool or parameter 1 and save.

Everything at once: telemetry

Send_Respond_Telemetry (ID 40, a remote frame) answers with the temperature, the supply voltage, both error bytes and the current, all from the same moment: one request instead of four, for a host that watches many drives (Send_Respond_Telemetry).

The product lock

STEPFOC and the Spectral Micro use the same bootloader and the same file name for their firmware, and each firmware drives the other board wrongly: the Spectral firmware on a STEPFOC drove a coil at about 1.7 A in every mode on the bench.

From firmware 109 a board remembers which product calibrated it, a stamp in the EEPROM written at the first start-up of a calibrated board and at every save.

A firmware that finds the other product's stamp, or no stamp but a calibration its own product cannot make (STEPFOC calibrates only 50, 75, 100 or 125 pole pairs), reads and writes nothing more, drives no pin and starts no control loop.

It stays reachable: it reports an error, Wrong firmware for this board (product lock) in #Error, the wrong_product bit in the error state and the identity, and a warning in #Info. Flash the right firmware and the board runs as before; nothing was written.

#Product shows the stamp. On a board the rule misjudges, #Product claim stamps it as this product and #Product clear removes the stamp; power-cycle after either. Both are UART commands only.

How long the control loop takes

The control loop runs every 160 µs (6250 Hz) and has to finish inside that. #Info prints the last loop's time; parameters 66 to 70 give its five sections, averaged over about 64 loops, in 0.1 µs: the checks, reading the encoder, the currents and the supply, the transforms, the control mode with the PWM, and the rest (the capture).

On the bench drive with everything on (anti-cogging, delay compensation, the direct PLL, the encoder table, fast reading and PWM) the loop took about 129 µs of its 160 while the motor turned, 128 µs while it held, 68 µs in idle. What the features cost while turning:

Feature Parameter µs per loop
anti-cogging on 37 about 10
commutation delay compensation 64 about 10
encoder table on 53 0.1
moving average instead of the direct PLL 50 −1
sin and cos from the table 65 +1.3 (slower, so off)
fast reading off 71 +14
fast PWM off 72 +4

Without the two fast paths the loop would take about 148 µs while turning, too close to 160 for comfort: leave them on. They read the ADC and the encoder and write the PWM by register instead of through the library calls, with every wait bounded; the current noise stayed the same.

A capture

The capture records three signals inside the control loop, sample by sample, 1024 samples per channel: what the loop saw and did, which a host polling over the bus cannot see.

Parameters 24 to 33 set it up and report on it, Send_Buffer_Read with kind 0 reads it (Reading the capture; the signals are listed under Capture and histogram). While the encoder table or the anti-cogging run turns the motor, a capture is not armed: the runs use its memory.

A step response, 1024 samples of speed, current and position error, one every 2 loops (0.33 s):

import time
import Spectral_BLDC as Spectral

comms = Spectral.CanCommunication(bustype='slcan', channel='COM41', bitrate=1000000)
motor = Spectral.SpectralCAN(node_id=0, communication=comms)

def read_all(seconds):
    end = time.time() + seconds
    while time.time() < end:
        message, ids = comms.receive_can_messages(timeout=0.01)
        if message is not None:
            motor.UnpackData(message, ids)

for number, value in ((24, 4), (25, 1), (26, 7), (27, 2), (28, 1)):
    motor.Send_Parameter(number, value)     # A speed, B Iq, C position error; every 2nd loop; start now
motor.Send_data_pack_1(1000, 0, 0)          # the step: to position 1000
read_all(0.5)
motor.Send_Get_Parameter(32)                # how many samples
read_all(0.1)
count = motor.parameters.get(32, 0)
motor.Send_Buffer_Read(0, 0, count)         # kind 0, from sample 0
read_all(3.0)
for i in sorted(motor.capture):
    speed, iq, position_error = motor.capture[i]
    print(i, speed, iq, position_error)

Trigger 2 records up to an error instead: armed with a pre-trigger, it keeps the moments before a trip, the watchdog's included, and the time after it. The capture calls (Send_Parameter, Send_Get_Parameter, Send_Buffer_Read) need the Spectral-BLDC library 1.21 or newer.

Memory

The drive's microcontroller has 128 KB of flash, of which the bootloader takes 12 KB, and 20 KB of RAM. Firmware 109 uses about 91 % of the 116 KB application flash and 65 % of the RAM for fixed data, which leaves about 7 KB for the stack and the heap.

Parameter 83 (#Par 83, or Send_Get_Parameter(83)) is the margin check: the bytes of that RAM the stack has never reached since start-up. The stack needs about 1.5 to 2 KB; read parameter 83 after the drive has run its hardest work (a calibration, the encoder table, the anti-cogging, sound) and see that plenty is left.

A histogram

The histogram adds one signal into 256 bins over the electrical angle or over one motor turn, every control loop, until it is stopped or a bin holds 65535 samples (about 45 minutes): the mean per bin shows what repeats with the angle, such as the cogging current at a steady speed.

Parameter 35 picks the signal, 34 starts it (1 electrical angle, 2 motor turn) and stops it (0), 36 counts the samples, and Send_Buffer_Read with kind 1 reads the count and the sum of each bin. The anti-cogging identification uses it the same way; while it runs, parameters 34 and 35 refuse a write.

Comments


Found a mistake on this page? Edit it on GitHub · Report it · Get help · This page as Markdown · llms.txt · The whole manual as PDF