illumium.org

Главная › Блоги › Блог kayo

«Печенье с малиновым джемом» или чаепитие с Raspberry Pi

kayo — Втр, 30/04/2013 - 01:23

Raspberry Pi — весьма забавное устройство, с которым можно делать много интересного, прикладывая минимум усилий. У нас в распоряжении вполне зрелое для своего уровня железо со всевозможными интерфейсами (чип armv6t BCM2835), что вкупе с «родной» операционной системой Raspbian (порт Debian на официально не поддерживаемый ABI используемого процессора) делает устройство весьма привлекательным для реализации самых странных хотелок искушенного разработчика. Наибольший интерес представляют низкоуровневые интерфейсы, используемые в индустрии мобильных и встраиваемых систем: I2C, SPI, UART, а также несколько портов GPIO, которые можно использовать по своему усмотрению без всяких ограничений, как для простых операций состоянием сигналов, так и для эмуляции других интерфейсов, не поддерживаемых аппаратно используемым MCU.

Была задача сделать устройство, которое будет работать автономно долгое время без непосредственного вмешательства прочих сапиенсов, ну разве что за редким эпизодическим присутствием.

Доработка напильником

Многие низкоуровневые интерфейсы выведены на коннектор P1 (это тот, у которого больше всего ног на плате). Вся информация о выведенных портах MCU и выводах питания есть в вики. Удобно распечатать такой листик и надеть прямо на разъём, чтобы не перепутать, что куда подключать.

Аппаратные часы

Первая вещь, которой мне очень не хватало на малинке, — аппаратные часы. Казалось бы, чего стоило разработчику поставить самые стандартные копеечные часы на DS1307 с малюсенькой батарейкой непосредственно на плату. Но видимо не особо это нужно для той ЦА, на которую устройство ориентированно. Что ж, придётся доработать самим.

Часы с интерфейсом I2C я купил готовые на ebay самые дешевые на базе DS1307Z. На плате зачем-то ещё стоит AT24C32, это EEPROM на 32К, который тоже доступен по I2C, может вы придумаете, для чего его использовать?

Подключил стандартно (SDA1, SCL1 — это второй интерфейс шины I2C на MCU пи), запитка от 5V, а не 3.3V. Но что бы устройства корректно работали, пришлось выпаять лишние подтяжки на 3.3K, которые стояли на плате часов, ведь у нас уже есть на 1.5К в RPi.

Спасибо jfornango за то, что подсказал, как правильно воткнуть аппаратные часы программно:

# вычищаем фальшивые часы
sudo dpkg --purge fake-hwclock
sudo rm /etc/rcS.d/K0?hwclock.sh

# ставим инструменты I2C
sudo apt-get install i2c-tools

# загружаем нужные модули
sudo modprobe i2c-bcm2708
sudo modprobe i2c-dev
sudo modprobe rtc-ds1307

# можем увидеть нечто интересное тут
ls -al /sys/bus/i2c/devices/i2c-1

# проверяем видны ли устройства
sudo i2cdetect -y 1

# пробуем забиндить часы
sudo -s
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
exit

# пробуем читать время
sudo hwclock -r

# поставим правильное время
sudo hwclock -w

# теперь делаем часы перманентными
sudo nano /etc/modules
# добавляем модули:
i2c-bcm2708
i2c-dev
rtc-ds1307

# удаляем из черного списка эти модули, если они там есть
sudo nano /etc/modprobe.d/raspi-blacklist.conf

# фиксим сервис аппаратных часов
sudo nano /etc/init.d/hwclock
# в зависимости для запуска (Required-Start) добавляем kmod
# параметр X-Start-Before подчищаем, иначе будет конфликт

# перед стартом сервиса инициализируем устройство
sudo nano /etc/default/hwclock
# добавляем строку:
# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device

