sábado, 21 de novembro de 2015

Alarme anti-furto para projetores multimídia - parte 2

Olá pessoal,

Continuando com o projeto segue abaixo vídeo do alarme e do código implementado:




O código:


#include <Wire.h> 
#include <SPI.h>
#include <Ethernet.h>
#include <Agentuino.h> 
//#include "RTClib.h"

// this must be unique
static byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0xDA }; 
// change network settings to yours

// change server to your email server ip or domain
// IPAddress server( 1, 2, 3, 4 );
//char server[] = "mail.sorocaba.unesp.br";
//char server[15] = "200.145.27.7";

EthernetClient client;


// RFC1213-MIB OIDs
// .iso (.1)
// .iso.org (.1.3)
// .iso.org.dod (.1.3.6)
// .iso.org.dod.internet (.1.3.6.1)
// .iso.org.dod.internet.mgmt (.1.3.6.1.2)
// .iso.org.dod.internet.mgmt.mib-2 (.1.3.6.1.2.1)
// .iso.org.dod.internet.mgmt.mib-2.system (.1.3.6.1.2.1.1)
// .iso.org.dod.internet.mgmt.mib-2.system.sysDescr (.1.3.6.1.2.1.1.1)
static char sysDescr[20] PROGMEM     = "1.3.6.1.2.1.1.1.0";  // read-only  (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysObjectID (.1.3.6.1.2.1.1.2)
static char sysObjectID[20] PROGMEM   = "1.3.6.1.2.1.1.2.0";  // read-only  (ObjectIdentifier)

// .iso.org.dod.internet.mgmt.mib-2.system.sysUpTime (.1.3.6.1.2.1.1.3)
static char sysUpTime[20] PROGMEM     = "1.3.6.1.2.1.1.3.0";  // read-only  (TimeTicks)

// .iso.org.dod.internet.mgmt.mib-2.system.sysContact (.1.3.6.1.2.1.1.4)
static char sysContact[20] PROGMEM    = "1.3.6.1.2.1.1.4.0";  // read-write (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysName (.1.3.6.1.2.1.1.5)
static char sysName[20] PROGMEM       = "1.3.6.1.2.1.1.5.0";  // read-write (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysLocation (.1.3.6.1.2.1.1.6)
static char sysLocation[20] PROGMEM   = "1.3.6.1.2.1.1.6.0";  // read-write (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysServices (.1.3.6.1.2.1.1.7)
static char sysServices[20] PROGMEM   = "1.3.6.1.2.1.1.7.0";  // read-only  (Integer)

// Arduino defined OIDs
// .iso.org.dod.internet.private (.1.3.6.1.4)
// .iso.org.dod.internet.private.enterprises (.1.3.6.1.4.1)
// .iso.org.dod.internet.private.enterprises.arduino (.1.3.6.1.4.1.36582)
// .iso.org.dod.internet.private.enterprises.arduino.value.valA0-A5 (.1.3.6.1.4.1.36582.3.1-6)
/*
static char valA0[] PROGMEM   = "1.3.6.1.4.1.36582.3.1.0";  // read-only  (Integer)

static char valA1[] PROGMEM   = "1.3.6.1.4.1.36582.3.2.0";  // read-only  (Integer)

// .iso.org.dod.internet.private.enterprises.arduino.value.valD0-D13 (.1.3.6.1.4.1.36582.3.7-20)
static char valD0[] PROGMEM   = "1.3.6.1.4.1.36582.3.7.0";  // read-only  (Integer)

static char valD1[] PROGMEM   = "1.3.6.1.4.1.36582.3.8.0";  // read-only  (Integer)
*/
static char alarme1[24] PROGMEM = "1.3.6.1.4.1.36582.3.1.0";  // read-only  (Integer)
static char alarme2[24] PROGMEM = "1.3.6.1.4.1.36582.3.2.0";  // read-only  (Integer)
static char alarme3[24] PROGMEM = "1.3.6.1.4.1.36582.3.3.0";  // read-only  (Integer)
static char relay[24] PROGMEM = "1.3.6.1.4.1.36582.3.7.0";  // read-only  (Integer)


