segunda-feira, 23 de novembro de 2009

Controlando dispositivos via Web com o Program-Me

Controlar dispositivos elétricos com o PROGRAM-ME é muito fácil, o principal cuidado que devemos tomar é com a capacidade máxima de corrente do chip ATMEGA que é de 40 mA (5V) .

Portanto para controlar dispositivos elétricos que necessitem de correntes superiores a 40mA , tensões superiores aos 12v disponíveis no Program-Me ou que trabalhem com corrente alternada (CA), será necessário associar alguns componentes entre os terminais dos PROGRAM-ME e o dispositivo a ser controlado.

Notem que um dos diferenciais do Program-Me, é já possuir on-board 4 transistores IRF510 que permitem controlar dispositivos externos sem qualquer hardware adicional, porém neste exemplo não iremos utilizar eles pois necessitamos de 5 interfaces.


Normalmente utilizamos um transitor na saída do Program-Me para dar um ganho na capacidade de corrente. Quando o dispositivo a ser controlado opera com corrente alternada (CA), ou necessita de uma corrente superior a suportada por transistores comuns, adicionamos além do transitor um relé.

Obs: Nos terminais da bobina do relé é necessário adicionar um diodo para proteger a junção do transistor, pois a bobina do relé gera uma tensão reversa ao ser desenergizada e que poderia danificar o transistor (vejam no diagrama elétrico da interface de relés os diodos D1 a D5) .


Com o circuito apresentado neste post, poderemos controlar até 5 dispositivos elétricos utilizando o PROGRAM-ME, sendo que o diferencial deste projeto é que vamos adicionar ao Program-Me um shield Wi-Fi (WiShield) que permitirá comandar os dispositivos remotamente de qualquer conexão internet.


O shield Wi-Fi utilizado é o da foto abaixo que é produzido pela AsyncLabs e custa por volta de US$ 50 nos Estados Unidos. Pode-se também utilizar um shield ethernet que pode ser encontrado aqui no Brasil por R$75 ,neste caso abrindo-se mão da conexão sem fios.



Seguem abaixo as características do Shield:

Wi-Fi Module Features:
• 802.11b Wi-Fi certified
- 1Mbps and 2Mbps throughput speeds
• Supports both infrastructure (BSS) and ad hoc (IBSS) wireless networks
• Ability to create secured and unsecured networks
- WEP (64-bit and 128-bit)
- WPA/WPA2 (TKIP and AES) PSK
• Low power usage
- Sleep mode: 250µA
- Transmit: 230mA
- Receive: 85mA

Pin Usage:
• SPI
- Slave select (SS): Arduino pin 10 (port B, pin 2)
- Clock (SCK): Arduino pin 13 (port B, pin 5)
- Master in, slave out (MISO): Arduino pin 12 (port B, pin 4)
- Master out, slave in (MOSI): Arduino pin 11 (port B, pin 3)
• Interrupt (Uses only one of the following, depending on jumper setting)
- INT0: Arduino pin 2 (port D, pin 2)
- DIG8: Arduino pin 8 (port B, pin 0)
• LED: Arduino pin 9 (port B, pin 1)
- To regain use of this pin, remove the LED jumper cap
• 5V power
• GND

Basicamente o projeto consiste em rodar um servidor Web no Program-Me, disponibilizando uma página simples onde podemos selecionar quais dos 5 dispositivos desejamos ligar ou desligar. O shield Wi-Fi permite a interface de rede entre o roteador wireless da rede local e o Program-Me.

O primeiro passo é acoplar o shield Wi-Fi ao Program-Me (figura abaixo) e depois carregar o sketch do servidorWeb, onde configuramos uma página Web simples que permitirá o controle de algumas saídas do Program-Me.



Neste caso utilizei como base o WiServer sketch apresentado no próprio site do fabricante do shield (http://asynclabs.com/wiki/index.php?title=AsyncLabsWiki), apenas adaptando a quantidade de dispositivos controlados para 5 dispositivos e modificando a formatação da página Web de forma a ficar compatível com o projeto que eu necessitava.

Montei então a placa para as interfaces dos 5 relés (figura abaixo), onde utilizei uma placa padrão que é facilmente encontrada nas lojas de componentes eletrônicos.



Na figura abaixo temos o diagrama elétrico da placa de interface de reles:



Conectei então essa interface em 5 portas de saída do Program-Me conforme figura abaixo:


  • Configurações:

No sketch é necessário atribuir um IP e uma máscara de rede para o Shield, sendo possível também utilizar segurança WEP (64-bit and 128-bit), WPA/WPA2 (TKIP and AES) PSK .

Abaixo temos o trecho do sketch onde são executadas as configurações de rede.

// Parametros de configuracao da rede wireless ----------------------------------------
unsigned char local_ip[] = { 192,168,10,200}; // Endereco IP do WiShield
unsigned char gateway_ip[] = { 192,168,10,1}; // Endereco do gateway ou roteador
unsigned char subnet_mask[] = { 255,255,255,0}; // mascara de rede local
const prog_char ssid[] PROGMEM = {
"PROGRAM_ME"}; // SSID da rede (max 32 bytes)
unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {
"12345678"}; // max 64 caracteres

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
// Key 0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Key 1
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Key 2
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
// Key 3
};

