CH201 Failing on Frequency Lock (STM32)

By liamrobinsonqu… , 27 May 2025

Hi all,

I'm integrating the CH201 (Shasta) ultrasonic sensor using SonicLib v3.24.0 on an STM32H757 with a custom board and BSP. I can successfully detect and program the sensor on the first attempt, but frequency lock always fails, even after multiple retries by the driver.

What I’ve tried
Using both invn.smartsonic.str-example.2.7.0 and invn.chirpmicro.smartsonic.chx01-hellochirp-example.2.31.0

Manually pulsing INT line high for 100 ms (before and after reset)

Verified that chbsp_program_enable(), chbsp_reset_assert(), and chbsp_reset_release() toggle the correct STM32 GPIOs

Confirmed chbsp_board_init() and chdrv_group_detect_and_program() complete successfully the first time

I2C comms remain functional throughout — I can read device registers, and ch_get_num_ports() correctly returns 1

On first boot:

Sensor enters bootloader

RAM init + firmware upload succeed

Device responds to I2C and changes address

But then:

chdrv_group_wait_for_lock() fails (returns CH_ERR_TIMEOUT)

Debug:`
Hello Chirp! - Chirp SonicLib Example Application
Compile time: May 27 2025 16:56:49
SonicLib version: 3.24.0

CH201: FOUND

Group initialized with 1 port(s)

Number of ultrasonic devices connected: 1

Number of ultrasonic devices connected: 1
Test I2C read: 020A

PROG_STAT: 0x05

chdrv_init_ram

Loading RAM init data...

Wrote 28 bytes in 1 ms.

chdrv_write_firmware

Programming sensor...

Wrote 2048 bytes in 6 ms.

Changing I2C address to 41

Sensor count: 1, 44 ms.
Chirp sensor initialized on I2C addr 0:41

Sensor hu initialization timed out or missing

Frequency lock failed`

Here is my code used from the main.c example in invn.smartsonic.str-example.2.7.0

int ch201_test(c_i2c & i2c_ch) {

uint8_t ret = 0;
// uint8_t chirp_error = 0;
uint8_t num_ports;
uint8_t dev_num;

// Setup extended group
chirp_group.i2c = &i2c_ch;

// Get pointer to the ch_group_t part
ch_group_t *grp_ptr = &chirp_group.group;

// Set the group pointer on each device (important!)
for (int i = 0; i < CHIRP_MAX_NUM_SENSORS; i++) {
grp_ptr->device[i]->group = grp_ptr;
}

/* Initialize board hardware functions
* This call to the board support package (BSP) performs all necessary
* hardware initialization for the application to run on this board.
* This includes setting up memory regions, initializing clocks and
* peripherals (including I2C and serial port), and any processor-specific
* startup sequences.
*
* The chbsp_board_init() function also initializes fields within the
* sensor group descriptor, including number of supported sensors and
* the RTC clock calibration pulse length.
*
*/

// Basic group pointer setup and scanning I2C bus for sensors
// chbsp_board_init(grp_ptr);

printf("\r\nHello Chirp! - Chirp SonicLib Example Application");
printf("\r\n Compile time: %s %s", __DATE__, __TIME__);
printf("\r\n SonicLib version: %u.%u.%u", SONICLIB_VER_MAJOR, SONICLIB_VER_MINOR, SONICLIB_VER_REV);
printf("\r\n");

chbsp_board_init(grp_ptr);
grp_ptr->num_ports = CHIRP_MAX_NUM_SENSORS; // Explicitly setting the number of ports
num_ports = grp_ptr->num_ports;
printf("\r\nGroup initialized with %u port(s)", grp_ptr->num_ports);

// num_ports = ch_get_num_ports(grp_ptr);

for (dev_num = 0; dev_num < num_ports; dev_num++) {
ch_dev_t *dev_ptr = &(chirp_devices[dev_num]);
ret |= ch_init(dev_ptr, grp_ptr, dev_num, CHIRP_SENSOR_FW_INIT_FUNC);
}

printf("\r\nSet grp_ptr->num_ports = %u", grp_ptr->num_ports);

chbsp_group_set_int1_dir_out(grp_ptr);
// pulse low→high for 100 ms
chbsp_group_int1_set(grp_ptr);
chbsp_delay_ms(grp_ptr->rtc_cal_pulse_ms); // your 100 ms
chbsp_group_int1_clear(grp_ptr);
chbsp_group_set_int1_dir_in(grp_ptr);
chbsp_group_int1_interrupt_enable(grp_ptr);

ret = ch_group_start(grp_ptr);

ch_dev_t *dev_ptr = ch_get_dev_ptr(grp_ptr, 0);
for (dev_num = 0; dev_num < num_ports; dev_num++) {
if (ch_sensor_is_connected(dev_ptr)) {
uint16_t part_num = ch_get_part_number(dev_ptr);
uint32_t freq = ch_get_frequency(dev_ptr);
uint16_t rtc_cal = ch_get_rtc_cal_result(dev_ptr);
uint16_t rtc_pulselength = ch_get_rtc_cal_pulselength(dev_ptr);
const char * p_fw_version = ch_get_fw_version_string(dev_ptr);
}
}

ch_io_int_callback_set(grp_ptr, sensor_int_callback_dummy);
ch_io_complete_callback_set(grp_ptr, io_complete_callback_dummy);

for (dev_num = 0; dev_num < num_ports; dev_num++) {
ch_config_t dev_config;
if (ch_sensor_is_connected(dev_ptr)) {
num_connected_sensors++;
active_devices |= (1 << dev_num);
if (num_connected_sensors == 1) {
dev_config.mode = CHIRP_FIRST_SENSOR_MODE;
} else {
dev_config.mode = CHIRP_OTHER_SENSOR_MODE;
}
if (dev_config.mode != CH_MODE_FREERUN) {
num_triggered_devices++;
}
dev_config.max_range = CHIRP_SENSOR_MAX_RANGE_MM;
dev_config.static_range = CHIRP_SENSOR_STATIC_RANGE;
if (dev_config.mode == CH_MODE_FREERUN) {
dev_config.sample_interval = MEASUREMENT_INTERVAL_MS;
} else {
dev_config.sample_interval = 0;
}
if (ch_get_part_number(dev_ptr) == CH201_PART_NUMBER) {
dev_config.thresh_ptr = &chirp_ch201_thresholds;
} else {
dev_config.thresh_ptr = 0;
}
ret = ch_set_config(dev_ptr, &dev_config);
if ((!ret) && (dev_config.mode == CH_MODE_FREERUN)) {
chbsp_set_int1_dir_in(dev_ptr);
chbsp_int1_interrupt_enable(dev_ptr);
}
if (!ret) {
chbsp_led_on(dev_num);
}
}
}

ch_set_rx_pretrigger(grp_ptr, RX_PRETRIGGER_ENABLE);

if (num_triggered_devices > 0) {
chbsp_periodic_timer_init(MEASUREMENT_INTERVAL_MS, periodic_timer_callback_dummy);
chbsp_periodic_timer_irq_enable();
chbsp_periodic_timer_start();
}

while(1) {
if (taskflags == 0)
chbsp_proc_sleep();

if (taskflags & DATA_READY_FLAG) {
taskflags &= ~DATA_READY_FLAG;
handle_data_ready(grp_ptr);
}

if (num_io_queued != 0) {
ch_io_start_nb(grp_ptr);
num_io_queued = 0;
}
if (taskflags & IQ_READY_FLAG) {
taskflags &= ~IQ_READY_FLAG;
handle_iq_data_done(grp_ptr);
}
}

phpbb Topic ID
51060