static char locDescr[20] = "Agentuino";

static char locObjectID[20] = "1.3.6.1.4.1.36582";
static uint32_t locUpTime = 0;
static char locContact[20] = "Eric Gionet";
static char locName[20] = "Agentuino";
static char locLocation[20] = "Nova Scotia, CA";
static int32_t locServices = 7;
boolean localarme1 = 0; 
boolean localarme2 = 0; 
boolean localarme3 = 0;
boolean locrele = 0;
boolean statusalarme1 = 0;
boolean statusalarme2 = 0;
boolean statusalarme3 = 0;
boolean statusrele = 0;

//uint32_t prevMillis = millis();
uint32_t dispMillis = 0;


char oid[SNMP_MAX_OID_LEN];
SNMP_API_STAT_CODES api_status;
SNMP_ERR_CODES status;

const int switchPin1 = 2; // Reed switch to digital pin 2
const int switchPin2 = 3; // Reed switch to digital pin 3
const int switchPin3 = 4; // Reed switch to digital pin 3
const int rele = 7;
boolean disparou;
boolean disptempo;

long lastDebounceTime = 0;
long debounceDelay = 1500;

int lastswitch1State = HIGH;
int lastswitch2State = HIGH;
int lastswitch3State = HIGH;
int staterelay = HIGH;

void pduReceived()
{
  SNMP_PDU pdu;
  Serial.println("UDP Packet Received...");
  api_status = Agentuino.requestPdu(&pdu);
  if ( (pdu.type == SNMP_PDU_GET || pdu.type == SNMP_PDU_GET_NEXT || pdu.type == SNMP_PDU_SET)
    && pdu.error == SNMP_ERR_NO_ERROR && api_status == SNMP_API_STAT_SUCCESS ) {
    pdu.OID.toString(oid);
    Serial.print("OID = ");
    Serial.println(oid);
    
    if ( pdu.type == SNMP_PDU_SET ) {
      status = SNMP_ERR_READ_ONLY;
    } else if ( strcmp_P(oid, sysDescr ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locDescr);
    } else if ( strcmp_P(oid, sysUpTime ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_TIME_TICKS, locUpTime);
    } else if ( strcmp_P(oid, sysName ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locName);
    } else if ( strcmp_P(oid, sysContact ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locContact);
    } else if ( strcmp_P(oid, sysLocation ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locLocation);
    } else if ( strcmp_P(oid, sysServices) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_INT, locServices);
     } else if ( strcmp_P(oid, sysObjectID) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locObjectID);
    } else if ( strcmp_P(oid, alarme1) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_INT, localarme1);
    } else if ( strcmp_P(oid, alarme2) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_INT, localarme2);
    } else if ( strcmp_P(oid, alarme3) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_INT, localarme3);
    } else if ( strcmp_P(oid, relay) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_INT, locrele);
    
    } else {
      status = SNMP_ERR_NO_SUCH_NAME;
    }
    pdu.type = SNMP_PDU_RESPONSE;
    pdu.error = status;
    Agentuino.responsePdu(&pdu);
  }
  Agentuino.freePdu(&pdu);
  
}



void setup() {

  Serial.begin(9600);  // Inicia conexao serial para monitoramento
   pinMode(switchPin1, INPUT);        // switchPin1 is an input
  digitalWrite(switchPin1, HIGH);    // Activate internal pullup resistor
  pinMode(switchPin2, INPUT);        // switchPin1 is an input
  digitalWrite(switchPin2, HIGH);    // Activate internal pullup resistor
  pinMode(switchPin3, INPUT);        // switchPin1 is an input
  digitalWrite(switchPin3, HIGH);    // Activate internal pullup resistor
  pinMode(rele, OUTPUT);      // rele is an output
  digitalWrite(rele, HIGH); 

  Ethernet.begin(mac);
  
  disparou = false;
  disptempo = true;
  
//  Serial.println("Ethernet iniciado");
  
  #ifdef AVR
    Wire.begin();
  #else
    Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
  #endif


  
  api_status = Agentuino.begin();

  if ( api_status == SNMP_API_STAT_SUCCESS ) {
    Agentuino.onPduReceive(pduReceived);
    delay(10);
    Serial.println("SNMP Agent Initiated...");
    return;
  } else
  {
  delay(10);
  Serial.print("SNMP Agent failed!");
  }

}


