Go 1,12 Linux 4.19.93 armv6l
. Аппаратное обеспечение - это расперипи ноль Вт (BCM2835) с изображением yocto linux.
У меня есть датчик приближения SRF04, управляемый gpio, управляемый драйвером srf04 linux.
Работает отлично подходит для sysfs и оболочки busybox.
# cat /sys/bus/iio/devices/iio:device0/in_distance_raw
1646
Ранее я использовал Go с устройствами IIO, которые поддерживают триггеры и буферизованный вывод с высокой частотой дискретизации на этой аппаратной платформе. Однако для этого приложения драйвер srf04 не реализует эти функции IIO. Убирайся. Мне не очень хочется добавлять поддержку буфера / триггера к самому драйверу (в настоящее время), поскольку мне не нужна «высокая» частота дискретизации. Горстка пингов в секунду должно быть достаточно для моей цели. Я полагаю, я вычислю среднее и стандартное. девиация для скользящего окна точек данных и «божественного» сигнала из шума.
Итак, я был бы совершенно счастлив прочитать байты из опубликованного файла sysfs с помощью Go.
Что подводит меня к сути этого поста. Когда я открываю файл для чтения и пытаюсь прочитать () любое количество байтов, я всегда получаю общую ошибку c -EIO
.
func (s *Srf04) Read() (int, error) {
samp := make([]byte, 16)
f, err := os.OpenFile(s.readPath, OS.O_RDONLY, os.ModeDevice)
if err != nil {
return 0, err
}
defer f.Close()
n, err := f.Read(samp)
if err != nil {
// This block is always executed.
// The error is never a timeout, and always 'input/output error' (-EIO aka -5)
log.Fatal(err)
}
...
}
Это похоже на странное поведение для меня. Поэтому я решил возиться с использованием io.ReadFull
. Это дало ненадежные результаты.
func (s *Srf04) Read() (int, error) {
samp := make([]byte, 16)
f, err := os.OpenFile(s.readPath, OS.O_RDONLY, os.ModeDevice)
if err != nil {
return 0, err
}
defer f.Close()
for {
n, err := io.ReadFull(readFile, samp)
log.Println("ReadFull ", n, " bytes.")
if err == io.EOF {
break
}
if err != nil {
log.Println(err)
}
}
...
}
Я закончил тем, что добавил его в al oop, так как обнаружил изменения в поведении от одноразовых операций чтения к нескольким вызовам чтения после друг друга. У меня есть выход, если он получает EOF, и неоднократно пытаюсь читать иначе.
Результаты - безумные, ненадежные, казалось бы, возвращающие случайные результаты. Иногда я получаю -5, иногда я читаю от 2 до 5 байт с устройства. Иногда я получаю байты без файла eof перед EOF. Байты, по-видимому, представляют символьные данные для чисел (каждая руна - это руна между [0-9]) - что я и ожидал.
В сторону: я ожидаю, что это связано с опросом файлов и go блокирование реализации ввода-вывода, но я не могу точно сказать.
В качестве временного решения я решил попробовать использовать os.exe c, и теперь я получаю результаты, которые ожидаю увидеть.
func (s *Srf04)Read() (int, error) {
out, err := exec.Command("cat", s.readPath).Output()
if err != nil {
return 0, err
}
return strconv.Atoi(string(out))
}
Но Йик. os.exec
. Тьфу.