Как организовать обмен данными между Arduino и Raspberry PI ?
В робототехнике и в системах в целом часто возникает необходимость разносить устройства и делить между ними задачи. На исполнительные органы и нижний уровень управления лучше всего ставить платы на микроконтроллерах, так как их быстродействие гораздо выше чем у компьютера. Компьютер в основном собирает и отдаёт данные, обрабатывает сложные алгоритмы, передаёт всю информацию в WEB, ну и тому подобное. Реализация связи идёт по такой цепочке Arduino I2C Raspberry PI. Давайте попробуем сделать.
Из этой статьи вы узнаете:
Простейшая схема подключения
Загружаем скетч и программу
Мой эксперимент «На столе»
Друзья, всем добрый день, на связи снова я, автор блога, Гридин Семён. Давно хотел написать статью по этой теме. И вот этот момент наступил. Я тоже делаю первые шаги в этом направлении.
Мне очень важно понять, как реализуется обмен данными между микроконтроллерной платой и одноплатным компьютером. Неважно какого производителя, смысл один и тот же. У меня есть Raspberry PI и Arduino UNO. Чаще всего в интернете я встречал описание связи по интерфейсу I2C. Вот с неё мы и начнём.
Интерьерная широкоформатная печать цены, принтер, станок широкоформатной печати цена.
Какое именно можно найти практическое применение? Именно распределение функций и задач в роботе и в автоматических системах. Таким образом можно расписать независимые микро-алгоритмы между действующими узлами и передавать всю необходимую информацию в «Мозг».
Простейшая схема подключения
Подключение ножек опишу лучше в табличной форме, так нагляднее всего, проводов всё равно немного:
Arduino UNO | Raspberry Pi |
5V | 5V |
GND | GND |
SCA | SCA |
SCL | SCL |
Я собрал схему.
Загружаем скетч и программу
Давайте подключим датчик температуры DHT11, чтобы мы могли видеть что обмен данными у нас реально работает.
Итак пишем скетч на Arduino.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #include <dht11.h> #include <Wire.h> dht11 DHT; // Объявление переменной класса dht11 #define DHT11_PIN 2 // Датчик DHT11 подключен к цифровому пину номер 4 int SLAVE_ADDRESS = 0x04; int ledPin = 13; boolean ledOn = false; void setup(){ Serial.begin(9600); // Скорость работы порта Serial.println("DHT TEST PROGRAM "); // Выводим текст Serial.print("LIBRARY VERSION: "); // Выводим текст Serial.println(DHT11LIB_VERSION); Serial.println(); // Пустая строка pinMode(ledPin, OUTPUT); Wire.begin(SLAVE_ADDRESS); Wire.onReceive(processMessage); Wire.onRequest(sendAnalogReading); } void loop(){ int chk; ; // Мониторинг ошибок chk = DHT.read(DHT11_PIN); // Чтение данных switch (chk){ case DHTLIB_OK: break; case DHTLIB_ERROR_CHECKSUM: Serial.println("Checksum error, \t"); break; case DHTLIB_ERROR_TIMEOUT: Serial.println("Time out error, \t"); break; default: Serial.println("Unknown error, \t"); break; } // Выводим показания влажности и температуры Serial.print("Humidity = "); Serial.print(DHT.humidity, 1); Serial.print(", Temp = "); Serial.println(DHT.temperature,1); delay(300); } void processMessage(int n) { char ch = Wire.read(); if (ch == 'l') { toggleLED(); } } void toggleLED() { ledOn = ! ledOn; digitalWrite(ledPin, ledOn); } void sendAnalogReading() { byte reading = DHT.temperature; Wire.write(reading); |
И пишем скрипт для Raspberry Pi на Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import smbus import time import os bus = smbus.SMBus(1) SLAVE_ADDRESS = 0x04 def request_reading(): reading = int(bus.read_byte(SLAVE_ADDRESS)) print(reading) while True: command = raw_input("Enter command: l - toggle LED, r - read A0 ") if command == 'l' : bus.write_byte(SLAVE_ADDRESS, ord('l')) elif command == 'r' : request_reading() |
И смотрим, что из этого у нас получается.
Мой эксперимент «На столе»
Хочу сразу написать, что в Raspberry Pi программа сразу не заработает, нужно сделать ещё несколько действий, в том числе и проверить связь между устройствами.
Сначала в raspiconfig мы выставляем разрешение на работу I2C порта. Находим в главном меню настройки preference — Interfeis — I2C — Enable.
Перезагружаемся:
1 | sudo reboot |
После перезагрузки проверяем, есть наше устройство?:
1 | ls /dev | grep i2c |
Если в ответ на эту команду мы получили:
1 2 | i2c-0 i2c-1 |
То всё ОК! Обращаю внимание у Raspberry Pi 3 только один порт i2c - 1.
Ставим следующие пакеты:
1 2 3 | sudo apt-get update sudo apt-get install i2c-tools (необязательно, но удобно просматривать подключенные устройства и всячески работать с шиной I2C в консоли) sudo apt-get install python-smbus |
Теперь проверяем соединение:
1 | sudo i2cdetect -y 1 |
В ответ должна выскочить такая картинка в консоли:
Если показывает адрес, то значит малина видит ваше устройство.
Если ваш скрипт выдаёт такую ошибку:
1 | OSError: [Errno 121] Remote I/O error |
Она говорит нам о том, что нужно проверить связь, так как устройство не доступно.
Записываем скетч и скрипт и наслаждаемся моментом:
На этом у меня всё, друзья. Если есть вопросы, пишите письма. Подписывайтесь на новости блога, пишите комментарии. Пока — пока.
С уважением, Гридин Семён
Можно было сразу рассмотреть связь через UART, там даже проще немного.
Или свисток USB-RS485 за 60р. с несколькими ардуинами и modbus, благо всё давно написано, надо только собрать.
Это через библиотеки Modbus делается? А скорость обмена там примерно какая?
Добрый день.
Скорость обмена наверно как и на всех стандартных UART до 115200 б/с.
На те же выходы UART + 1GPIO можно повесить RS485 микросхему и будет Вам 485 и без свистка =)
Вариантов много, мне больше всех нравится вариант, где быстрее всего будет передавать данные!!!
Быстрее всего по параллельной шине или QUAD-SPI)) на крайний случай для пром.применений — CAN шина.
если на GPIO есть 16 свободных ног, городи параллельную передачу) максимум скорости =))))
«На те же выходы UART + 1GPIO можно повесить RS485 микросхему и будет Вам 485 и без свистка =)»
Что за древняя технология пином дрыгать. давно направление уже всё определяется автоматически. Тем более микросхему какую?? Обвязку поять? Свисток 60р. Готовая плата с обвязкой и автоматическим определением ~150р. Rs485 и есть промышленная сеть, что может быть проще, дешевле и безопаснее для оборудования на передачу до 1км???
Помнится, ардуинку про мини напрямую соединил с UART малинки, и все хорошо работало. На ардуинке висели два датчика температуры TS611, данные с которых запрашивала малинка. Никаких адаптеров не потребовалось, скорость сразу поставил 115200.
Пример хороший, но, к сожалению передает только один байт. Как быть если нужно передать float или string?