gpio i2c

Подключаем датчик температуры к шине данных i2c

i2c - шина данных для обмена информацией между устройствами. Представлена двумя линиями - линия данных SDA (второй вывод в колодке GPIO) и тактовая линия SCL (третий вывод в колодке GPIO).  

Как передаются данные по i2c на электрическом уровне я описывать не буду, это всё можно прочитать в гугле, поэтому перейдём сразу к практической части. Нам потребуется  чип датчика температуры LM75A:

Поскольку чип выполнен в очень неудобном для домашнего использования форм-факторе soic-8 (очень мелкий), то нам также потребуется переходник на DIP-8,

чтобы можно было сделать проводное соединение с  Raspberry Pi. Припаиваем чип к переходнику. Линии SDA и SCL необходимо подтянуть резисторами 1кОм к питанию.В итоге конструкция должна выглядеть примерно так:

Я использовал Raspbian по 2 причинам:

1. В дистрибутив включены i2c драйвера в виде модулей ядра, которые остаётся лишь подгрузить командой modprobe

2. в репозитории есть i2c-tools, которые нам потребуются для работы с датчиком температуры Итак, подгружаем модули ядра, которые позволят нам работать с i2c:

sudo modprobe i2c-dev

sudo modprobe i2c-bcm2708

Устанавливаем i2c-tools из репозитория: sudo apt-get install i2c-tools

В i2c-tools входят следующие утилиты:

i2cdetect - для определения устройств, подключенных к шине i2c

i2cget - для чтения данных из регистров подключенных устойств

i2cset - запись данных в регистры подключённых устройств

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

i2c-detect -l

Если в выводе команды отобразились доступные шины i2c (i2c-0, i2c-1), то значит можно двигаться дальше.

Будем работать с i2c-0. Подключим датчик температуры к линиям SDA0 и SCL0,  5V питания и GND для датчика также будем брать с колодки GPIO.

Если датчик правильно подключён, то в ответ на команду i2cdetect -y 0 мы увидим сетку, в одной из ячеек которой будет стоять адрес датчика (в моём случае 48).

К одному ведущему (master) устройству по i2c можно подключить множество ведомых (slave), поэтому каждому ведомому устройству необходим адрес, по которому к нему будет обращаться ведущее устройство. Адрес датчика LM75A задаётся в регистре Conf

A2,A1,A0 - выводы 7,6,5 чипа LM75A(см.схему ниже). Если они присоединены к питанию, то принимают значение 1, если к земле, то 0.  У меня А0 A1 A2 посажены на землю, а значит регистр, отвечающий за адрес имеет значение (1001000=0x48), что подтверждается командой i2cdetect

Теперь получим значение температуры. LM75A проводит замеры температуры каждые 100мс. Её значение хранится в регистре Temp, который состоит из двух байтов.  t=(значение регистра Temp, сдвинутое на 5 битов вправо)*0.125

 Получим значение регистра:

i2cget -y 0x48 0x00 w

-y: игнорировать предупреждение о потенциальной опасности i2c-tools для вашего оборудования.

0x48 - адрес датчика на шине i2c

0x00 -  адрес регистра Temp

>w - получить слово данных (поскольку ответ состоит из двух байтов. Для получения одного байта нужно использовать параметр b)

в ответ мы должны увидеть значение регистра Temp. У меня это 0xa014

0xa0 - значение младшего байта (LSByte)0x14 - значение старшего байта (MSByte) записываем в двоичной форме и сдвигаем на 5 битов вправо: 10100101=165

165*0.125 = 20.625 градусов значение температуры на датчике.

Запись в регистры рассмотрим в следующей статье, в которой будем управлять чипом FM приёмника по i2c

Тэги:

 

Автор:

