Slave 1 (um botão que acende/apaga uma lâmpada por MOC + TRIAC):
#include <MasterSlaveFuji.h>
MasterSlaveFuji *rs485;
#define ID 1
#define DEBOUNCE 50
#define BUTTON_PIN 12
#define LAMP_PIN 13
long lastButtonPress;
bool buttonIsPressed = false;
bool hasChanged = false;
bool lampOn = false;
void setup(){
Serial.begin(9600);
rs485 = new MasterSlaveFuji(ID, &Serial, 2);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LAMP_PIN,OUTPUT);
}
void loop(){
// Atualiza dados
rs485->update();
if (rs485->hasNewMessage()) // Se houve mensagem nova...
{
switch(rs485->function) // Acao de acordo com a funcao
{
case 'L': // Caso a funcao seja 'L', atualizar status da lampada
lampOn = rs485->data4 - '0'; // Atualiza status da lampada
rs485->sendACK(); // Envia comando que foi entendido
break;
case 'S': // Caso a funcao seja 'S', informar status da lampada
// Envia resposta com o status da lampada
rs485->sendACK(0, 'S', 1, rs485->Positive, '0', '0', '0', '0' + lampOn);
break;
default: // Se a funcao nao for 'L' nem 'S', o comando nao e conhecido
rs485->sendNAK();
}
}
// Verifica se o botao foi pressionado, com debounce
if (digitalRead(BUTTON_PIN) == LOW)
{
if (!buttonIsPressed)
{
lastButtonPress = millis();
buttonIsPressed = true;
}
else if ((millis() > (lastButtonPress + DEBOUNCE)) && !hasChanged)
{
lampOn = !lampOn;
hasChanged = true;
}
}
else
{
buttonIsPressed = false;
hasChanged = false;
}
digitalWrite(LAMP_PIN, lampOn);
}
Slave 2 (dois botões, um que controla um led no próprio slave, e outro que controla a lâmpada do outro slave):
#include <MasterSlaveFuji.h>
MasterSlaveFuji *rs485;
#define ID 2
#define DEBOUNCE 50
#define LAMP_PIN 13
byte buttonPin[2] = {11,12};
long lastButtonPress[2];
bool buttonIsPressed[2] = {false, false};
bool hasChanged[2] = {false, false};
bool lampOn;
bool button2Pressed;
void setup(){
Serial.begin(9600);
rs485 = new MasterSlaveFuji(ID, &Serial, 2);
pinMode(buttonPin[0], INPUT_PULLUP);
pinMode(buttonPin[1], INPUT_PULLUP);
pinMode(LAMP_PIN,OUTPUT);
lampOn = false;
button2Pressed = false;
}
void loop(){
// Atualiza RS485
rs485->update();
if (rs485->hasNewMessage()) // Se houver nova mensagem...
{
switch(rs485->function)
{
case 'L': // Caso a funcao seja 'L', atualizar status da lampada
lampOn = rs485->data4 - '0'; // Atualiza status da lampada
rs485->sendACK(); // Envia comando que foi entendido
break;
case 'S': // Caso a funcao seja 'S', informar status da lampada
// Envia resposta com o status da lampada
rs485->sendACK(0, 'S', 1, rs485->Positive, '0', '0', '0', '0' + lampOn);
break;
case 'B': // Caso a funcao seja 'B', informa se o botao foi pressionado
rs485->sendACK(0, 'B', 1, rs485->Positive, '0', '0', '0', '0' + button2Pressed);
button2Pressed = false; // status do botao ja enviado, retorna para falso
break;
default: // Caso a funcao nao seja nenhuma das anteriores, responder que nao entendeu
rs485->sendNAK();
}
}
// Verifica botoes
for (int i = 0; i < 2; i++)
{
if (digitalRead(buttonPin[i]) == LOW)
{
if (!buttonIsPressed[i])
{
lastButtonPress[i] = millis();
buttonIsPressed[i] = true;
}
else if ((millis() > (lastButtonPress[i] + DEBOUNCE)) && !hasChanged[i])
{
if (i == 0) // Se for pressionado o botao 1, mudar status da lampada
{
lampOn = !lampOn;
}
else // Se for o botao 2, preparar para informar o master
{
button2Pressed = true;
}
hasChanged[i] = true;
}
}
else
{
buttonIsPressed[i] = false;
hasChanged[i] = false;
}
}
digitalWrite(LAMP_PIN, lampOn);
}
A biblioteca do RS485 (MasterSlaveFuji) também foi atualizada. Tem um pequeno "ajuste" que tive que fazer para eliminar uns erros que estavam acontecendo, com lixo chegando no Master, talvez seja problema de falta de resistor de pull-up/down, resistor de impedância de valor diferente do convencional (150 ohms, ao invés de 120 ohms), enfim, depois tento descobrir o que aconteceu. Ainda tenho uns erros de timeout, mas novamente, espero que seja algo com relação aos resistores.
Também não consegui fazer funcionar com uma baud rate maior do que 9600 (tentei com 14400, e não deu certo), novamente espero que com os resistores resolva este problema.
O tempo entre envio do questionamento e resposta do slave para o baud rate de 9600 está em 35 ms. Com 14400, é de 25 ms, mas como falei, dá erro de timeout. Então, mantendo 9600 de baud rate, e se forem os cerca de 30 nós que estimo, seriam uns 2 segundos para questionar todos os nós (alguns precisarão informar status de botões, sensores, etc.). Esse tempo pode até ser maior, então espero que eu consiga aumentar o baud rate e manter funcionando.
De acordo com os problemas que estava tendo, decidi modificar a PCI dos slaves para ter a possibilidade de colocar resistores de pull-up/down, além de reorganizar os componentes do circuito de conversão para 5v, para ficar mais parecido com o layout descrito no datasheet to LM2576.
Aproveitei e fiz logo a "PCI de entrada", que ficará na caixa principal da automação junto com o Mega. Nessa caixa ficará a entrada da alimentação dos slaves, e a conexão para o Mega entrar na rede RS-485.
Só estou na dúvida como fazer a conexão dessa PCI com o Mega... por enquanto, coloquei conectores fêmeas para conectar por fios pino/pino com os pinos do Mega, mas não confio muito nesse tipo de conexão... acho que o ideal seria um shield, mas da forma que estou pensando em fazer minha rede de automação, terei duas redes, uma para cada andar da casa, então fazer por shield talvez dê muito certo... alguém tem alguma sugestão? Minha preocupação em utilizar fios jumpers é válida, ou não preciso me preocupar tanto com isso?
MasterSlaveFuji.zip (1.9 KB)