// configuracao do wireless mode
// WIRELESS_MODE_INFRA - conexao com um AP
// WIRELESS_MODE_ADHOC - conexao direta com outro dispositivo WiFi (por exemplo com o PC)
unsigned char wireless_mode = WIRELESS_MODE_ADHOC;
unsigned char ssid_len;
unsigned char security_passphrase_len;


* O sketch completo deste projeto está disponível no final deste post.


  • Testando o dispositivo

Por volta de 15 segundos após ligar o conjunto, o shield Wi-Fi sintoniza a rede local e a página já fica disponível para acesso no endereço configurado para o shield. (neste caso 192.168.10.200)
Ao entrar no Browser com o endereço associado ao Shield é apresentada a seguinte tela:




Ao clicarmos com o mouse em cima do link de um dos relés, o Program-Me muda o estado da porta correspondente ao relé selecionado, ligando ou desligando o dispositivo que estiver conectado nos terminais desse relé.

A tela abaixo mostra o estado após selecionarmos o rele 1 na tela anterior.



Os comando podem ser executados facilmente de qualquer browser, inclusive de telefones celulares com Wi-Fi ou que tenham serviço de dados habilitado.

Vale lembrar que além do Servidor Web, podemos ter um cliente Web rodando em paralelo desde que o ATMEGA equipado seja um 328.
Esse tipo de configuração em paralelo permitirá por exemplo que a sua aplicação colete informações de um site de terceiros na internet e essas informações sejam utilizadas nas páginas hospedadas no PROGRAM-ME.
Outra implementação interessante que pode ser executada seria conectar sensores (temperatura, humidade, fumaça etc) e monitorar essas informações via Web com o Program-Me.

Bem pessoal é isso, espero que gostem do post e que ele sirva de inspiração para muitas idéias legais de aplicação.

José Luiz Sanchez Lorenzo

/*
* WebServer para controle via WEB de 5 dispositivos eletricos usando o Program-Me
*/
//carrega as bibliotecas necessarias para o funcionamento do WiServer
#include WiServer.h
#include string.h

#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// configura as saidas do Program-Me que serao utilizadas para controlar os reles
#define ledPin1 14
#define ledPin2 15
#define ledPin3 16
#define ledPin4 17
#define ledPin5 18


// Parametros de configuracao da rede wireless ----------------------------------------
unsigned char local_ip[] = { 192,168,10,200}; // Endereco IP do WiShield
unsigned char gateway_ip[] = { 192,168,10,1}; // Endereco do gateway ou roteador
unsigned char subnet_mask[] = { 255,255,255,0}; // mascara de rede local
const prog_char ssid[] PROGMEM = { "PROGRAM_ME"}; // SSID da rede (max 32 bytes)
unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = { "12345678"}; // max 64 caracteres

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
};

// configuracao do wireless mode
// WIRELESS_MODE_INFRA - conexao com um AP
// WIRELESS_MODE_ADHOC - conexao direta com outro dispositivo WiFi (por exemplo com o PC)
unsigned char wireless_mode = WIRELESS_MODE_ADHOC;
unsigned char ssid_len;
unsigned char security_passphrase_len;


boolean states[5]; //array que armazena os estados dos reles
char stateCounter; //variavel temporaria para indexar os reles
char tmpStrCat[64]; //variavel utilizada no processamento da pagina Web
char stateBuff[4]; //variavel utilizada no processamento de texto durante conversao de boleana para string (boolToString())
char numAsCharBuff[2];
char ledChange; //indica alteracao no estado dos reles

void boolToString (boolean test, char returnBuffer[4])
{
returnBuffer[0] = '\0';
if (test)
{
strcat(returnBuffer, "ON"); //retorna "ON" se o rele estiver ligado
}
else
{
strcat(returnBuffer, "OFF"); //retorna "OFF" se o rele estiver desligado
}
}

void printStates() //envia para a porta serial/USB o estado dos reles quando ocorrer alguma solicitacao de alteracao
{
for (stateCounter = 0 ; stateCounter < 5; stateCounter++)
{
boolToString(states[stateCounter], stateBuff);

Serial.print("Estado do Rele ");
Serial.print(stateCounter+1);
Serial.print(": ");
Serial.println(stateBuff);
}
}

void writeStates() //atualiza o estado das saidas do Program-Me acionando os reles
{
digitalWrite(ledPin1, states[0]);
digitalWrite(ledPin2, states[1]);
digitalWrite(ledPin3, states[2]);
digitalWrite(ledPin4, states[3]);
digitalWrite(ledPin5, states[4]);

}

