quinta-feira, 23 de junho de 2016

Tape changer - mudança no projeto



Bom dia pessoal,

Vamos lá para mais um post sobre e o projeto do tape changer e no último post descrevi as dificuldades de se implementar um braço robótico. Neste post vou descrever a mudança radical que tive de implementar para resolver as dificuldades. Vamos lá:

1) Mudança: utilização de motores de passo ao invés de servos para movimentação retilínea da garra.

Uma decisão que tive tomar  foi a de utilizar motor de passo ao invés de servos. Agora qual motor de passo utilizar? Em um primeiro momento resolvi começar a fazer testes com motores de passo para drives de CD/DVD.
















Pensei: "Poxa que legal... funciona...e com Arduino ainda". Uma dificuldade que encontrei para utilizar estes motores de passo foi a dificuldade de implementar um fuso mais comprido a ponto de conseguir mover a fita ou colocá-la no drive LTO. Também pensei em utilizar dois motores de passo e dois fusos para fazer a abertura e fechamento da garra porém sem sucesso.
De repente tive um insight: esse movimento retilíneo está bastante presente em projetos de CNC!!! Comecei a pesquisar as implementações de fusos e motores de passo para movimentar em eixos nos projetos de CNC e encontrei um canal excelente no Youtube - o canal Eletrônica Hoje:





Agradeço a ajuda!!!


2) Implementação do movimento retilíneo:

Usei como base este vídeo:



O motor de passo que escolhi foi esse:
Motor de passo Nema 17




Para acionamento e controle do motor de passo escolhi o driver A4988:

Driver A4988














Segue abaixo esquema de ligação do driver ao motor de passo:















Atente para o esquema onde é realizada a ligação de alimentação externa (pinos VMOT e GND) que exige a conexão de um capacitor de 100 microFarad para dar maior estabilidade no fornecimento de tensão. Os enrolamentos do motor de passo devem ser ligados nos pinos 2B,2A,1A e 1B.
Maiores detalhes de ligação estão em alguns vídeos do canal Eletrônica Hoje:

a) Ligação dos motores de passo de 4 ou 6 fios:




b) Ajuste de corrente dos drivers A4988 - Parte 1:





c) Ajuste de corrente dos drivers A4988 - Parte 2:





A ligação com o Arduino e o código para testes são estes:

http://www.arduinoecia.com.br/2015/03/controle-motor-de-passo-bipolar-driver-A4988.html


É importante fazermos um teste do motor de passo sem carga para verificar o comportamento do motor para depois fazermos a conexão do fuso.

No próximo post vamos ver como fazer o acoplamento do motor de passo ao fuso que transmitirá o movimento para o conjunto a ser movimentado.

Até mais!

Agradecimentos ao Canal Eletrônica Hoje e ao site Arduino e Cia.

quarta-feira, 22 de junho de 2016

Tape changer com braço robótico - parte 2

Olá pessoal! Neste post vou contar para vocês um pouco da experiência que tive para implementar o projeto de tape changer (trocador de fita) utilizando braço robótico. Bom, vamos lá!
Como não tenho noção nenhuma a ponto de construir a estrutura do braço robótico resolvi comprar uma em alumínio...
Comprei este no Aliexpress:





Não veio com instruções de montagem porém o vendedor me enviou por e-mail as instruções (em chinês) mas muito bem detalhado e não foi difícil a montagem.

Depois de montado comprei os servos (6 servos) MG995 e os montei na estrutura. A partir daí fomos aos testes.


Realizadas as ligações dos servos atentamos para a corrente exigida pelos servos e tensão de alimentação e precisamos de alimentação externa. Deve-se prestar atenção na interligação do terra do Arduino com o terra da alimentação externa dos servos.
Fizemos o controle da movimentação dos servos através de potenciômetros e notamos que determinados servos eram mais exigidos que outros em termos de corrente e também que o movimento necessário do braço e da garra para remover a fita ou colocar tem que ser retilíneo (por conta da fita), o que dificultou bastante o teste pois teríamos que acionar vários servos ao mesmo tempo para reproduzir este movimento retilíneo. Somada a esta dificuldade temos também tivemos que recorrer a uma fonte de alimentação com maior capacidade de fornecimento de corrente.





Devido às dificuldades de implementação chegamos a conclusão que era necessário rever o projeto e pensar na possibilidade de se usar motores de passo para realizar o movimento retilíneo da garra. É que fizemos e veremos no próximo post como foi essa mudança na implementação.

Até a próxima!



terça-feira, 15 de março de 2016

Novo projeto: tape changer com Arduino

Olá pessoal,

Depois de um bom tempo sem postar hoje coloco um novo projeto com Arduino: um tape changer com drive de fita LTO. Até agora é o projeto mais complexo que estou implementando e ainda não está terminado. Trocadores de fita (ou biblioteca de fitas) são equipamentos que armazenam fitas magnéticas para fins de backup e trocam a fita automaticamente no drive quando finalizam uma gravação. Vocês podem dar uma olhada no funcionamento de um desses:


Uma biblioteca de fitas não é barata...

Vamos lá então pessoal... a idéia inicial era de usar um braço robótico para puxar e trazer a fita do drive e para o drive. Nos próximos posts vou relatar como foi a experiência disso. Depois de várias tentativas mal sucedidas de se utilizar braço robótico acabei por modificar totalmente o projeto.

Abraços,

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.