Arduino Raspberry Pi I2C коммуникация
- Войдите на сайт для отправки комментариев
Добрый день!
Делаю систему которая следит за дверьми и окнами. На концах стоят герконы, а на рамах магниты. Если дверь открыли, то цепь размыкается и на входе (12 пин) ардуины (UNO) логический ноль.
Ардуина у меня соеденена с Raspberry Pi по средствам I2C. Вот собственно с этим и есть проблема. У меня была идея, на ардуине проверять входы (состояние герконов) и их показания записывать в массив байтов. Записать данные в массив не проблема, но вот как передать эти данные Raspberry и как их прочитать в Python на Raspberry никак не могу понять. С одним датчиком проблем нет, но вот с массивом беда.
Вот мой код для Arduino:
#include <Wire.h>
#define SLAVE_ADDRESS 0x04
int state = 0;
int Command =99;
/*
Available commands:
99 - DEFAULT: Nothing to do
1 - CHECK DOORS
*/
int mainDoorPin = 12;
int ledPin = 13;
byte systemState[8];
void setup(){
pinMode(ledPin,OUTPUT);
Serial.begin(9600);
Wire.begin(SLAVE_ADDRESS);
digitalWrite(ledPin,LOW);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}
void loop()
{
delay(100);
}
void receiveData(int byteCount)
{
while (Wire.available()) {
Command = Wire.read();
}
Serial.print("Received value: ");
Serial.println(Command);
switch (Command){
case 99:
//Set system to initial state
Serial.println("Initial state...");
systemState[0]=0;
systemState[1]=0;
break;
case 1:
Serial.println("Checking doors");
checkDoors();
break;
}
}
void checkDoors()
{
if(systemState[0] == 0){
systemState[0] = digitalRead(mainDoorPin);
systemState[1] = 0;
}
}
void sendData(){
Wire.write(systemState,sizeof(systemState));
}
Как видно из кода, в массиве systemState у меня два значения и отправляю я Raspberry я этот массив, но получаю только первое значение.
вот для Python:
import smbus
import time
bus = smbus.SMBus(1)
address = 0x04
def writeNumber(value):
bus.write_byte(address, value)
return -1
def readNumber():
number = (bus.read_byte(address))
return number
while True:
var = input("Enter: ")
if not var:
continue
writeNumber(var)
print "RPI: Hi Arduino, I sent you ", var
time.sleep(1)
number = readNumber()
print "Arduino: Hey RPi, I received a digit ", number
print
Перерыл уже весь интернет, ничего не нашел. Может кто-то сталкивался, как в Python прочитать массив байтов полчаемый по I2C. Или может кто на толкнет, что почитать. Спасибо.
А почему ббы Вам не использовать напрямую GPIO малинки, их там много ... Проблемы с 3.3в ? Их решить несложно... Прощщее, чем изобретать протокол для и2с...
Как то изначально не хотелось использовать машинку для этого. На малине хотелось только обрабатывать данные полученные от ардуины, и запихивать их в БД. Это раз. А второе, интересней связать два устройства и наладить связь между ними. Может видел кто статью или какой другой материал? Можно и на английском. Спасибо.
http://wiringpi.com/reference/i2c-library
гляньте на это
http://wiringpi.com/reference/i2c-library
гляньте на это
Спасибо. Судя повсему, это поможет, есть возможность считать 16-и битовое значение :)
А можно поподробнее как Raspberry Pi и Arduino связаны?
А можно поподробнее как Raspberry Pi и Arduino связаны?
>Ардуина у меня соеденена с Raspberry Pi по средствам I2C.
Если написано i2c - значит
- sda ардуины подключен к sda распбери
- scl ардуины подключен к scl распбери
- земля ардуины соединена с землей распбери
Согласование уровней - нужно
тоесть 2 ардуины к одному распбери не подключить?
хотел использовать распбери как сервера ардуины как улиенты обрабатывающие инфу от датчиков
Разрешаю подключить.
А если серьезно, почитайте про i2c.
Можно подключить, конешн.
почитать я почитал, но страшновато эксперементировать
Подниму среди уважаемых читателей тему.
Пытался повторить разные варианты с разных источников,
но не всё гладко в нашем королевстве.
Так что есть повод поделиться опытом и по обсуждать.
Итак! Имеем:
Arduino Pro Mini (на самом деле неважно какая) с програмированием в Arduino IDE 1.8.9 (в общем случае тоже неважно)
Raspberry Pi3 (так же неважно какая) с программированием на Python3 (на самом деле очень важно, потому что Python3 и все предыдущие версии отличаются крайне сильно.
Сразу же скажу, что если с arduino я знаком достаточно давно, то с raspberry и языком программирования Python3 знаком не сильно.
Задача: Отправить несколько байт с малинки на ардуину, в ответ получить несколько байт с ардуины обратно в малинку. Ради унификации, хотелось бы на ардуине использовать универсальны скетч из проекта ESPEasy https://www.letscontrolit.com/wiki/index.php?title=ProMiniExtender
Если внимательно глянуть, то в этом скетче ардуино по i2c принимается команда из 4-х байт. В ответ посылает 0-2 байта как результат.
Для начала, просто попробуем послать число в INT (2 байта). Теперь что получаю и с чем столкнулся в процессе отладки:
Послать Raspberry - > Arduino 2 байта достаточно просто:
#!/usr/bin/python3 import smbus import time # for RPI version 1, use "bus = smbus.SMBus(0)" bus = smbus.SMBus(1) # This is the address we setup in the Arduino Program address = 0x04 def writeNumber(value): bus.write_byte(address, int(value)&0xFF) bus.write_byte(address, int(value)>>8) # bus.write_byte(address, value.to_byte(2, byteorde='big')) # Рабочий вариант # bus.write_byte_data(address, 0, ord(value)) return -1 def readNumber(): # num = bus.read_byte(address) num = (bus.read_byte(address) << 8) | bus.read_byte(address) return num while True: var = input("Enter 1 – 9: ") if not var: continue writeNumber(var) print( "RPI: Привет Arduino, Я послал тебе ", var) # sleep one second time.sleep(1) number = readNumber() print( "Arduino: Привет RPI, Я ответил тебе 1: ", number ) number = readNumber() print( "Arduino: Привет RPI, Я ответил тебе 2:", number ) number=0 printНа ардуино принимаем и отправляем обратно:
#include <Wire.h> #define SLAVE_ADDRESS 0x04 int number = 0; int state = 0; byte dat[2]; byte num=0; byte num1=0; byte num2=0; void setup() { pinMode(13, OUTPUT); Serial.begin(19200); // start serial for output // initialize i2c as slave Wire.begin(SLAVE_ADDRESS); // define callbacks for i2c communication Wire.onReceive(receiveData); Wire.onRequest(sendData); Serial.println("Ready 555!"); } void loop() { delay(100); if( state==1 ) { Serial.println( "--------------------" ); state=0; } } // callback for received data void receiveData(int byteCount){ while(int n=Wire.available()) { number = Wire.read(); if( num==0 ) { num1=number; num=1; } else if( num==1 ) { num2=number; num=0; number=num1 + (num2<<8); } else num=0; } } // callback for sending data void sendData(){ Serial.println(number); Wire.write(number); }В итоге получается какая-то фигня.
С малинки улетает не 2 а 3 байта. 3-йбайт является повторением 2-го. Ладно. На ардуино принимает 3 байта, последний отбрасываем.
Отправляем обратно:
Wire.write(number);
(можно и разбив на 2 байта, без разницы)
или так:
Wire.write(number&0xFF);
Wire.write(number>>8);
Без разницы. На малинку прилетает ТОЛЬКО последний байт.
Я уже голову сломал.
Что многоуважаемый All может сказать на эту тему: Может у кого-нить уже есть достойная повторения реализация многобайтной передачи между этими двумя дейвайсами?