Комментариев: 17

  • AEgorov12
    13.02.2013 в 23:02 ответ

    а нельзя ли использовать внутреннюю подтяжку линий к + питания?

    • Mike3
      13.02.2013 в 23:47 ответ

      Можно. На Raspberry Pi реализована внутренняя подтяжка SDA и SCL 1,8kОм резисторами. Просто эта панелька с датчиком температуры у меня валялась давно и подключалась к плате, в которой не было внутренней подтяжки на i2c линиях

      • AEgorov12
        14.02.2013 в 00:09 ответ

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

        • Mike3
          14.02.2013 в 01:51 ответ

          Если температура отрицательная, то бит D10 старшего байта температурного регистра будет равен 1, т.е если значение старшего байта регистра температуры >127. В этом случае температура будет вычислять следующим образом: значение регистра температуры приводится к дополнительному коду (dop_code=~temp_registry_value+1), сдвигается на 5 разрядов вправо и умножается на 0.125: temp = (dop_code>> 5)*0.125

  • EGA7
    25.02.2013 в 11:43 ответ

    Когда же уже ждать "Запись в регистры рассмотрим в следующей статье, в которой будем управлять чипом FM приёмника по i2c"?

    • Mike3
      25.02.2013 в 13:45 ответ

      Через 2-3 недели, когда я получу пополнение из Китая. Что-то не смог я у себя FM чип найти и выковырять неоткуда.

  • EGA7
    25.02.2013 в 16:19 ответ

    Ясно, будем ждать. А на этом сайте есть какая нибудь возможность личной переписки или отправки сообщений с сайта на элпочту? Ну или тему на форуме на крайний случай создать, хотелось бы двухстороннее общение вести, без засорения блогов. Весьма интересует работа с i2c.

    • Mike3
      25.02.2013 в 18:33 ответ

      Да, тут даже на форуме ветка есть для обсуждения аспектов GPIO http://raspberrypi.ru/forum/topics/20/

      • EGA7
        25.02.2013 в 19:49 ответ

        Или по i2c все таки лучше в раздел подключения микросхем http://raspberrypi.ru/forum/topics/21/? Хотя это и не важно. Пойду создам тему.

  • DaTo0
    15.04.2013 в 10:57 ответ

    то есть, про радио не будет??:(

  • PeterHirt3
    18.04.2013 в 01:00 ответ

    да, интересно про i2c, про запись и если можно - популярно про мастер/слейв и подключение нескольких однотипных/разнотипных датчиков. использование второй шины вместе с первой и тп) все очень интересно. расскажите плиз.

  • I am mehanic1
    29.09.2013 в 17:41 ответ

    Сорцы на СИ-градусника с оповещением. Подключение темдатчика, как написано выше в этой ветке...Для подключения свдиода задействован GPIO17 (P1-11) питание взято с P1-17 в файле-исходнике blink.c есть подробно-коменты...Оба файла кладем в одну дирректорию--папку короче Да предварительно ставим bcm2835 у кого нет... как написано здесь http://www.airspayce...835/index.html. Компилим строкой: gcc tbody.c -o tbody -l bcm2835 --есть в комментах в сорце tbody.c.., греем рукой, при 29 и более диод будет мигать 3 раза, затем вывод текущей темп., если равно или более 29 ---3 мига, если менее 29 --- выводит постоянно темп-ру... Уставку по градусам и еще что либо можно поставить свои... См. коменты. Исходники ниже... //Код tbody.c: //Hi!!! This mehanical program version. Источник сорцов на СИ http://www.ip-symcon.de/forum/threads/21088-Raspberry-PI-Modbus-TCP-IP-Server. Спасибо --- mibu Senior Member --- за прямой код.... //root@raspberrypi:~/ds# cat /sys/bus/w1/devices/10-000800fb0e06/w1_slave ---путь до девайса --мой случай // gcc tbody.c -o tbody -l bcm2835 ------компилируем так ---название сорцов (файла), мой случай //Lets go #include <stdio.h> #include <stdlib.h> #include <string.h> #include "blink.c" int main(int argc, char **argv) { FILE *ptr_file; char buf[100]; char *p; double temp; //int a=4; while(1) // поставил в бесконечный цикл (можно так: int a=4; while(a--), здесь а=4 определяет колво циклов, меняем циферку 4 на нужное колво циклов { ptr_file = fopen("/sys/bus/w1/devices/10-000800fb0e06/w1_slave", "r"); //мой случай (0-000800fb0e06 -- этот каталог у каждого будет свой) if (!ptr_file) return 1; while (fgets(buf,100, ptr_file)!=NULL) {}; //printf(" Temp in hex: %s",buf);// можно раском-вать эту строку и добавив для удобства "Temp in hex:" зрить температуру в hex p = strstr(buf, "t=") + 2; p[strlen(p)-1] = 0; //remove new line char temp = atof(p)/1000; //cast to float printf("\n Temperature: %.3f C\n", temp); //ограничил ширину поля после запятой до трех знаков, даллас точнее тысячных не у меня не кажет. if( temp>=29.000 ) //сравниваем с нужной константой тем-ры, здесь для тех кто в айболитов будет играть, надо видимо 37 С поставить, для примера стоит 29, чб быстрее остывал.. {return blnk(argc, argv);} fclose(ptr_file); } return 0; } ///////////////////////////////////// //Код blink.c : //Thank you very much this resourse: http://www.airspayce.com/mikem/bcm2835/blink_8c-example.html // Author: Mike McCauley #include <bcm2835.h> // Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17) #define PIN RPI_GPIO_P1_11 int blnk(int argc, char **argv) { // If you call this, it will not actually access the GPIO // Use for testing // bcm2835_set_debug(1); if (!bcm2835_init()) return 1; // Set the pin to be an output bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); // Blink int a=3; //здесь а=3 определяет колво мигов диода, меняем циферку 3 на нужное колво циклов, можно поставить в бесконечный цикл: while(1) while (a--) { // Turn it on bcm2835_gpio_write(PIN, LOW); //поменяв местами LOW и HIGH (см.ниже) получаем после return высокий уровень на выходе со светящимся диодом, понятно что кроме случая с while(1) // wait a bit bcm2835_delay(500); // изменив например, 500 мс на 10000 получим задержку в 10 сек между миганием диода и т.д // turn it off bcm2835_gpio_write(PIN, HIGH); // wait a bit bcm2835_delay(500); // то же } bcm2835_close(); return main(argc, argv); // здесь после трех мигов диода, возвращаемся в главную функцию и далее покругу. Миги прекращаются при остывании датчика менее 29 С для примера }

  • opakak
    24.09.2016 в 22:24 ответ

    Люди, подскажите где мы берем коэффициент 0,125 на который умножаем. Никак не могу понять…

    • raspiman
      25.09.2016 в 07:28 ответ

      из документации к датчику 1. If the Temp data MSByte bit D10 = 0, then the temperature is positive and Temp value (°C) = +(Temp data)×0.125°C. 2. If the Temp data MSByte bit D10 = 1, then the temperature is negative and Temp value (°C) =−(2’s complement of Temp data)×0.125°C.

  • shef777
    08.04.2017 в 17:40 ответ

    Всем привет! I2c-detect -l command not found Как победить?

    • bro
      08.04.2017 в 23:08 ответ

      Надо установить i2c-tools:   sudo apt-get install i2c-tools

Ваш комментарий

Авторизуйтесь для отправки комментария

© Сообщество пользователей RaspberryPi 2021