Grettings.
I’m having troubles trying to set my IMX6ULL to working with one-wire protocol; using same pin to send and receive signals.
Particularly i want to control temperature sensor DS18S20, but i cant get it to do the “initialization procedure”, which consists in sending a pulse to the sensor and then receive the “acknowledge” signal from it.
I’m using colibri IMX6ULL WB 512 (core image minimal 5.7.2-devel-20230726155409+build) with a custom board, where i set pin SODIMM 137 to the sensor:
In initialization procedure i send the module a low signal for 480us and then i change the pin setting to “in”, and that’s where i can’t get the presence pulse from the sensor.
I sensed the pin with an oscilloscope and definetly the sensor works fine, therefore i’m able to see the low signal, but in my C program the logic level never changes.
This low signal lasts for about 50 us, but once i set the pin config to “in” im not able to detect any change.
Maybe it has something to do with the pin config itself, i’ve tried with pull-up/down config, CMOS /Schmitt Trigger in, but nothing changes (sensor datasheet says that sensor output is an opendrain with a pullup resistor). I also tried to set other pin to just “in” config and connected to the sensor to see if that was the problem but once again it didn’t work.
I would like some advices in what i should look at here, thank you!
Please check regarding SNVS pad you are using. Pinctrl groups can either contain SNVS or non-SNVS pads, but not the mix of SNVS and non-SNVS pads. SNVS pinctrl group can belong only to iomuxc_snvs, and not to iomuxc.
If using two pads connected together, then configure output one as open drain, so that you don’t need to change IO direction.
And the pin works fine it’s just i can’t get to detect that pulse. (By the way i tried all the combinations between open drain/cmos and schimitt trigger.
In Linux, especially on 6ULL, everything shorter than 10ms is hard real time. Shorter than 2ms is extreme real time. Are you kidding catching 50us pulse in bash script? I didn’t time sleep 0 call, but I guess it is longer than 50us when lucky to hit I-cache.
Perhaps you could solve it with C and libgpiod, but even for C it is challenging and not guaranteed due to Linux nature. Use external MCU or perhaps upgrade to iMX7 with real time M4 code on the same chip.
Have you ever built an image using this documentation? The libgpiod is available on Yocto as a package by default on the BSP 5 layers, you can find it below:
Daniel, i managed to run libgpiod by flashing the image every time i wanted to make some change to my C program. Anyways, i wasn’t able to detect any change of edge.
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: gpio-event <CHIP-NAME> <OFFSET>\n");
return EXIT_FAILURE;
}
const char *chip_name = argv[1];
int offset = atoi(argv[2]);
struct gpiod_line *line = get_gpio_line(chip_name, offset);
if (!line) {
return EXIT_FAILURE;
}
set_line_mode(line, GPIOD_LINE_ACTIVE_STATE_HIGH);
struct timespec start_time;
clock_gettime(CLOCK_MONOTONIC, &start_time);
// Espera 500 ms
usleep(RETARDO_MS);
gpiod_line_set_value(line, 0);
wait_microseconds(RETARDO_US);
gpiod_line_release(line);
line = get_gpio_line(chip_name, offset);
if (!line) {
return EXIT_FAILURE;
}
if (gpiod_line_request_both_edges_events(line, "gpio-event") < 0) {
perror("Error al configurar la línea GPIO");
gpiod_line_release(line);
return EXIT_FAILURE;
}
struct gpiod_line_event event;
struct timespec end_time;
while (1) {
gpiod_line_event_wait(line, NULL);
if (gpiod_line_event_read(line, &event) == 0) {
clock_gettime(CLOCK_MONOTONIC, &end_time);
long elapsed_time_ns = (end_time.tv_sec - start_time.tv_sec) * 1000000000 + (end_time.tv_nsec - start_time.tv_nsec);
if (event.event_type == GPIOD_LINE_EVENT_RISING_EDGE) {
printf("Flanco de subida detectado. Tiempo transcurrido: %ld ns.\n", elapsed_time_ns);
} else if (event.event_type == GPIOD_LINE_EVENT_FALLING_EDGE) {
printf("Flanco de bajada detectado. Tiempo transcurrido: %ld ns.\n", elapsed_time_ns);
}
}
}
gpiod_line_release(line);
return EXIT_SUCCESS;
}
Maybe the only way to get this running would be to writing a specific C driver for the sensor?
As mentioned by @Edward , obtaining accurate timings for these sensors can be challenging on the userspace side. With that in mind, I believe that libgpiod may not provide the necessary support to achieve your desired result.
Considering this, the most straightforward alternative would likely involve using a kernel driver. You can find the w1_therm.c driver, which appears to support the sensor you’re working with. Additionally, you can access relevant documentation here. I recommend implementing this driver and assessing whether it meets your requirements.
If you have any further questions, please don’t hesitate to reach out.