# вручную правим симлинки
cd /etc/rc0.d
sudo ln -s ../init.d/hwclock.sh K06hwclock.sh
cd ../rc6.d
sudo ln -s ../init.d/hwclock.sh K06hwclock.sh
cd ../rcS.d
sudo ln -s ../init.d/hwclock.sh S10hwclock.sh

# разрешаем сервис
sudo update-rc.d hwclock.sh enable

Если не удалить fake-hwclock, будет происходить нечто невероятное, что отъело у меня много времени.

Интерфейс 1-wire

Мне понадобилось подключить пучок термодатчиков от Dallas/Maxim DS18B20 в режиме паразитного питания. Интерфейс 1-wire на Raspberry Pi эмулируется bitbanging-ом на одном порту GPIO4. Вот что нам нужно сделать:

# загружаем модули
sudo modprobe w1-gpio
sudo modprobe w1-therm

# подключаем датчики и проверяем, видны ли они
ls /sys/bus/w1/devices

# должны увидеть что-то типа:
# 10-00080198b895 28-0000029fbfe8 w1_bus_master1
# первые два устройства — мои датчики
# последнее — контроллер шины

# пробуем считать данные
cat /sys/bus/w1/devices/10-00080198b895/w1_slave 
# увидим что-то вроде:
#   31 00 4b 46 ff ff 08 10 95 : crc=95 YES
#   31 00 4b 46 ff ff 08 10 95 t=85000
# измеренная температура 85°C для комнаты?
# это означает, что термометр не делал измерения
# поскольку датчики у меня подключены в режиме
# паразитного питания

Однако актуальное на момент написания ядро 3.6.11+ от 7 февраля 2013 не поддерживало режим паразитного питания, когда датчики при работе встроенного АЦП запитываются от сигнальной линии через резистор-подтяжку, когда нет обмена данными, и на ней высокий уровень.

Патч появился несколько позднее и активируется передачей модулю параметра pullup=1. Последняя сборка ядра находится здесь. Скрипт для автоматизированного обновления тут. После установки версии ядра с патчем, всё заработало, как надо:

# снова загружаем модули
sudo modprobe w1-gpio pullup=1
sudo modprobe w1-therm

# снова пробуем считать данные
cat /sys/bus/w1/devices/10-00080198b895/w1_slave 
# увидим что-то вроде:
#   31 00 4b 46 ff ff 08 10 95 : crc=95 YES
#   31 00 4b 46 ff ff 08 10 95 t=24250
# измеренная температура 24.25°C вполне адекватна

# прописываем модули в /etc/modules
# w1-gpio pullup=1
# w1-therm

IR пульт

Если уж развлекаться, то на полную. Валялся у меня без дела ИК-пульт от TV-тюннера вместе с приёмником на шнурке. Впору пристроить его к Pi в качестве основного девайса пользовательского ввода. Подключается это дело нехитро, у приёмника три вывода: земля, питание и сигнальный. На питание подадим 3.3V, а сигнальный подключим к GPIO18. Осталось настроить софт:

# устанавливаем lircd
sudo apt-get install lirc

# нам поругаются, что lirc не настроен
# всё в порядке, так и должно быть

# загружаем модуль
sudo modprobe lirc_rpi

# теперь можем послушать команды с пульта
sudo mode2 -d /dev/lirc0

# направляем пульт на приёмник и нажимаем кнопки
# смотрим, что к нам приходит

О да, Кэп, это морзянка.

# настраиваем lirc
sudo nano /etc/lirc/hardware.conf
# правим DRIVER="default"
# DEVICE="/dev/lirc0"
# MODULES="lirc_rpi"
# и LIRCD_ARGS="--uinput"
# также я раскомментировал
# START_LIRCMD=false
# потому что буду активировать режим мыши кнопкой

# находим подходящие конфиги под ваш пульт
# в /usr/share/lirc/remotes
# мне подошли avermedia/lircd.conf.avermedia98
# и avermedia/lircmd.conf.avermedia98 для мыши

