potřeboval bych poradit ohledně komunikace mezi UNO (master) a NANO (slave). Zatím jde jen o pokus, do budoucna chci toto využít v IoT. Master se má jednou za pět minut zeptat slave na data, slave po přijmutí požadavku přečte aktuální hodnoty z čidel a odešle je na slave kde se zpracují dál (zatím pro test výpis na serial). Komunikace probíhá přes I2C (knihovna Wire) kde si arduina posílají data zabalená v strukture.
A teď popis problému: master odešle požadavek přes Wire.requestFrom() a čeká na čtení odpovědi (tedy než se vrátí struct()). Zde problém není. Slave obdrží požadavek a přes event Wire.onRequest(requestEvent) odešle očekávanou struct(). Když dám čtení z čidel přímo do eventu, tak komunikace nejde. Respektive po obdržení požadavku odešle slave nejdřív prázdnou struct() a hned za tím druhou naplněnou daty. Bohužel Master přijme jen tu první a komunikace se zablokuje. Pokud budu číst data z čidla v loop() a ukládat je do globální proměnné, a ty pak odešlu v eventu, funguje vše v pořádku. Bohužel v tomto druhém případě ztrácí komunikace výhodu onoho času, kdy chci mít data na master. Slave se bude pořád ptát čidla a ukládat data do proměnné i když je master nepotřebuje. Proč nepřečtu data z čidla přímo v eventu?
Kód master:
Kód: Vybrat vše
//i2c Master UNO---------------------------
#include <Wire.h>
struct RECIVE_DATA //struktura potřebných dat mezi MASTER a SLAVE
{
float teplota;
float vlhkost;
float hic;
};
RECIVE_DATA data; //globální peroměnná ktará udržuje aktuální stavy dat z čidla
void setup()
{
Serial.begin(9600);
Wire.begin(); //inicializace I2C komunikace v rezimu master
Wire.onReceive(receiveEvent);
}
void loop()
{
while(Serial.available())
{
char c = Serial.read();
if(c == 'T')
{
Serial.println("Poslán dotaz na SLAVE...");
Wire.requestFrom(5,sizeof(RECIVE_DATA));
Serial.println("Odesláno...");
Serial.println("Čekám na data ze SLAVE...");
byte *p = (byte *)&data;
while(Wire.available())
{
char c = Wire.read(); //přečtu jeden znak z buffera
*p=c; // ulozim ho do místa, kam směřuje ukazatel
p++; // ukazatel posuneme o jeden znak dál
}
vypisData();
}
else
{
Serial.println("Pouze T odešle dotaz na SLAVE.");
}
}
}
void receiveEvent(int howMany)
{
if(sizeof(data)!= howMany)
return; //asi nedosli data co cakam, když nemají spravnou velikost
byte *p = (byte *)&data;
while(Wire.available())
{
char c = Wire.read(); // precitam jeden znak z buffra
*p=c; // ulozim ho do miesta, kam smeruje pointer
p++; // pointer posuniem o jeden znak hore
}
}
Kód: Vybrat vše
//I2C Slave NANO---------------------
#include <Wire.h>
struct REQUEST_DATA //struktura potřebných dat mezi MASTER a SLAVE
{
float teplota;
float vlhkost;
float hic;
};
REQUEST_DATA data; //globální peroměnná ktará udržuje aktuální stavy dat z čidla
//DHT22---------------------
#include <DHT.h>
#define DHTPIN 2 //číslo pinu Arduina, kam je připojený DATA pin senzoru DHT
#define DHTTYPE DHT22 //typ senzoru DHT-22 (neboDHT11 pro pripad, ze by byl DHT-11)
DHT dht(DHTPIN, DHTTYPE); // do proměné dht uložíme údaje o již nadefinovaném senzoru
void setup()
{
Serial.begin(9600);
dht.begin(); //inicializace senzoru
Wire.begin(5); //inicializace I2C komunikace slave s adresou 5
Wire.onRequest(requestEvent); // register odeslání
}
void loop()
{
data.teplota = dht.readTemperature();
data.vlhkost = dht.readHumidity();
data.hic = dht.computeHeatIndex(data.teplota, data.vlhkost, true);
delay(2000); //počkej 2s
}
void requestEvent()
{
const byte *p = (const byte *)&data; //převod jednotlivých znaků z objektu na byte přes ukazatele
Wire.write(p, sizeof(REQUEST_DATA)); //odeslání všech byte
}
Kód: Vybrat vše
data.teplota = dht.readTemperature();
data.vlhkost = dht.readHumidity();
data.hic = dht.computeHeatIndex(data.teplota, data.vlhkost, true);