void loop() {
    int somaledsyellow = 0; //variavel para somar os valores para acionar os leds amarelo via i2c
    int somaledsred = 0; //variavel para somar os valores para acionar os leds vermelho via i2c
    int totalleds = 0; //variavel para totalizar os valores para acionar os leds amarelo e vermelho via i2c
    int reading1 = digitalRead(switchPin1); // estado do sensor magnetico 1
    int reading2 = digitalRead(switchPin2); //estado do sensor magnetico 2
    int reading3 = digitalRead(switchPin3); // estado do sensor magnetico 3
    staterelay = digitalRead(rele); //estado do rele
    
    // se os sensores magneticos nao foram acionados e depois de acionados passaram-se mais de 5 minutos acende os leds verdes
    if ((reading1) && (reading2) && (reading3) && (disptempo)) {
       digitalWrite(rele,HIGH); // rele e desligado
       Wire.beginTransmission(32); //endereca o modulo I2c no endereco 32
       Wire.write(248); // escreve o valor para acender todos os leds
       Wire.endTransmission(); // finaliza a transmissao
    }
    else
    {
      if ((reading1 != lastswitch1State) || (reading2 != lastswitch2State) || (reading3 != lastswitch3State)) {
          lastDebounceTime = millis(); // se  mudou o estado de um dos sensores magneticos grava o tempo com a funcao millis
      }   
      if ((millis() - lastDebounceTime) > debounceDelay) { //Se passou mais de 1500ms com o estado modificado o rele e acionado e toca a sirene
         if ((reading1 == 0) || (reading2 == 0) || (reading3 == 0)) { 
              digitalWrite(rele,LOW); // o rele e ligado
         }
      }
      
      if (reading1 == LOW) { //se o sensor magnetico 1 estiver em estado baixo ou seja acionado
           statusalarme1 = 1; // o status do sensor magnetico 1 e colocado em 1
           somaledsred = somaledsred + 8; //liga o primeiro led vermelho da esquerda pra direita
      }
      else
      {
           somaledsyellow = somaledsyellow + 1; //se o sensor nao foi acionado acende o primeiro led amarelo da esquerda pra direita
           statusalarme1 = 0; // o status do sensor magnetico 1 e colocado em 0
      }
    
      if (reading2 == LOW) { //se o sensor magnetico 2 estiver em estado baixo ou seja acionado
          statusalarme2 = 1; // o status do sensor magnetico 1 e colocado em 1
          somaledsred = somaledsred + 16; //liga o segundo led vermelho da esquerda pra direita
      }
      else
      {
           somaledsyellow = somaledsyellow + 2; //se o sensor nao foi acionado acende o segundo led amarelo da esquerda pra direita
           statusalarme2 = 0; // o status do sensor magnetico 2 e colocado em 0
      }

      if (reading3 == LOW) { //se o sensor magnetico 3 estiver em estado baixo ou seja acionado
          statusalarme3 = 1; // o status do sensor magnetico 3 e colocado em 1
          somaledsred = somaledsred + 32; //liga o terceiro led vermelho da esquerda pra direita
      }
      else
      {
          somaledsyellow = somaledsyellow + 4;//se o sensor nao foi acionado acende o terceiro led amarelo da esquerda pra direita
          statusalarme3 = 0;  // o status do sensor magnetico 3 e colocado em 0
       }

       totalleds = 255 - (somaledsyellow + somaledsred); //totaliza os valores de escrita para os leds amarelos e vermelhos
       Wire.beginTransmission(32);
       Wire.write(255);
       Wire.write(totalleds); // escreve o valor correspondente para acionar ou desacionar os leds vermelhos e amarelos
       Wire.endTransmission();
       
       if (!disparou) { // se o alarme nao disparou
              dispMillis = millis(); 
              disptempo = false;
              disparou = true;
       }
          
       //Aguarda 5 minutos para parar de tocar a sirene
       if ((millis() - dispMillis > 300000) && (!disptempo)){
              digitalWrite(rele,HIGH);
              //  Serial.print("Parar a sirene");
              disptempo = true;
              disparou = false;
       }
  }
    lastswitch1State = reading1; //ultimo estado do sensor magnetico 1
    lastswitch2State = reading2; //ultimo estado do sensor magnetico 2
    lastswitch3State = reading3; //ultimo estado do sensor magnetico 3
    
   
    Agentuino.listen(); //O agentuino fica em espera
    // Atualiza os estados dos sensores para as variaveis a serem lidas via SNMP
    localarme1 = statusalarme1; 
    localarme2 = statusalarme2;  
    localarme3 = statusalarme3;
    locrele = staterelay; //atualiza o estado do rele para ser lido via SNMP
}