# если готовых конфигов нет, можно нагенерить
# с помощью irrecord
irrecord -d /dev/lirc0 ~/lirc.conf

# сервис мыши запускаем при входе в сеанс
sudo nano /etc/X11/Xsession.d/99lircmd
# добавляем строки
killall lircmd
lircmd --uinput

# чтобы переключать мышь например кнопкой Autoscan
# добавляем в конфиг мыши TOGGLE_ACTIVATE * AUTOSCAN

# запускаем сервис
sudo service lirc start

# смотрим, правильно ли lirc распознаёт события
irw
# нажимаем кнопки и смотрим вывод

Доработка наждачкой

Ну и на закуску осталось немного подтюнить ОС.

Сторожевой таймер

Поскольку моё устройство будет трудиться вдали от заботливых сисадминских рук, мне понадобилось задействовать аппаратный watchdog, дабы в случае чего система помогла себе сама. Работает это просто как бревно: аппаратный счётчик инициализируется некоторым значением и отсчитывает назад, как только значение обнулится, произойдёт аппаратный сброс процессора. Чтобы этого не произошло, мы должны программно с приемлемым интервалом реинициализировать счетчик.

Функции watchdog таймера на Raspberry Pi реализованы модулем bcm2708_wdog. А использовать его мы будем посредством сервиса watchdog:

# ставим сервис
sudo apt-get install watchdog

# указываем используемый модуль
sudo nano /etc/default/watchdog
# меняем watchdog_module="none"
# на watchdog_module="bcm2708_wdog"

# указываем используемое устройство
sudo nano /etc/watchdog.conf
# раскомментируем строку:
# watchdog-device = /dev/watchdog

# убедимся, что сторожевой таймер запущен в режиме
# реального времени, иначе могут быть проблемы:
# realtime = yes
# priority = 1

# закомментируем строки, которые потенциально могут
# вызвать проблемы, вроде этой:
# pidfile = /var/run/syslogd.pid

# как видно, здесь ещё много чего интересного
# можно настроить, например реакцию на перегрузку
# (строки max-load-*)

# настраиваем модуль
sudo nano /etc/modprobe.d/watchdog.conf
# добавляем options bcm2708_wdog heartbeat=15
# параметр heartbeat указывает число секунд,
# которое должно пройти до аппаратного сброса

# перезапускаем сервис
sudo service watchdog restart

Итак, сторожевой таймер работает, но хотелось бы как-то убедиться в этом воочию. Есть много способов проверки:

  1. Форк-бомба. Цепная реакция с рекурсивным порождением дочерних процессов. Классическая реализация на Bash: (: (){ :|:& };:). Будет работать только если мы науськали нашего пса дергать сброс при перегрузке системы (раскомментировали строки max-load-* в конфиге). Если нет, можно попробовать запустить вочдог не в realtime и взорвать форк-бомбу, но должного эффекта придётся прилично подождать.
  2. Модуль panic.ko. Более действенный способ, если не лень собирать, сработает в любом случае, ибо «убъёт систему окончательно и бесповоротно» (шутка).
  3. Тупо убить процесс сервиса (sudo killall watchdog). В таком случае работа с устройством /dev/watchdog будет завершена некорректно, туда просто перестанут поступать сигналы реинициализации, и через указанные нами 15 секунд произойдёт аппаратный сброс. Ввиду своей лени этот способ я и применил. Сработало.

Ещё пара слов о watchdog. Модулю ядра можно передать параметр nowayout = 0, чтобы разрешить останавливать таймер, который уже однажды был запущен. По умолчанию nowayout = 1, можно подумать, что при остановке сервиса через какоето время сработает аппаратный сброс. На самом деле это не так, потому что при остановленном watchdog работает сервис wd_keepalive, который осуществляет реинициализацию таймера.

  • Разработка устройств
  • 1-wire
  • gpio
  • i2c
  • raspberry pi
  • Бортовой журнал Иллюмиума