// Esta é a funcao que gera a pagina Web
boolean sendPage(char* URL) {

Serial.println("Iniciada Impressao da pagina");

printStates();
writeStates();

//verifica qual link da pagina foi clicado e define qual rele deve-se alterar o estado
if (URL[1] == '?' && URL[2] == 'R' && URL[3] == 'E' && URL[4] == 'L')
{
ledChange = (int)(URL[5] - 49); //determina qual foi o link clicado na pagina.

for (stateCounter = 0 ; stateCounter < 5; stateCounter++)
{
if (ledChange == stateCounter)
{
states[stateCounter] = !states[stateCounter]; // inverte o estado do rele selecionado
Serial.print("Alterado estado do rele "); //informa na serial/USB que houve alteracao de estado
Serial.println(ledChange+1);
}
}

//retorna o usuario para a pagina principal
WiServer.print("");
return true;
}

if (strcmp(URL, "/") == false)
{
WiServer.print("Program-Me Server");
WiServer.print("
Sistema de controle de dispositivos via WEB utilizando o PROGRAM-ME
\n
");
WiServer.print("

\n
");
WiServer.print("
Selecione o Rele que deseja alterar o status :
\n
");
WiServer.print("

\n
");
for (stateCounter = 0; stateCounter < 5; stateCounter++) //for each led
{
numAsCharBuff[0] = (char)(stateCounter + 49); //soma 49 para obter o caracter ASCII comecando por 1
numAsCharBuff[1] = '\0'; //strcat espera uma string de caracteres e nao apenas um
//Essa string e um caracter + um string terminator.

tmpStrCat[0] = '\0'; //inicializa a string
strcat(tmpStrCat, " tmpStrCat[12] = (char)(stateCounter + 49); //adiciona o numero do Rele
tmpStrCat[13] = '\0'; //finaliza a string apropriadamente

strcat(tmpStrCat, ">Rele ");
strcat(tmpStrCat, numAsCharBuff);
strcat(tmpStrCat, ": ");

boolToString(states[stateCounter], stateBuff);
strcat(tmpStrCat, stateBuff);
strcat(tmpStrCat, "
"); //nos temos agora algo similar a Rele 1: Off

WiServer.print(tmpStrCat);
WiServer.print("

\n
");
}

WiServer.print(" ");
return true;
}
}

void setup() {
// Inicializa o WiServer e prepara ele para fornecer acesso a pagina
// Configura as portas do Program-Me selecionadas para os reles como saida
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
pinMode(ledPin5, OUTPUT);

Serial.begin(9600); //configura a porta serial/USB para 9600bps
WiServer.init(sendPage);

//Inicializa o array que armazena o estado dos reles colocando os reles em OFF
states[0] = false;
states[1] = false;
states[2] = false;
states[3] = false;
states[4] = false;
}

void loop(){
// Run WiServer
WiServer.server_task();

delay(10);
}

8 comentários:

  1. É possível com que esse shield utilize DHCP para buscar um IP?

    ResponderExcluir
  2. Ainda não está disponível, mas acredito que em breve o pessoal libere uma versão do WiServer que suporte DHCP.

    ResponderExcluir
  3. Rafael Polo - sagitarius.43@hotmail.com - Caro Colega, me interessa muito essa aplicação pratica deste controlador de reles. Gostaria de solicitar-lhe um orçamento de um sistema deste tipo já pronto e testado, para 10 reles. Não há carga muito elevada para controlar, na verdade o on-off do rele já me resolve o problema. O que quero é comprar o sistema e a placa já prontos...espero sua resposta! Abraços!

    ResponderExcluir
  4. Boa tarde Rafael, enviei um e-mail ao Sr com os meus contatos.

    atenciosamente

    José Luiz

    ResponderExcluir
  5. Great writing! I want you to follow up to this topic!?!

    online pharmacy

    ResponderExcluir
  6. Eu também teria interesse em uma dessas placas, seria possível a venda de uma dessas?

    Pode ser uma parecia com a do Rafael.

    Terias algum valor para ela?

    ResponderExcluir
  7. Jaélcio Almeida - jaelciobasket@hotmail.com - Me interessei em um módulo controlador com 10 reles, me passe o valor. Simples como o Rafael postou, apenas on-off. Desde já agradeço a atenção.

    ResponderExcluir
  8. LEOUFAM@YAHOO.COM.BR - ACHEI SUPER INTERESSANTE,ELE FUNCIONA COM O ARDUINO DUEMILANOVE?QUERO ATIVAR CARRGAS DE MAIOR AMPERAGEM,COMO ARCONDICIONADO.VC TEM ALGUMA QUE FAÇA ISSO?OUTRA COISA NAO PRECISA DE ALIMENTAÇÃO EXTERNA?

    ResponderExcluir