Observem que mais uma vez utilizamos o agentuino para disponibilizar os dados dos sensores e do relé para serem lidos pelo Zabbix (vide posts anteriores).

É isso aí pessoal. Quaisquer dúvidas entrem em contato!

domingo, 25 de outubro de 2015

Novo projeto - Alarme anti-furto para projetores multimídia

Olá pessoal, tudo bem com vocês!

Neste post vou apresentar um novo projeto que implementei na Universidade onde trabalho. Quem já trabalhou em instituições de ensino sabe que hoje o uso de projetores multimídia nas salas é bastante comum e costuma-se fixar estes equipamentos no teto para serem utilizados sempre que precisar sem precisar toda vez levar o equipamento e instalar em uma mesa. Isto torna o uso bastante prático porém acrescenta um risco de furto (acredite: há verdadeiras "quadrilhas" especializadas em furtar esses equipamentos) e pensando nisso comecei a pesquisar se há algum dispositivo de segurança que pudesse monitorar esses equipamentos (fora cadeados, suportes de ferro, etc) e descobri que não há nenhum dispositivo parecido que pudesse identificar uma tentativa de furto em tempo real. Analisando equipamentos de segurança patrimonial e alarmes verifiquei que existe um sensor magnético que pode ser conectados em alarmes para identificar abertura de portas e janelas e que poderia ser colocado no projetor multimídia, possibilitando o monitoramento por uma central de alarme. Como uma central de alarme com conexão de rede não é um equipamento muito barato resolvi implementar uma central utilizando Arduino + Ethernet Shield, possibilitando o monitoramento até por SNMP.
Vamos ver o material necessário para o projeto:

- Sensores magnéticos: o sensor magnético consiste de duas partes separadas: uma com um reed switch conectado a um par de fios e outra parte com uma imã. Ao aproximar o imã do reed switch a chave é fechada e ao afastar o imã a chave é aberta. Fixa-se a parte com o reed switch e o par de fios no corpo do projetor e outra parte com o imã fixa-se no suporte do projetor no teto de forma que fiquem bem encostados. 

Fig.ura 1: Sensor magnético



















- Bornes: os bornes são para conectar os fios que vem dos sensores magnéticos para a protoboard.

Figura 2: Bornes para conexão dos fios












- Protoboard
- Arduino UNO
- Ethernet Shield W5100


- Sirene 12V: a sirene vai alertar quando um dos sensores magnéticos abrir.


Figura 3: Sirene eletrônica















- Fonte 12V 1A: a fonte vai alimentar a sirene.

Figura 4: Fonte 12V 1A
















- Módulo relé 1 canal ou 2 canais: o relé vai permitir o acionamento da sirene em 12V.

Módulo relé 1 canal















- Fio de alarme 2 vias ou cabo de rede: para conectar os sensores magnéticos à central de alarme.

- Expansor de portas I2C PCF8574N: como temos poucas portas no Arduino UNO e utilizaremos leds indicadores de acionamento dos sensores magnéticos utilizamos o expansor de portas.


No próximo post veremos a implementação do circuito e do código Arduino. Até a próxima!

segunda-feira, 14 de setembro de 2015

Monitoramento de tensão - SNMP + Zabbix

Olá pessoal!