Хочу добавить про часы.У меня

Алексей (не проверено) — Пт, 25/10/2013 - 18:13

Хочу добавить про часы.

У меня алгоритм почему-то не сработал. А помогло решение с сайта:
1.    Ставим инструменты I2C
sudo apt-get install i2c-tools

2.    Удаляем из черного списка модули i2c-bcm2708, i2c-dev, rtc-ds1307, если они там есть
sudo nano /etc/modprobe.d/raspi-blacklist.conf

3.    Правим скрипт hwclock.sh
sudo nano /etc/init.d/hwclock.sh

Добавляем в функцию hwclocksh() после строк
start)
            # If the admin deleted the hwclock config, create a blank
            # template with the defaults.
            if [ -w /etc ] && [ ! -f /etc/adjtime ] && [ ! -e /etc/adjtime ]; then
                printf "0.0 0 0.0\n0\nUTC" > /etc/adjtime
            fi
строку init_rtc_device и комментируем следующие 3 строки:

            init_rtc_device

        #   if [ -d /run/udev ] || [ -d /dev/.udev ]; then
        #       return 0
        #   fi
После функции hwclocksh() вставляем функцию
init_rtc_device()
{
  [ -e /dev/rtc0 ] && return 0;

  # load i2c and RTC kernel modules
  modprobe i2c-dev
  modprobe rtc-ds1307

  # iterate over every i2c bus as we're supporting Raspberry Pi rev. 1 and 2
  # (different I2C busses on GPIO header!)
  for bus in $(ls -d /sys/bus/i2c/devices/i2c-*);
  do
    echo ds1307 0x68 >> $bus/new_device;
    if [ -e /dev/rtc0 ];
    then
      log_action_msg "RTC found on bus `cat $bus/name`";
      break; # RTC found, bail out of the loop
    else
      echo 0x68 >> $bus/delete_device
    fi
  done
}

4.    разрешаем сервис hwclock и отключаем fake-hwclock
sudo update-rc.d fake-hwclock disable
sudo update-rc.d hwclock.sh enable

  • ответить

Очень рекомендую поставить

kayo — Вс, 27/10/2013 - 22:50

Очень рекомендую поставить systemd на Raspbian, скорость загрузки возрастёт прилично.

По поводу часов, в данный момент я использую udev правила для инициализации устройства и systemd скрипт для начальной установки системных часов с аппаратных.

/etc/udev/rules.d/80-ds1307.rules:

KERNEL=="i2c-1", SUBSYSTEM=="i2c-dev", ACTION=="add", PROGRAM="/bin/sh -c 'echo ds1307 0x68 > /sys/bus/i2c/devices/i2c-1/new_device'"
KERNEL=="i2c-1", SUBSYSTEM=="i2c-dev", ACTION=="remove", PROGRAM="/bin/sh -c 'echo 0x68 > /sys/bus/i2c/devices/i2c-1/delete_device'"

/etc/systemd/system/hwclockinit.service:

[Unit]
Description=Setup time from hardware clock

[Service]
Type=oneshot
ExecStartPre=/bin/sh -c 'while ! [ -e /dev/rtc0 ]; do sleep 1; done'
ExecStart=/sbin/hwclock -s

[Install]
WantedBy=basic.target

We used to be in Love…
  • ответить

Здравствуйте!В своей статье

Arty (не проверено) — Сб, 08/02/2014 - 05:43

Здравствуйте!

В своей статье Вы пишите: "Подключил стандартно (SDA1, SCL1 — это второй интерфейс шины I2C на MCU пи), запитка от 5V, а не 3.3V. Но что бы устройства корректно работали, пришлось выпаять лишние подтяжки на 3.3K, которые стояли на плате часов, ведь у нас уже есть на 1.5К в RPi."

Я нехорошо разбираюсь в схемотехнике и не хочу ничего испортить. На плате RTC находятся 4 резистора на 3.3 кОм. Они обведены красным (R2,R3) и зеленым (R1,R8) на фотографии:

