From d94e8ba0bc7d2646980a111d126b23308ab2d90f Mon Sep 17 00:00:00 2001 From: YoungSoo Shin Date: Wed, 2 Jul 2025 10:16:15 +0900 Subject: [PATCH] ODROID-C5: analog: fix for ODROID-C5 ODROID-C5 has two internal 10bit ADCs. However, the value of in_voltage0_raw outputs a difficult number. So, klipper read "in_voltage0_input", which outputs the actual voltage value, to read the value of ADC. The iio device file, The read speed of "in_voltage0_input" is very slow. This will adversely affect the stepper motor operation and result in a "Stepper too far in past" error. Read the value of Voltage0_raw and calculate the ADC voltage directly in the klipper. Change-Id: I293cbdf8d1f54efe50ab89729a9908eb598820b6 --- src/linux/Makefile | 5 +- src/linux/analog_odroidc5.c | 102 ++++++++++++++++++++++++++++++++++++ src/linux/gpio.h | 5 ++ 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/linux/analog_odroidc5.c diff --git a/src/linux/Makefile b/src/linux/Makefile index 7c1de7c1..1c41c856 100644 --- a/src/linux/Makefile +++ b/src/linux/Makefile @@ -3,10 +3,13 @@ dirs-y += src/linux src/generic src-y += linux/main.c linux/timer.c linux/console.c linux/watchdog.c -src-y += linux/pca9685.c linux/spidev.c linux/analog.c linux/hard_pwm.c +src-y += linux/pca9685.c linux/spidev.c linux/hard_pwm.c src-y += linux/i2c.c linux/gpio.c generic/crc16_ccitt.c generic/alloc.c src-y += linux/sensor_ds18b20.c +src-$(CONFIG_MACH_LINUX_DEFAULT) += linux/analog.c +src-$(CONFIG_MACH_LINUX_ODROIDC5) += linux/analog_odroidc5.c + CFLAGS_klipper.elf += -lutil -lrt -lpthread flash: $(OUT)klipper.elf diff --git a/src/linux/analog_odroidc5.c b/src/linux/analog_odroidc5.c new file mode 100644 index 00000000..94c97347 --- /dev/null +++ b/src/linux/analog_odroidc5.c @@ -0,0 +1,102 @@ +// Read analog values from Linux IIO device +// +// Copyright (C) 2017 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include // open +#include // snprintf +#include // atoi +#include // read +#include "command.h" // shutdown +#include "gpio.h" // gpio_adc_setup +#include "internal.h" // report_errno +#include "sched.h" // sched_shutdown + +// ODROID-C5 +DECL_CONSTANT("ADC_MAX", 1800); + +#define ANALOG_START (1<<12) + +DECL_ENUMERATION_RANGE("pin", "analog0", ANALOG_START, 8); + +// ODROID-C5 +#define IIO_PATH "/sys/bus/iio/devices/iio:device0/in_voltage0_raw" +#define SCALE_PATH "/sys/bus/iio/devices/iio:device0/in_voltage_scale" +#define OFFSET_PATH "/sys/bus/iio/devices/iio:device0/in_voltage_offset" + +struct gpio_adc +gpio_adc_setup(uint32_t pin) +{ + struct gpio_adc g; + int fd; + char buf[64]; + int ret; + + fd = open(SCALE_PATH, O_RDONLY); + ret = read(fd, buf, sizeof(buf)-1); + if (ret <= 0) { + goto fail; + } + buf[ret] = '\0'; + g.scale = atof(buf) * 1000; + close(fd); + + fd = open(OFFSET_PATH, O_RDONLY); + ret = read(fd, buf, sizeof(buf)-1); + if (ret <= 0) { + goto fail; + } + buf[ret] = '\0'; + g.offset = atoi(buf); + close(fd); + + fd = open(IIO_PATH, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + report_errno("analog open", fd); + goto fail; + } + ret = set_non_blocking(fd); + if (ret < 0) + goto fail; + + g.fd = fd; + return g; +fail: + if (fd >= 0) + close(fd); + shutdown("Unable to open adc device"); +} + +uint32_t +gpio_adc_sample(struct gpio_adc g) +{ + return 0; +} + +uint16_t +gpio_adc_read(struct gpio_adc g) +{ + char buf[64]; + int voltage; + int ret = pread(g.fd, buf, sizeof(buf)-1, 0); + if (ret <= 0) { + report_errno("analog read", ret); + try_shutdown("Error on analog read"); + return 0; + } + buf[ret] = '\0'; + + voltage = atoi(buf) + g.offset; + voltage = voltage > 0 ? voltage : 0; + voltage = voltage * g.scale; + voltage = voltage < 1800000 ? voltage : 1800000; + voltage /= 1000; + + return voltage; +} + +void +gpio_adc_cancel_sample(struct gpio_adc g) +{ +} diff --git a/src/linux/gpio.h b/src/linux/gpio.h index d72007c2..cf9a4043 100644 --- a/src/linux/gpio.h +++ b/src/linux/gpio.h @@ -1,6 +1,7 @@ #ifndef __LINUX_GPIO_H #define __LINUX_GPIO_H +#include "autoconf.h" // CONFIG_MACH_LINUX_* #include // uint8_t struct gpio_out { @@ -20,6 +21,10 @@ void gpio_in_reset(struct gpio_in g, int8_t pull_up); uint8_t gpio_in_read(struct gpio_in g); struct gpio_adc { +#ifdef CONFIG_MACH_LINUX_ODROIDC5 + int scale; + int offset; +#endif int fd; }; struct gpio_adc gpio_adc_setup(uint32_t pin);