Depois de um bom tempo sem postagens o blog volta com novidades! Dando continuidade ao projeto de monitoramento de tensão hoje veremos como implementar SNMP com Agentuino neste projeto e monitorá-lo através do Zabbix da mesma forma como fizemos com o circuito de monitoramento de temperatura.
O que precisaremos para implementar SNMP? Antes de mais nada precisamos acrescentar um Shield Ethernet W5100 ao nosso projeto, configurar a rede e conectá-lo. Uma vez acrescentado o Shield Ethernet W5100, vamos ao código:

A única coisa que mudou em relação ao SNMP Agentuino do projeto de monitoramento de temperatura foi a variável tensao que será disponibilizada via SNMP para a leitura pelo agente SNMP Zabbix.


#include <Wire.h> 
#include <SPI.h>
#include <Ethernet.h>
#include <Agentuino.h> 

static byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D }; 

EthernetClient client;

static const char sysDescr[20] PROGMEM     = "1.3.6.1.2.1.1.1.0";  // read-only  (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysObjectID (.1.3.6.1.2.1.1.2)
static const char sysObjectID[20] PROGMEM   = "1.3.6.1.2.1.1.2.0";  // read-only  (ObjectIdentifier)

// .iso.org.dod.internet.mgmt.mib-2.system.sysUpTime (.1.3.6.1.2.1.1.3)
static const char sysUpTime[20] PROGMEM     = "1.3.6.1.2.1.1.3.0";  // read-only  (TimeTicks)

// .iso.org.dod.internet.mgmt.mib-2.system.sysContact (.1.3.6.1.2.1.1.4)
static const char sysContact[20] PROGMEM    = "1.3.6.1.2.1.1.4.0";  // read-write (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysName (.1.3.6.1.2.1.1.5)
static const char sysName[20] PROGMEM       = "1.3.6.1.2.1.1.5.0";  // read-write (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysLocation (.1.3.6.1.2.1.1.6)
static const char sysLocation[20] PROGMEM   = "1.3.6.1.2.1.1.6.0";  // read-write (DisplayString)

// .iso.org.dod.internet.mgmt.mib-2.system.sysServices (.1.3.6.1.2.1.1.7)
static const char sysServices[20] PROGMEM   = "1.3.6.1.2.1.1.7.0";  // read-only  (Integer)

// Arduino defined OIDs
// .iso.org.dod.internet.private (.1.3.6.1.4)
// .iso.org.dod.internet.private.enterprises (.1.3.6.1.4.1)
// .iso.org.dod.internet.private.enterprises.arduino (.1.3.6.1.4.1.36582)
// .iso.org.dod.internet.private.enterprises.arduino.value.valA0-A5 (.1.3.6.1.4.1.36582.3.1-6)
/*
static const char valA0[] PROGMEM   = "1.3.6.1.4.1.36582.3.1.0";  // read-only  (Integer)

static const char valA1[] PROGMEM   = "1.3.6.1.4.1.36582.3.2.0";  // read-only  (Integer)

// .iso.org.dod.internet.private.enterprises.arduino.value.valD0-D13 (.1.3.6.1.4.1.36582.3.7-20)
static const char valD0[] PROGMEM   = "1.3.6.1.4.1.36582.3.7.0";  // read-only  (Integer)

static const char valD1[] PROGMEM   = "1.3.6.1.4.1.36582.3.8.0";  // read-only  (Integer)
*/
static const char tensao[24] PROGMEM = "1.3.6.1.4.1.36582.3.5.0";  // read-only  (Integer)


static char locDescr[20] = "Agentuino";

static char locObjectID[20] = "1.3.6.1.4.1.36582";
static uint32_t locUpTime = 0;
static char locContact[20] = "Eric Gionet";
static char locName[20] = "Agentuino";
static char locLocation[20] = "Nova Scotia, CA";
static int32_t locServices = 7;
boolean loctensao = 0; 
boolean statustensao = 0;

//uint32_t prevMillis = millis();
uint32_t dispMillis = 0;


char oid[SNMP_MAX_OID_LEN];
SNMP_API_STAT_CODES api_status;
SNMP_ERR_CODES status;


byte LEDNORMAL = 3; //pino do Led verde (ENERGIA NORMAL)
byte LEDFALTA = 4; //pino do Led vermelho (FALTA DE ENERGIA)