http://upyourpic.org/images/201312/21ke6sec1v.jpg

В связи с этим у меня пара вопросов:

1. Правильно ли я понял, что нужно выпаивать только два резистора R2 и R3, обведенные красным цветом?

2. После выпаивания резисторов нужно ли закоротить контакты, к которым они были припаяны, или оставить как есть?

Спасибо!

  • ответить

У вас модуль работает в таком

kayo — Сб, 08/02/2014 - 19:41
У вас модуль работает в таком виде? Если нет, то надо выпаять те, которые стоят между линиями шины I2C и +3.3V питания. Видимо тока у портов RPi или чипа часов не хватает, чтобы до напряжения логического нуля дотягивать линии. Выпаять, коротить ничего не нужно. Честно, не помню какие именно резисторы, проще проверить по плате. Как вариант, можно выпаять подтяжки 1.5К на RPi.
We used to be in Love…
  • ответить

Недавно прикрутил часы,

Гость (не проверено) — Пнд, 07/04/2014 - 02:26

Недавно прикрутил часы, все нормально работало… Пока не запустил программу, использующую I2C (через библиотеку bcm2835). После первого запуска часы перестают работать. В смысле, через hwclock. При этом через библиотеку bcm2835 часы читаются и пишутся.

root@raspberrypi:/home/pi# hwclock
hwclock: ioctl(RTC_RD_TIME) to /dev/rtc0 to read the time failed
root@raspberrypi:/home/pi#

Восстанавливается только после перезагрузки. И до первого запуска моей проги.

Да, и i2cdetect перестает видеть устройства на шине. Все девайсы при этом нормально работают.

  • ответить

Очевидно, что библиотека

kayo — Пнд, 07/04/2014 - 11:29

Очевидно, что библиотека конфликтует с драйвером в ядре. Для того собственно и нужен драйвер, чтобы организовать совместную работу нескольких устройств на шине. А библиотека bcm2835 работает с MCU напрямую, поэтому я её не использую. В общем, вам нужно выбрать один из вариантов:

  1. Продолжать работать с библиотекой, обращаясь к часам напрямую в своём коде
  2. Работать с шиной посредством драйвера ядра i2c через /dev интерфейс
  3. Написать драйвер для своего устройства, работающий через драйвер i2c

Советую работать через ядро, в доке (Documentation/i2c/dev-interface) всё подробно описано.

We used to be in Love…
  • ответить

Спасибо за статью.На одной из

Zement (не проверено) — Пт, 16/05/2014 - 16:24

Спасибо за статью.

На одной из сборок Raspbian всё отлично встало (по статье). На сборке за январь 2014, при самой установке watchdog'а начали появляться ошибки выполнения конфигурации (хотя сам watchdog в системе появлялся). После правки конфигов, старта сервиса, и всяческих рестартов, проверок (форк_бомбами, или через 'killall watchdog') - результат был нулевой.

Помогли рекоммендации из последнего поста этой темы:

http://www.raspberrypi.org/forums/viewtopic.php?t=66059&p=515215

Возможно, кому-то пригодится.

  • ответить

Отправить комментарий

Содержимое этого поля является приватным и не будет отображаться публично.
  • Доступные HTML теги: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".

Подробнее о форматировании

CAPTCHA
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.
  _____     _   ____       _      _        
|___ | (_) | _ \ / \ | | ___
/ / | | | |_) | / _ \ | | / _ \
/ / | | | __/ / ___ \ | | | __/
/_/ _/ | |_| /_/ \_\ |_| \___|
|__/
Введите код, изображенный в стиле ASCII-арт.
RSS-материал

Навигация

  • Подшивки
  • Фотоальбомы

«Иллюмиум» на якоре.

Работает на Drupal, система с открытым исходным кодом.

(L) 2010, Illumium.Org. All rights reversed ^_~