СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

H Кодирование Arduino для температурного датчика TMP102 в черновиках

Привет, Хабр! Сегодня хочу продолжить тему программирования датчиков с использованием шаблонов. Но на этот раз планирую погрузиться в тему немного глубже.

Для отработки различных вариантов кодов будем использовать датчик температуры TMP102. Посмотрим, что получится и разберем отличия в реализации кодов.

Температурный датчик TMP102 [1] является одним из широко используемых цифровых датчиков для измерения температуры окружающей среды. Поэтому, собственно, на нем и остановим выбор.



Замечу, что у датчика TMP102 может быть разное расположение выводов по сравнению с показанным на изображении. Датчик TMP102 поддерживает протокол I2C и оснащен выводами SDA и SCL.

Подключим аналоговые контакты 4 и 5 вашей платы Arduino Uno к выводам SDA и SCL датчика TMP102. Также подключим +5 В и заземление, как показано на следующей схеме.

В этом статье мы используем плату Arduino Uno в качестве ведущего, а TMP102 — как подчиненную периферию, где адрес части TMP102 равен 0x48 в шестнадцатеричном формате:



Теперь подключим свою плату Arduino к компьютеру с помощью USB-кабеля и создадим новый скетч в интегрированной среде Arduino, используя следующий фрагмент кода:

Serial Monitor:
#include <Wire.h>
int partAddress = 0x48;

void setup(){
  Serial.begin(9600);
  Wire.begin();
}

void loop(){

  Wire.requestFrom(partAddress,2);
byte MSB = Wire.read();
  byte LSB = Wire.read();

  int TemperatureData = ((MSB << 8) | LSB) >> 4;

  float celsius = TemperatureData*0.0625;
  Serial.print("Celsius: ");
  Serial.println(celsius);

  float fahrenheit = (1.8 * celsius) + 32;
  Serial.print("Fahrenheit: ");
  Serial.println(fahrenheit);

  delay(500);
}


Теперь можем увидеть показания температуры в градусах Цельсия и Фаренгейта в окне.
В предыдущем фрагменте кода функция Wire.requestFrom (partAddress, 2) запрашивает два байта из ведомого TMP102. Ведомое устройство передает байты данных ведущему устройству, которые захватываются функцией Wire.read () и сохраняются в виде двух разных битов: старший бит (MSB) и младший бит (LSB).

Эти байты преобразуются в целочисленное значение, которое затем преобразуется в фактическое показание по Цельсию путем умножения инкрементной доли датчика TMP102, который получается из таблицы данных.

TMP102 является одним из самых простых датчиков I2C для взаимодействия с Arduino, поскольку значения датчиков могут быть получены с помощью простого метода запроса I2C.
Кодирование Arduino для датчика BH1750 BH1750 является цифровым световым датчиком, который измеряет количество видимого света в данной области.

Несмотря на то, что в различных проектах DIY простые фотоэлементы используются в качестве дешевой альтернативы, датчик BH1750 известен высоким разрешением и точностью в широком диапазоне применений. Окружающий свет, также называемый световым потоком или люксом, измеряется в единичном просвете.

Датчик BH1750 поддерживает связь I2C с адресом части 0x23, с 0x5C в качестве вторичного адреса, если вы используете несколько датчиков BH1750. Ниже представлен образ типичной вскрывающей панели, состоящей из BH1750:



Выводы SDA и SCL платы BH1750 подключим к аналоговым выводам 4 и 5 платы Arduino Uno, как показано на следующей принципиальной схеме. Также заполним соединения +5 В и заземление, как показано на следующей схеме:



Хотя BH1750 является простым и удобным датчиком I2C, в случае сенсора с множеством возможностей измерения кодирование напрямую с использованием библиотеки Wire нецелесообразно.

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

Для BH1750 мы продемонстрируем использование такой библиотеки для кодирования I2C. Прежде чем использовать эту библиотеку, придется импортировать ее в Arduino IDE.

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

После перезапуска Arduino IDE перейдите в меню File | Примеры | BH1750 и откройте скетч Arduino BH1750test. Это должно открыть следующий фрагмент кода в Arduino IDE.

Настройте соответствующий последовательный порт и загрузите его на плату Arduino. Как только код будет выполнен, вы сможете проверить значения светового потока (lux), используя последовательный монитор среды разработки Arduino. Убедитесь, что серийный монитор настроен на скорость 9600 бод:

#include <Wire.h>
#include <BH1750.h>

BH1750 lightMeter;

void setup(){
  Serial.begin(9600);
  lightMeter.begin();
  Serial.println("Running...");
}

void loop() {
  uint16_t lux =
lightMeter.readLightLevel();
  Serial.print("Light: ");
  Serial.print(lux);
  Serial.println(" lx");
  delay(1000);
}


Как видно из предыдущего фрагмента кода, мы импортировали библиотеку BH1750, включив файл BH1750.h с помощью Wire.h. Эта библиотека предоставляет функцию readLightLevel (), которая будет получать значение окружающего света от датчика и предоставлять его как целое число.

Поскольку код Arduino работает в цикле с задержкой в 1000 миллисекунд, значения lux будут выбираться с датчика и посылаться в последовательный порт каждую секунду. Наблюдать эти значения в окне Serial Monitor.

PyMata для быстрого прототипирования I2C


Мы использовали pyFirmata в качестве нашей библиотеки Python по умолчанию для взаимодействия с протоколом Firmata. Хотя pyFirmata поддерживает режимы аналогового, цифрового, PWM и SERVO с простыми в использовании методами, он обеспечивает ограниченную поддержку протокола I2C.