volatile unsigned long contador; //variável controlada através da interrupção na porta 2 

void pduReceived()
{
  SNMP_PDU pdu;
  Serial.println("UDP Packet Received...");
  api_status = Agentuino.requestPdu(&pdu);
  if ( (pdu.type == SNMP_PDU_GET || pdu.type == SNMP_PDU_GET_NEXT || pdu.type == SNMP_PDU_SET)
    && pdu.error == SNMP_ERR_NO_ERROR && api_status == SNMP_API_STAT_SUCCESS ) {
    pdu.OID.toString(oid);
    Serial.print("OID = ");
    Serial.println(oid);
    
    if ( pdu.type == SNMP_PDU_SET ) {
      status = SNMP_ERR_READ_ONLY;
    } else if ( strcmp_P(oid, sysDescr ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locDescr);
    } else if ( strcmp_P(oid, sysUpTime ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_TIME_TICKS, locUpTime);
    } else if ( strcmp_P(oid, sysName ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locName);
    } else if ( strcmp_P(oid, sysContact ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locContact);
    } else if ( strcmp_P(oid, sysLocation ) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locLocation);
    } else if ( strcmp_P(oid, sysServices) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_INT, locServices);
     } else if ( strcmp_P(oid, sysObjectID) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locObjectID);
    } else if ( strcmp_P(oid, tensao) == 0 ) {
      status = pdu.VALUE.encode(SNMP_SYNTAX_INT, loctensao);
    
    } else {
      status = SNMP_ERR_NO_SUCH_NAME;
    }
    pdu.type = SNMP_PDU_RESPONSE;
    pdu.error = status;
    Agentuino.responsePdu(&pdu);
  }
  Agentuino.freePdu(&pdu);
  
}

void setup() {
     Ethernet.begin(mac);
     pinMode(LEDNORMAL, OUTPUT);
     digitalWrite (LEDNORMAL, LOW);
     pinMode(LEDFALTA, OUTPUT);
     digitalWrite(LEDFALTA, LOW);

     pinMode(2,INPUT); //porta 2 que detecta se está em estado alto ou baixo
     digitalWrite(2,LOW);  
     contador = 0;
     attachInterrupt(0, detect, RISING); //a interrupção 0 utiliza a porta 2 para atender a interrupção e caso haja a interrupção chama a função detect na subida do estado (LOW para HIGH)

    api_status = Agentuino.begin();

    if ( api_status == SNMP_API_STAT_SUCCESS ) {
          Agentuino.onPduReceive(pduReceived);
          delay(10);
          Serial.println("SNMP Agent Initiated...");
          return;
     } 
     else
     {
          delay(10);
          Serial.print("SNMP Agent failed!");
      }

}

void loop() {
  unsigned long contador_loop = contador; 
  unsigned long tempo = millis()+100; 
  while (tempo > millis()); 
  if (contador > contador_loop) //se chamar a interrupção detect contador ficará maior que contador_loop
  {
     digitalWrite(LEDNORMAL, HIGH); //se tiver tensão no circuito acende Led Verde
     digitalWrite(LEDFALTA, LOW); //se tiver tensão no circuito apaga Led vermelho
     statustensao = 1;
  }
  else
  {
     contador = 0;
     digitalWrite(LEDFALTA, HIGH); //se não tiver tensão no circuito acende Led vermelho
     digitalWrite(LEDNORMAL, LOW); //se não tiver tensão no circuito apaga Led verde   }
     statustensao = 0;
  }
  Agentuino.listen();
  loctensao = statustensao;  
}

void detect() {
   contador++; 
}

Com isso basta configurar o Zabbix para ler via SNMP a variável tensao e acionar uma trigger se o valor for igual a zero (falta tensão).

Configuramos um gráfico para visualizar:




Pessoal, por enquanto é só. Quaisquer dúvidas estamos aqui. No próximo post iniciaremos um novo projeto.


sábado, 25 de abril de 2015

Monitoramento de tensão - código

Olá pessoal,

Continuando o projeto de monitoramento de tensão vamos ao código:

