Arduino UNO (Master) - Arduino NANO (Slave)

Odpovědět
qwert29
Příspěvky: 3
Registrován: 05 srp 2018, 15:18
Reputation: 0

Arduino UNO (Master) - Arduino NANO (Slave)

Příspěvek od qwert29 » 05 srp 2018, 17:17

Ahoj pánové,
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 slave:

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
}
Já bych chtěl tyto řádky přesunout z loop() do requestEvent() a proměnnou data nevytvářet jako globální, ale jen místní v eventu. Ale když to udělám, nefunguje to.

Kód: Vybrat vše

  data.teplota = dht.readTemperature();
  data.vlhkost = dht.readHumidity();
  data.hic = dht.computeHeatIndex(data.teplota, data.vlhkost, true);

rejze69
Příspěvky: 174
Registrován: 02 dub 2018, 18:56
Reputation: 0

Re: Arduino UNO (Master) - Arduino NANO (Slave)

Příspěvek od rejze69 » 05 srp 2018, 23:31

Lokální proměnné se neudrží pokud program opustí smyčku nebo funkci. I když bude loop prázdný, stejně bude volán a obsah lokálni proměnné z requestEvent se ztratí.

qwert29
Příspěvky: 3
Registrován: 05 srp 2018, 15:18
Reputation: 0

Re: Arduino UNO (Master) - Arduino NANO (Slave)

Příspěvek od qwert29 » 07 srp 2018, 11:21

To ano, tomu rozumím. Proto chci vytvořit globální strukturu data do které by se pak v requestEvent() načetli data ze senzoru a hned odeslali. Globální pro to, aby se v každém eventu nemusela struktura vytvářet. Loop() by pak byl prázdný, protože by se v něm nic nezpracovávalo.

Kód: Vybrat vše

void requestEvent()
{
  #ifdef DEBUG
  Serial.println("Odpověď na požadavek MASTER...");
  #endif

  #ifdef DEBUG
  Serial.println("Načítám data ze senzoru....");
  vypisData();
  #endif
  data.teplota = dht.readTemperature();
  data.vlhkost = dht.readHumidity();
  data.hic = dht.computeHeatIndex(data.teplota, data.vlhkost, true);
  
  #ifdef DEBUG
  Serial.println("Odesílám data na master....");
  #endif
  
  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
  #ifdef DEBUG
  
  Serial.println("Odesláno.");
  #endif
}
Bohužel pokud to takto udělám, výpis na seriový monitor je tento:

Kód: Vybrat vše

Odpoved na pozadavek MASTER...
Nacitam data ze senzoru....
Teplota: 0.00 *C  %	Vlhkost: 0.00 %	Pocitova teplota: 0.00 *C
Odpoved na pozadavek MASTER...
Nacitam data ze senzoru....
Teplota: 0.00 *C  %	Vlhkost: 0.00 %	Pocitova teplota: 0.00 *C
Odesilam data na master....
Odeslano.
Odesilam data na master....
Odeslano.

....tzn. že se nepochopitelně na jeden požadavek dvakrát načtou hodnoty a pak odešlou. Navíc se ty data nenačtou korektně.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 5 hostů