В этой статье используем другую библиотеку Python Firmata под названием PyMata.
Библиотека PyMata поддерживает регулярные методы Firmata, а также обеспечивает полную поддержку протокола обмена сообщениями I2C. PyMata можно легко установить с помощью Setuptools:
C: \> easy_install.exe pymata
C:\Users\Oleg>pip install pymata #так надо!


Если вы используете Linux или Mac OS X, используйте следующую команду в терминале, чтобы установить библиотеку PyMata:
$ Sudo pip install pymata


Если все настроено правильно, этот процесс завершится без ошибок. Вы можете подтвердить PyMata, открыв интерактивную подсказку Python и импортировав PyMata:
>>> import PyMata


Взаимодействие TMP102 с использованием PyMata


Чтобы использовать функции PyMata, понадобится, чтобы плата Arduino была оснащена прошивкой firmata стандартного firmata, как и библиотека pyFirmata. Прежде чем приступить к объяснению функций PyMata, сначала запустим следующий фрагмент кода. Подключим датчик температуры TMP102, как описано выше.

С помощью Arduino IDE перейдем в меню Файл | Примеры | Firmata и загрузим стандартный скетч Firmata оттуда в свою плату Arduino. Теперь создадим исполняемый файл Python, используя следующий фрагмент кода. Изменим значение порта (COM5), если необходимо, на соответствующее имя порта, как того требует ваша операционная система.

import time
from PyMata.pymata import PyMata

#Initialize Arduino using port name
port = PyMata("COM5")

#Configure I2C pin
port.i2c_config(0, port.ANALOG, 4, 5)

# One shot read asking peripheral to send 2 bytes
port.i2c_read(0x48, 0, 2, port.I2C_READ)
# Wait for peripheral to send the data
time.sleep(3)

# Read from the peripheral
data = port.i2c_get_read_data(0x48)

# Obtain temperature from received data
TemperatureSum = (data[1] << 8 | data[2]) >> 4

celsius = TemperatureSum * 0.0625
print celsius

fahrenheit = (1.8 * celsius) + 32
print fahrenheit

firmata.close()


При выполнении предыдущего фрагмента кода можно увидеть показания температуры в градусах Фаренгейта и Цельсия.

Как можно видеть из встроенных комментариев в коде, первым шагом для использования Arduino с помощью PyMata является инициализация порта с помощью конструктора PyMata.

PyMata поддерживает конфигурацию контактов I2C через функцию i2c_config (). PyMata также поддерживает одновременные операции чтения и записи с помощью функций i2c_read () и i2c_write ().

Взаимодействие BH1750 с использованием PyMata


В случае BH1750 предыдущий фрагмент кода PyMata можно использовать с небольшими изменениями, чтобы получить данные датчика внешней освещенности. В качестве первого изменения можно заменить адрес части TMP102 (0x48) на экземпляр BH1750 (0x23) в следующем фрагменте кода.

Также нужно будет преобразовать необработанные значения, полученные от датчика, в значение люкс, используя данную формулу. После этих изменений запустите с терминала следующую программу:

import time
from PyMata.pymata import PyMata

port = PyMata("COM5")
port.i2c_config(0, port.ANALOG, 4, 5)

# Request BH1750 to send 2 bytes
port.i2c_read(0x23, 0, 2, port.I2C_READ)
# Wait for BH1750 to send the data
time.sleep(3)

# Read data from BH1750
data = port.i2c_get_read_data(0x23)

# Obtain lux values from received data
LuxSum = (data[1] << 8 | data[2]) >> 4

lux = LuxSum/1.2
print str(lux) + ' lux'

firmata.close()


При запуске предыдущего фрагмента кода можно увидеть показания датчика освещенности в люксах на терминале. Этот процесс может использоваться на большом количестве устройств I2C для считывания зарегистрированной информации.

Команды pySerial



Стандартный протокол Firmata и библиотеки Firmata от Python очень полезны для тестирования или быстрого прототипирования датчиков I2C.

Хотя у них есть много преимуществ, проекты, основанные на Firmata, сталкиваются со следующими недостатками: задержка в режиме реального времени, ограниченная поддержка.

Таким образом, можно использовать подходы Firmata для быстрого прототипирования устройств, но для создания передовых проектов необходимо использовать альтернативные методы.

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

Соединение с последовательным портом


После подключения вашего Arduino к USB-порту компьютера можно открыть порт в своем Python-коде, используя серийный класс, как показано в следующем примере кода:
import serial
port = serial.Serial('COM5',9600, timeout=1)


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

Перед выполнением любой другой команды из библиотеки pySerial необходимо инициализировать последовательный порт.

После того как последовательный порт открыт можно начать чтение порта с помощью readline (). Функция readline () требует указания таймаута при инициализации порта, иначе код может завершиться с исключением:
line = port.readline()


Функция readline () будет обрабатывать каждую строку из порта, которая заканчивается символом конца строки \ n.

При работе с pySerial необходимо очистить входной буфер, чтобы избежать переполнения буфера и поддерживать операции в реальном времени:
port.flushInput()


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

Это хорошая практика кодирования для закрытия последовательного порта после завершения процесса. Эта практика может устранить проблему блокировки порта после завершения кода Python:
port.close()


Выводы


Работа знакомит пользователей с различными шаблонами кода прототипов с практическими приложениями. Эти шаблоны создания прототипов помогли изучить новые парадигмы программирования Python и методы Firmata. На примерах рассмотрены концепции программирования с предоставлением быстрых шаблонов программирования.

Литература


  1. Датчик температуры TMP102.
  2. Книга: «Arduino Basic Connections».

комментарии (1)

0
barkalov ,  
Ниже представлен образ типичной вскрывающей панели, состоящей из BH1750
Перевести breakout board как «вскрывающая панель» — это талант!

серийный монитор
Ок, вопросов больше нет.