byte LEDNORMAL = 3; //pino do Led verde (ENERGIA NORMAL)
byte LEDFALTA = 4; //pino do Led vermelho (FALTA DE ENERGIA)

volatile unsigned long contador; //variável controlada através da interrupção na porta 2

void setup() {
     pinMode(LEDNORMAL, OUTPUT);
     digitalWrite (LEDNORMAL, LOW);
     pinMode(LEDFALTA, OUTPUT);
     digitalWrite(LEDFALTA, LOW);

     pinMode(2,INPUT); //porta 2 que detecta se está em estado alto ou baixo
     digitalWrite(2,LOW); 
     contador = 0;
     attachInterrupt(0, detect, RISING); //a interrupção 0 utiliza a porta 2 para atender a interrupção e caso haja a interrupção chama a função detect na subida do estado (LOW para HIGH)
}

void loop() {
  unsigned long contador_loop = contador;
  unsigned long tempo = millis()+100;
  while (tempo > millis());
  if (contador > contador_loop) //se chamar a interrupção detect contador ficará maior que contador_loop
  {
     digitalWrite(LEDNORMAL, HIGH); //se tiver tensão no circuito acende Led Verde
     digitalWrite(LEDFALTA, LOW); //se tiver tensão no circuito apaga Led vermelho
  }
  else
  {
     contador = 0;
     digitalWrite(LEDFALTA, HIGH);
//se não tiver tensão no circuito acende Led vermelho

      digitalWrite(LEDNORMAL, LOW); //se não tiver tensão no circuito apaga Led verde   }
}

void detect() {
   contador++;
}



Créditos do código: Renato Aloi

Qualquer dúvida postem aqui ou no Facebook ok?

No próximo post vamos ver como utilizar o Agentuino + Zabbix também para apresentar graficamente o monitoramento de tensão.

Até mais pessoal!
 

 

sábado, 18 de abril de 2015

Monitoramento de tensão - circuito de detecção de tensão

Olá pessoal!



Vamos para a implementação do monitor de tensão e o primeiro passo é montar o circuito detector de tensão. A idéia é monitorar um circuito elétrico (tomada ou derivação) quanto à presença de tensão ou não e fazer com que o Arduino perceba estes estados através de uma de suas portas. Temos que colocar alguns parâmetros no projeto para que o circuito detector trabalhe de forma flexível e segura:
1) Tensão a ser monitorada: pode ser 110V ou 220V. No projeto optamos por trabalhar com ambas as tensões.
2) Proteção dos circuitos: como estamos monitorando um circuito elétrico é fundamental implementarmos algumas proteções aos circuitos diretamente ligados ao Arduino.

Detalhes construtivos:

1) Caixa para acomodação dos componentes: optamos por utilizar uma caixa 20x20 do sistema VID da Tigre.




2) Conector fêmea para cabo de energia: tínhamos sobrando esses cabos com conector fêmea para cabo de energia e decidimos utilizá-lo para poder conectar cabos de energia com o novo padrão e se for preciso também conectar cabos de energia com padrão antigo. Se a tomada a ser monitorada for do padrão novo utiliza-se um cabo de energia com plug no padrão novo! Se não utilize um cabo do padrão antigo.



3) Protoboard para conexão dos componentes.




4) Borne para ligação da entrada de energia no optoacoplador.





Detalhes do circuito:

