Automação residencial em módulos

Bacana... e já tens as torneiras funcionando com touch? ^^

Bom, eu dissequei vários códigos e bibliotecas (maniac, Stefan Engelke, aaronds, entre outros), precisava descartar os problemas com a parte de software. Li algumas vezes o datasheet (ainda preciso repassar alguns detalhes), o chip é pequeno, mas não é nada simples (pelo menos pra mim rs), porem entendo um pouco melhor como a coisa funciona. X)

Num primeiro momento, como minha automação inclui a parte de segurança, o master não pode ter o luxo de ficar sem ouvir por longos períodos, e como o papel do objeto "radio" da biblioteca do maniac é tentar enviar até que receba o ack ou o tempo chegue no timeout, alterei o abaixo no RF24.ccp

bool RF24::write( const void* buf, uint8_t len ) {
  (...)
  //const uint32_t timeout = 500;
  const uint32_t timeout = 50;
  (...)
}

bool RF24Network::write_to_pipe( uint16_t node, uint8_t pipe ){
  (...)
  //short attempts = 5;
  short attempts = 1;
  (...)
}

bool RF24Network::write(uint16_t to_node){
  //int retries = 3;
  int retries = 1;
}

Pelos meus testes os nodes responderão entre 8 e 20 ms, coloquei no loop do arduino o encargo de reenvio (tirando da livraria a responsabilidade), assim o master não para de ouvir os outros nodes por uma situação qualquer em um node (leitura de sensores ou algum processamento, por exemplo).

Para testes das requisições do master, as partes que interessam (pois o resto é parecido com o exemplo txrx), ficaram assim:

(...)
#define dlyCheck 0
#define dlyMonit 1

const unsigned long intDelay[] = {100UL, 1000UL};
unsigned long longLastMillis[] = {0UL, 1000UL};

uint8_t this_node = 0;
int to_node_idx = 0;
unsigned long next_check_time = 0;

enum state {OFF, ON, waiting, error};

struct message_t {
  int Id;
  bool Value;
};

struct nodes_t {
  uint8_t Node;
  char Name[8]; //TODO: change to use progmem http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
  state State;
  unsigned long LastRequest;
  unsigned long LastResponse;
  uint8_t retries;
  bool Light;
  bool Presence;
  bool Door;
} 
Node[Nodes_Count] = {
  {0,"Master", OFF, 0UL, 0UL},
  {1,"Living", OFF, 0UL, 0UL},
  {2,"kitchen", OFF, 0UL, 0UL},
  {3,"F-Room", OFF, 0UL, 0UL},
  {4,"B-Room", OFF, 0UL, 0UL},
  {5,"Hall", OFF, 0UL, 0UL}
};

#if defined(__AVR_ATmega2560__)
RF24 radio(9,53);
#else
RF24 radio(9,10);
#endif

RF24Network network(radio);
(...)
void setup() {
  //    JP_1    Node
  //(X)	( )	( )	0
  //( )	(X)	( )	1
  //( )	( )	(X)	2
  //(X)	(X)	(X)	3
  //( )	(X)	(X)	4
  //(X)	(X)	( )	5

  //TODO: change to use direct port access
  pinMode(JP_1,INPUT); 
  pinMode(JP_2,INPUT);
  pinMode(JP_3,INPUT);

  // turn on pullup resistors
  digitalWrite(JP_1, HIGH);
  digitalWrite(JP_2, HIGH);
  digitalWrite(JP_3, HIGH);

  delay(20); //wait to stabilize(?)

  bool JP1 = digitalRead(JP_1) == LOW;
  bool JP2 = digitalRead(JP_2) == LOW;
  bool JP3 = digitalRead(JP_3) == LOW;

  if (JP1 && !JP2 && !JP3) this_node = 0u;
  if (!JP1 && JP2 && !JP3) this_node = 1u;
  if (!JP1 && !JP2 && JP3) this_node = 2u;
  if (JP1 && JP2 && JP3) this_node = 3u;
  if (!JP1 && JP2 && JP3) this_node = 4u;
  if (JP1 && JP2 && !JP3) this_node = 5u;

  if(this_node == 0)
    to_node_idx = 1;

  Serial.begin(57600);
  radio.begin();

  network.begin(75, this_node);
  
  Serial.print(Node[this_node].Name);
  Serial.println(F(" Initialized"));

  pinMode(LED_ON, OUTPUT);
  digitalWrite(LED_ON, HIGH);
}
(...)
void StatusRequest(void){
  unsigned long now = millis();

  if ((now - longLastMillis[dlyCheck] >= intDelay[dlyCheck])
    && (Node[to_node_idx].retries < 3)
    && (Node[to_node_idx].State != error) 
    && ((now - Node[to_node_idx].LastRequest) >= TimeCheck)
    ){
      longLastMillis[dlyCheck] = now;
      Node[to_node_idx].State = waiting;    
      Node[to_node_idx].LastRequest = now;

      RF24NetworkHeader header(/*to node*/ Node[to_node_idx].Node, /*type*/ 'S' /*Status*/);
      
      if (network.write(header, &now, sizeof(now))) {
        Serial.print(F("Sent Status Request: "));
        Serial.print(now, 10);
        Serial.print(F(", To Node: "));
        Serial.println(Node[to_node_idx].Name);

        Node[to_node_idx].retries = 0;
      }
      else {
        Serial.print(F("Node: "));
        Serial.print(Node[to_node_idx].Node);
        Serial.print(F(" - "));
        Serial.print(Node[to_node_idx].Name);
        Serial.println(F(" no found"));

        Node[to_node_idx].retries++;
      }
  }
  if(to_node_idx == Nodes_Count -1)
    to_node_idx = 1;
  else
    to_node_idx++;
}

O código acima esta longe de ser o código final. Nem é o atual em desenvolvimento, o atual esta quase impossível de ler (rs), a biblioteca do maniac parece a mais completa, mas estou com todos "os métodos que interessaram" em um único sketch gigante, pois usando o VS2010 com o visual micro add-in consigo ver mais detalhes enquanto escrevo o código (ir para definições [que não o .h], auto-completar, bookmarks, etc :wink: )

Juro que não imaginava que essa parte seria a mais complicada =) Mas quando tiver algo mais próximo de completo/real eu posto aqui.