Drive.DC.H
H-bridge DC motor driver for the Drive.DC.H tile (rev a).
Embeds the TI DRV8214, a full H-bridge motor driver with integrated current sensing, stall detection, and voltage/speed regulation.
Examples
Quick start
#include "core_tiles.h"
tile_t motor;
tile_drive_dc_h_init(core_tiles_pal(&core_i2c3), 0, &motor, NULL);
if (tile_is_ready(&motor)) {
tile_drive_dc_h_forward(&motor); // drive forward
core_delay_ms(2000);
tile_drive_dc_h_brake(&motor); // slow-decay brake
}API reference
Initialization
tile_drive_dc_h_find
uint8_t tile_drive_dc_h_find(tiles_pal_t* hal, uint8_t instance)Check whether a DRV8214 is present on the I2C bus.
- hal
- Platform HAL handle
- instance
- Instance index (0-8, see mapping table)
Returns 1 if device ACKs, 0 otherwise
tile_drive_dc_h_init
void tile_drive_dc_h_init(tiles_pal_t* hal, uint8_t instance, tile_t* tile, const drive_dc_h_cfg_t *cfg)Verifies device presence, configures I2C bridge control in PWM mode, sets regulation parameters, and enables the output stage in coast state (motor not spinning). Call forward() or reverse() to start the motor.
- hal
- Platform HAL handle
- instance
- Instance index (0-8, see mapping table)
- tile
- Pointer to tile handle (populated by this function)
- cfg
- Optional config, or NULL for defaults
Lifecycle
tile_drive_dc_h_sleep
Studiovoid tile_drive_dc_h_sleep(tile_t* tile)Clears EN_OUT in CONFIG0. The device remains on the I2C bus and registers are accessible, but no current flows through the motor. OVP protection remains active in sleep.
- tile
- Pointer to tile handle
tile_drive_dc_h_wake
Studiovoid tile_drive_dc_h_wake(tile_t* tile)Sets EN_OUT in CONFIG0. The bridge returns to the last commanded state (coast/brake/forward/reverse).
- tile
- Pointer to tile handle
Runtime
tile_drive_dc_h_forward
Studiovoid tile_drive_dc_h_forward(tile_t* tile)Drive motor forward (OUT1=H, OUT2=L).
- tile
- Pointer to tile handle
tile_drive_dc_h_reverse
Studiovoid tile_drive_dc_h_reverse(tile_t* tile)Drive motor in reverse (OUT1=L, OUT2=H).
- tile
- Pointer to tile handle
tile_drive_dc_h_brake
Studiovoid tile_drive_dc_h_brake(tile_t* tile)Motor is actively held. Current recirculates through the low-side FETs, providing strong braking force.
- tile
- Pointer to tile handle
tile_drive_dc_h_coast
Studiovoid tile_drive_dc_h_coast(tile_t* tile)Motor freewheels. No braking force is applied. This is the initial state after init().
- tile
- Pointer to tile handle
tile_drive_dc_h_set_target
Studiovoid tile_drive_dc_h_set_target(tile_t* tile, uint8_t value)In voltage mode: sets target motor terminal voltage. With VM_GAIN_SEL=0: value * 15700/255 mV (61.6 mV/bit) With VM_GAIN_SEL=1: value * 3920/255 mV (15.4 mV/bit) In speed mode: sets target ripple speed. Target speed = value * W_SCALE rad/s.
- tile
- Pointer to tile handle
- value
- Target setpoint (0-255)
tile_drive_dc_h_get_fault
Studiouint8_t tile_drive_dc_h_get_fault(tile_t* tile)Contains FAULT[7], STALL[5], OCP[4], OVP[3], TSD[2], NPOR[1], CNT_DONE[0]. Use the DRV8214_FAULT_* masks to decode individual bits.
- tile
- Pointer to tile handle
Returns Raw fault byte (0 = no faults)
tile_drive_dc_h_clear_fault
Studiovoid tile_drive_dc_h_clear_fault(tile_t* tile)Sets CLR_FLT in CONFIG0. Clears FAULT, OCP, OVP, TSD, and NPOR bits. The CLR_FLT bit is self-clearing.
- tile
- Pointer to tile handle
tile_drive_dc_h_is_stalled
Studiouint8_t tile_drive_dc_h_is_stalled(tile_t* tile)Check if a motor stall condition is active.
- tile
- Pointer to tile handle
Returns 1 if STALL bit is set, 0 otherwise
tile_drive_dc_h_get_voltage_mv
Studiouint16_t tile_drive_dc_h_get_voltage_mv(tile_t* tile)Reads the VMTR register. The reading is proportional to the voltage across OUT1-OUT2 terminals. Valid while driving.
- tile
- Pointer to tile handle
Returns Motor voltage in mV (e.g. 3300 = 3.3 V)
tile_drive_dc_h_get_current_ma
Studiouint16_t tile_drive_dc_h_get_current_ma(tile_t* tile)Reads the IMTR register and converts using the current CS_GAIN_SEL setting. The reading reflects the current flowing through the low-side FETs during drive or brake.
- tile
- Pointer to tile handle
Returns Motor current in mA
tile_drive_dc_h_get_speed
Studiouint8_t tile_drive_dc_h_get_speed(tile_t* tile)Returns the raw SPEED register from the ripple counting algorithm. Value is proportional to motor speed but requires motor-specific calibration for RPM conversion.
- tile
- Pointer to tile handle
Returns Raw speed estimate (0-255)
tile_drive_dc_h_get_speed_rpm
Studiouint32_t tile_drive_dc_h_get_speed_rpm(tile_t* tile)Converts the chip's ripple-speed estimate to shaft RPM using the live W_SCALE setting and the configured ripples-per-rev, making it the exact inverse of the set_speed_rpm() target conversion. Accuracy depends on the motor profile (see set_motor_params()); without INV_R/KMC calibration the estimate is approximate.
- tile
- Pointer to tile handle
Returns Estimated shaft speed in revolutions per minute
tile_drive_dc_h_get_ripple_count
Studiouint16_t tile_drive_dc_h_get_ripple_count(tile_t* tile)Returns the total number of commutation ripples counted since the last clear. Proportional to rotor position.
- tile
- Pointer to tile handle
Returns Ripple count (0-65535)
tile_drive_dc_h_clear_ripple_count
Studiovoid tile_drive_dc_h_clear_ripple_count(tile_t* tile)Sets CLR_CNT in CONFIG0. Also clears CNT_DONE flag. The CLR_CNT bit is self-clearing.
- tile
- Pointer to tile handle
tile_drive_dc_h_set_speed_rpm
Studiovoid tile_drive_dc_h_set_speed_rpm(tile_t* tile, uint32_t rpm, drive_dc_h_direction_t direction)Switches the chip into speed-regulation mode (REG_CTRL=10b), writes WSET_VSET so the internal PI loop targets `rpm` for the given motor, and engages the bridge in `direction`. Returns immediately — the chip ramps the motor to the target speed autonomously and is_running() / get_speed() report progress.
- tile
- Initialised tile handle
- rpm
- Target shaft speed in revolutions per minute
- direction
- DRIVE_DC_H_DIR_FORWARD or DRIVE_DC_H_DIR_REVERSE
- The driver picks the finest W_SCALE (24/40/64/128) whose 8-bit WSET range still reaches the requested speed, so low targets get the best granularity the chip offers: the RPM step is `60 × W_SCALE / ripples_per_rev`, e.g. 120 RPM at ripples_per_rev=12 for targets below ~30 600 RPM. WSET is clamped at 0xFF for targets beyond the coarsest scale, and a nonzero request never rounds down to a stop.
- The conversion depends on the ripples-per-rev value from the init config (or set_motor_params()), and closed-loop accuracy depends on the ripple-counter calibration (INV_R, KMC) from `motor_mohm` / `kv_uv_per_rpm`. If those aren't set, speed regulation falls back to chip defaults and the RPM target is approximate. Provide a full motor profile — at init or via set_motor_params() — for accurate low-RPM control.
tile_drive_dc_h_move_distance
Studiovoid tile_drive_dc_h_move_distance(tile_t* tile, uint16_t ripples, drive_dc_h_direction_t direction)Closed-loop step: programs RC_THR for the requested ripple count, clears the ripple counter, engages the bridge in `direction`, then polls until either CNT_DONE fires or the motor stalls. On completion the bridge is put into slow-decay brake — the motor is actively held at the new position, not coasting.
- tile
- Initialised tile handle
- ripples
- Number of ripples to advance (0–65472)
- direction
- DRIVE_DC_H_DIR_FORWARD or DRIVE_DC_H_DIR_REVERSE
- This call BLOCKS until the move completes or the motor stalls. Worst-case wall-time depends on motor speed + load; budget accordingly. There is no built-in timeout beyond the chip's own stall detector — use a separate watchdog or @ref tile_drive_dc_h_wait_for_stop with a timeout if you need a hard upper bound.
- On completion the bridge is left in BRAKE (slow decay, both low-side FETs on). Call @ref tile_drive_dc_h_coast afterwards if you'd rather let the motor freewheel.
- Ripple counts are coarse (integer commutation ticks, not encoder counts). Resolution = 1/ripples_per_rev of a revolution — typically 1/12 turn. Don't expect sub-degree positioning.
tile_drive_dc_h_is_running
Studiouint8_t tile_drive_dc_h_is_running(tile_t* tile)Returns 1 when the bridge is in forward or reverse drive (any non-zero, non-brake combination of IN1/IN2 in I²C bridge mode). Returns 0 when braking, coasting, sleeping, in pad-control mode, or not yet ready.
- tile
- Initialised tile handle
Returns 1 if driving, 0 otherwise
tile_drive_dc_h_wait_for_stop
Studiouint8_t tile_drive_dc_h_wait_for_stop(tile_t* tile, uint32_t timeout_ms)Polls the 16-bit ripple counter at ~10 ms cadence. Returns 1 when two successive samples (≥30 ms apart) report the same count — i.e., the rotor is mechanically stationary. Returns 0 if `timeout_ms` elapses first. Useful after @ref tile_drive_dc_h_brake when you want to know the motor has actually settled rather than just "the bridge has been commanded to brake".
- tile
- Initialised tile handle
- timeout_ms
- Maximum time to wait, in milliseconds
Returns 1 if the rotor settled before timeout, 0 on timeout
Config
tile_drive_dc_h_set_control_mode
Studiovoid tile_drive_dc_h_set_control_mode(tile_t* tile, drive_dc_h_control_mode_t mode)In I²C mode (default after init), forward/reverse/brake/coast control the bridge. In either pad-control mode, the chip ignores I²C bridge bits and tracks pads 2/3 directly: - PAD_PHEN — pad 2 = EN (PWM), pad 3 = PH (direction) - PAD_IN1IN2 — pad 2 = IN1, pad 3 = IN2 (independent half-bridges) Monitoring (voltage, current, fault, ripple count) keeps working over I²C in all modes. Switching to a pad mode disables I²C bridge calls (forward/reverse/etc) — they'll log an error and no-op.
- tile
- Pointer to tile handle
- mode
- Bridge control source (DRIVE_DC_H_CTRL_*)
tile_drive_dc_h_set_regulation_mode
Studiovoid tile_drive_dc_h_set_regulation_mode(tile_t* tile, drive_dc_h_reg_mode_t mode)Writes REG_CTRL bits in REG_CTRL0. After switching, set_target() is interpreted in the new loop's units (voltage code, speed code, etc.). Speed mode requires ripple counting to be enabled — the driver automatically sets EN_RC=1 when SPEED is selected.
- tile
- Pointer to tile handle
- mode
- Regulation mode (DRIVE_DC_H_REG_*)
tile_drive_dc_h_set_current_regulation_mode
Studiovoid tile_drive_dc_h_set_current_regulation_mode(tile_t* tile, drive_dc_h_imode_t mode)Selects when the chip's internal current loop folds back to keep motor current under the ITRIP threshold. ITRIP itself is set by the combination of CS_GAIN_SEL (set_current_sense_gain) and the internal 500 mV VREF (INT_VREF=1, fixed by this driver since the external VREF pin isn't routed on the Drive.DC.H tile).
- tile
- Pointer to tile handle
- mode
- Current regulation mode (DRIVE_DC_H_IMODE_*)
tile_drive_dc_h_set_current_sense_gain
Studiovoid tile_drive_dc_h_set_current_sense_gain(tile_t* tile, uint8_t code)Programs CS_GAIN_SEL[2:0] in RC_CTRL0. Lower max-current ranges give finer current resolution but lower R_DS(on) headroom; higher ranges support larger motors but coarser get_current_ma() steps. Codes: 0 = 4 A, 1 = 2 A, 2 = 1 A, 3 = 0.5 A, 4 = 0.25 A, 5 = 0.125 A Also affects ITRIP when current regulation is enabled.
- tile
- Pointer to tile handle
- code
- CS_GAIN_SEL code (0-5)
tile_drive_dc_h_set_stall_enabled
Studiovoid tile_drive_dc_h_set_stall_enabled(tile_t* tile, uint8_t enabled)Toggles EN_STALL in CONFIG0. When disabled, the STALL bit in the fault register won't latch and is_stalled() always returns 0. Useful while tuning the inrush time for a new motor.
- tile
- Pointer to tile handle
- enabled
- 1 = stall detection on, 0 = off
tile_drive_dc_h_set_inrush_time_ms
Studiovoid tile_drive_dc_h_set_inrush_time_ms(tile_t* tile, uint16_t ms)Programs CONFIG1/CONFIG2 with a 16-bit count of 102.4 µs ticks, giving up to ~6.7 s. During the blanking window after a drive command, the stall detector ignores motor current — necessary because real motors draw several × steady-state during startup. Tune for the slowest motor you want to drive.
- tile
- Pointer to tile handle
- ms
- Inrush blanking time in milliseconds (0 - 6710)
tile_drive_dc_h_set_stall_recovery
Studiovoid tile_drive_dc_h_set_stall_recovery(tile_t* tile, drive_dc_h_stall_recovery_t mode)In LATCH mode, hitting a stall turns the bridge off until either clear_fault() is called or the chip is power-cycled. In REPORT mode the chip flags STALL but keeps driving — useful for haptics or actuators that legitimately stall against an end-stop.
- tile
- Pointer to tile handle
- mode
- DRIVE_DC_H_STALL_LATCH or DRIVE_DC_H_STALL_REPORT
tile_drive_dc_h_set_ripple_threshold
Studiovoid tile_drive_dc_h_set_ripple_threshold(tile_t* tile, uint16_t count)The chip raises CNT_DONE when the running ripple count reaches (count × scale). Useful for "rotate N counts then stop" patterns: watch the CNT_DONE bit in get_fault(), then call coast(). Internal threshold is 10-bit; the driver picks the smallest scale (×2, ×8, ×16, or ×64) that fits `count`.
- tile
- Pointer to tile handle
- count
- Threshold count (0 - 65472, larger = coarser scale)
tile_drive_dc_h_set_ripple_filter_gain
Studiovoid tile_drive_dc_h_set_ripple_filter_gain(tile_t* tile, uint8_t code)Programs FLT_GAIN_SEL[1:0] in RC_CTRL0. Scales the magnitude of detected ripples before the counter — increase if get_ripple_count() undercounts, decrease if it spuriously counts noise. Codes: 0 = ×2, 1 = ×4 (default), 2 = ×8, 3 = ×16
- tile
- Pointer to tile handle
- code
- FLT_GAIN_SEL code (0-3)
tile_drive_dc_h_set_motor_params
Studiovoid tile_drive_dc_h_set_motor_params(tile_t* tile, uint16_t motor_mohm, uint16_t ripples_per_rev, uint16_t kv_uv_per_rpm)Writes the DRV8214's ripple-counter calibration registers (INV_R, KMC and their scale fields) from physical motor parameters, and caches ripples-per-rev for the set_speed_rpm()/get_speed_rpm() conversions. Equivalent to supplying `motor_mohm`, `ripples_per_rev` and `kv_uv_per_rpm` in the init config — use this when the driver was initialised with defaults (e.g. from Studio) and you want accurate closed-loop speed control. Example (RS PRO 834-7644, direct drive): motor_mohm=6000, ripples_per_rev=12, kv_uv_per_rpm=187. chip defaults (no-op for INV_R/KMC). (poles × brush pairs; common: 3, 5, 6, 7, 12). 0 = default (12); clamped to 255. motor: 100-2000). 0 = skip KMC tuning.
- tile
- Initialised tile handle
- motor_mohm
- Winding resistance in milliohms. 0 = leave
- ripples_per_rev
- Commutation ripples per shaft revolution
- kv_uv_per_rpm
- Back-EMF constant in µV/RPM (typical small
Advanced
Driver gaps · 1
Chip capabilities this driver doesn’t expose yet.
Enums
drive_dc_h_direction_t
Drive direction for the tier-2 helpers.
- DRIVE_DC_H_DIR_FORWARD
- OUT1=H, OUT2=L (matches forward()).
- DRIVE_DC_H_DIR_REVERSE
- OUT1=L, OUT2=H (matches reverse()).
Constants
| TILE_DRIVE_DC_H_VERSION_MAJOR | 4 | |
| TILE_DRIVE_DC_H_VERSION_MINOR | 2 | |
| TILE_DRIVE_DC_H_VERSION_PATCH | 0 | |
| DRV8214_I2C_ADDR_DEFAULT | 0x34 | |
| DRV8214_CONFIG3_DEFAULT | 0x63 | Expected CONFIG3 register value at power-on. |
| DRV8214_FAULT_FAULT | 0x80 | Bit 7 — any fault active |
| DRV8214_FAULT_STALL | 0x20 | Bit 5 — motor stall |
| DRV8214_FAULT_OCP | 0x10 | Bit 4 — overcurrent |
| DRV8214_FAULT_OVP | 0x08 | Bit 3 — overvoltage |
| DRV8214_FAULT_TSD | 0x04 | Bit 2 — thermal shutdown |
| DRV8214_FAULT_NPOR | 0x02 | Bit 1 — power-on reset |
| DRV8214_FAULT_CNT_DONE | 0x01 | Bit 0 — ripple count done |
| DRIVE_DC_H_MODE_VOLTAGE | 0 | |
| DRIVE_DC_H_MODE_SPEED | 1 | |
| DRIVE_DC_H_MODE_RIPPLE_COUNT | 2 | |
| DRIVE_DC_H_MODE_PAD_PHEN | 3 | |
| DRIVE_DC_H_MODE_PAD_IN1IN2 | 4 |