1) Utilização de optoacoplador: como estamos trabalhando com tensões de 110V AC e 220V AC convém protegermos o Arduino caso haja algum problema nesses circuitos. O optoacoplador utilizado foi o 4N25.
2) Resistor de 220K: limitador de corrente na entrada do optoacoplador.
3) Resistor pull-down de 10K.
4) 2 LEDS (um para indicar presença de tensão (led verde) e outro para indicar falta de tensão (led vermelho).


Esquema de ligação:




Como funciona:

O circuito que se quer monitorar a tensão é conectado através dos pinos 1 e 2 do optoacoplador e utilizando-se de um resistor limitador de corrente. Nos pinos 4 e 5 são ligados ao 5V e GND do Arduino e utilizando-se de um resistor pull-down para sempre termos sinais em nível ALTO ou BAIXO, sem níveis intermediários. Se há tensão no circuito o LED do optoacoplador é iluminado (está conectado nos pinos 1 e 2 do optoacoplador) e do outro lado temos um fototransistor e quando exposto à luz a sua base é excitada por esse facho de luz, fazendo com que os pinos 4 e 5 passem a conduzir. No pino 4 derivamos uma conexão à porta 2 do Arduino que ficará em estado alto se o circuito tiver tensão e em estado baixo se não estiver com tensão.
No Arduino optamos por trabalhar com interrupções na porta 2 para detectar essas mudanças de estado da porta e agir conforme essas mudanças ocorrem.

No próximo post vamos ao código! Não deixem de acompanhar!

Até mais!

quinta-feira, 19 de março de 2015

Novo projeto - monitoramento de tensão

Olá pessoal,

Hoje vamos iniciar com as experiências que tive em uma outra necessidade que tive no dia-a-dia do meu trabalho. Primeiramente vamos entender a problemática e a solução que obtive utilizando Arduino.
Temos diversos equipamentos de rede (switch) que são conectados a pequenos nobreaks para que em momentos de quedas rápidas de energia o switch não seja desligado. Se há queda de energia isso faz com que o switch seja reinicializado e isso demora um tempo e a rede fica indisponível enquanto ele não volta ao seu estado funcional.
Com a utilização destes pequenos nobreaks o grande problema ocorre quando há uma queda mais prolongada de energia, consumindo boa parte da carga da bateria e também muitas vezes esgotando totalmente. Como esses nobreaks muitas vezes só desligam com a carga totalmente esgotada ocorreram várias vezes das baterias dos nobreaks ficarem danificadas por esse esgotamento. Uma parte da rede elétrica em que estes nobreaks e switches ficam conectados são conectados em um estabilizador de 100KVA em cabine e algumas vezes o estabilizador desarma e não reaciona (ele tem uma chave que desarma e o rearme é manual). A outra parte da rede elétrica não está no estabilizador (rede não estabilizada) e depende diretamente da energia vinda diretamente da rua.
De tudo isso o complicado é saber quando e onde ocorreu o problema. É uma falha da concessionária de energia? É problema no estabilizador como mencionado acima? O quão frequente são estas falhas?
Com esses problema surgiu a idéia de implementar uma espécie de monitoramento da energia em determinados pontos da rede elétrica para determinar quando e onde caiu a energia. A idéia é que se colocarmos um monitor de energia em algum ponto da rede elétrica que está conectada com o estabilizador saberemos que provavelmente em uma queda de energia deste ponto provavelmente o problema ocorreu no estabilizador como mencionado acima ou o circuito que este ponto de rede elétrica caiu (por desarme de disjuntor, problema na tomada, etc).Se conectarmos um monitor de energia em um ponto da rede elétrica que não está conectada ao estabilizador e houver uma queda de energia detectada provavelmente a energia vinda diretamente da concessionária falhou ou o circuito que este ponto de rede elétrica caiu (por desarme de disjuntor, problema na tomada, etc). Então temos:
1 monitor de energia conectado à rede elétrica estabilizada.
1 monitor de energia conectado à rede elétrica não estabilizada.

Temos as seguintes situações com essa configuração de monitores:
1) Queda de energia detectada pelo monitor conectado à rede estabilizada: provavelmente ocorreu queda do estabilizador ou do circuito.
2) Queda de energia detectada pelo monitor conectado à rede não estabilizada: provavelmente ocorreu um problema geral elétrico.
3)Queda de energia detectada pelo monitor conectado à rede estabilizada e também queda de energia detectada pelo monitor conectado à rede não estabilizada: provavelmente há falha de energia vinda diretamente da concessionária de energia.

Como implementar esse monitor? O escolhido foi: com Arduino! Basta implementar um circuito detector de tensão e monitorar. Monitorar como? Podemos utilizar igualmente o monitoramento implementado para temperatura que ao invés de monitorar temperatura monitora tensão e notifica via e-mail e SMS.
No próximo post vamos entrar nos detalhes de implementação do monitor de tensão utilizando Arduino.
Até a próxima.