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);
}
}