Detecção de intrusão de porta usando Nicla Voice Arduino
Capa do Post blog sistema de detecção de intrusão de porta usando nicla voice e portenta h7

Sistema de detecção de intrusão de porta usando Nicla Voice e Portenta H7 Deixe um comentário

A segurança sempre foi um fator muito importante para o nosso bem-estar, desde o pessoal até o material. Manter nossos bens seguros é algo com o qual lidamos todos os dias, seja em nossos carros, armários, computadores ou casas. Garantimos que tudo esteja trancado, mas há momentos em que isso não é suficiente. Num mundo tão conectado, onde temos muitas informações na palma da mão, seria útil ter o status daquilo que garantimos de uma maneira mais analógica, como a porta da frente de nossa casa. Aproveitar o microfone integrado do Nicla Voice Arduino Pro proporciona a possibilidade de construir esse tipo de sistema de proteção.

Foto da conexão wifi-fi bluetooth e cabo

Objetivos

O objetivo deste tutorial é apresentar um sistema de detecção e monitoramento de intrusos para a porta da frente de uma casa usando a combinação de Nicla Voice e Portenta H7 como host, juntamente com a Arduino Cloud. Os objetivos do projeto são os seguintes:

  • Analisar os sons ao redor com o microfone incorporado do Nicla Voice e executar algoritmos de inteligência artificial localmente.
  • Identificar corretamente se uma porta foi aberta de maneira comum ou se sofreu uma tentativa forçada.
  • Relatar eventos de abertura e detecção de intrusos por Bluetooth Low Energy para um Host.
  • O host deve encaminhar os dados do Nicla Voice para a Arduino Cloud usando uma conexão à Internet (Wi-Fi neste caso).
  • Criar um dashboard na Arduino Cloud que sincroniza em tempo real para informar e alertar o usuário.

Coletar dados do mundo real para treinar um modelo de aprendizado de máquina.

Requisitos de Hardware e Software

Para seguir com este tutorial você irá precisar dos seguintes itens listados abaixo:

Requisitos de Hardware e Software Nica Voice Arduino e Portenta H7

Além disso, você precisará utilizar os seguintes softwares:

O Modelo de Aprendizado de Máquina executado no Nicla Voice Arduino Pro

O aprendizado de máquina é uma forma de programação na qual fazemos com que nosso dispositivo processe dados brutos de sensores e aprenda com base em características significativas extraídas que serão posteriormente usadas para identificar ou prever cenários originalmente treinados.

Para identificar quando a porta está sendo aberta ou quando está sendo forçada, treinamos um modelo de aprendizado de máquina usando a integração das Ferramentas de Aprendizado de Máquina que será executado repetidamente no Nicla Voice.

Primeiro, gravamos o Nicla Voice com um firmware de ingestão de áudio para gravar e enviar amostras para nosso projeto de Ferramentas de Aprendizado de Máquina de três cenários diferentes que queremos identificar posteriormente.

Aqui está o design do nosso modelo:

Design do modelo nicla voice

Como estamos utilizando o Nicla Voice, devemos seguir o design do modelo para ser suportado pelo processador neural Syntiant NDP120 embarcado, observando essas características.

Bloco de Dados de Série Temporal:

  • Tamanho da janela: 968 ms
  • Aumento da janela: 484 ms
  • Frequência: 16000 H

Bloco de Processamento:

  • Áudio (Syntiant): Este bloco DSP calcula características de energia do filtro de Mel a partir de sinais de áudio.

Bloco de Aprendizado:

  • Classificação: Este bloco inclui a arquitetura de Rede Neural para aprender padrões a partir de dados de áudio.

Aqui está uma representação gráfica de como as amostras parecem antes e depois do processamento de sinal digital:

raw audio

Nossas três classes são:

  • Aberta: gravamos o som da porta sendo aberta.
  • Forçada: gravamos o som da fechadura da porta sendo atingida com uma ferramenta metálica.
  • Z_openset: gravamos o ruído do ambiente quando nada está acontecendo e sons desconhecidos como música e conversas.

Aqui está a configuração do classificador de rede neural para esta aplicação:

configuração do classificador

Após o treinamento do modelo com muitas amostras de uma porta sendo aberta, sendo forçada e nada acontecendo (z_openset), obtivemos resultados consideráveis, evidenciados na “Matriz de Confusão”, com uma precisão de 97,4% alcançada com um conjunto de dados de validação.

Importante! O desempenho do modelo pode ser afetado se a aplicação for implementada em um ambiente muito diferente daquele usado para o treinamento. É recomendável alimentar os conjuntos de dados com novas amostras e re-treinar o modelo para uma implantação nova e aprimorada.

Para uma nova implantação do modelo, use o carregador Syntiant e substitua o arquivo ei_model.synpkg, que você pode encontrar dentro da pasta baixada, pelo seu próprio.

Configuração do Sistema de Detecção de Intrusos com Portenta H7 e Nicla Voice Arduino Pro

Nesta aplicação, não precisamos de nenhum diagrama de fiação específico além do Nicla Voice e do Portenta H7.

O Nicla Voice será fixado na porta guardada e perto da fechadura, o host Portenta H7 ficará em algum lugar com boa cobertura Wi-Fi e não muito longe do Nicla Voice, devido à faixa estreita do Bluetooth Low Energy de alguns metros.

configuração do sistema de detecção de intrusos com Nicla Voice Arduino e Portenta H7

O Nicla se comunicará com o Portenta H7 via Bluetooth Low Energy, anunciando qualquer evento para o host, que receberá e encaminhará a notificação para a Arduino Cloud usando Wi-Fi.

O Nicla Voice é alimentado por uma bateria LiPo dentro de seu invólucro. O Portenta H7 será alimentado por um adaptador de energia USB de 5 VDC. Embora o Portenta H7 possa funcionar por longos períodos sem precisar de resfriamento externo, é sempre recomendável manter os dispositivos que estão funcionando 24/7 o mais frios possível, tendo o ventilador de refrigeração conectado ao invólucro Portenta H7.

Visão Geral do Sistema de Detecção de Intrusos

O Nicla Voice anexado à porta executa um modelo de aprendizado de máquina que ouve os ruídos ao redor e procura por sons conhecidos, como a porta sendo aberta ou a fechadura da porta sendo atingida com uma ferramenta metálica, por exemplo, para simular um processo de forçamento.

Se os sons forem reconhecidos com uma certeza superior a 70%, o evento será considerado como ocorrido, e uma notificação Bluetooth Low Energy será enviada para o host Portenta H7, atualizando o status da porta. O Portenta H7 será responsável por receber a notificação do evento da porta e atualizar as variáveis do painel na IoT Cloud imediatamente, para que o usuário possa estar ciente em tempo real de qualquer mudança. 

Além dessas características, o dashboard da aplicação mostrará um histórico de eventos, juntamente com uma “Notificação de Alerta de Intrusão“, o status de conexão Bluetooth Low Energy entre ambos os dispositivos e o nível da bateria do Nicla Voice, para que possamos saber quando recarregá-lo.

Código do Nicla Voice Arduino Pro

Vamos examinar algumas seções importantes do código para tornar esta aplicação totalmente operacional. Começaremos com as bibliotecas necessárias.

  • Incluindo as bibliotecas NDP.h habilitará e executará o Neural Decision Processor (NDP120), incluído no BSP do Nicla Voice.
  • Incluindo ArduinoBLE.h habilitará a comunicação Bluetooth® Low Energy. Instale-a pesquisando-a no Gerenciador de Bibliotecas.

Os serviços e características de Bluetooth Low Energy são padronizados para o uso específico das funcionalidades desta aplicação. O serviço é definido como Alerta Imediato, o que o torna ideal para o uso que daremos ao notificar sobre a abertura de uma porta ou evento de forçamento. Além disso, definimos duas características, uma para o Nível de Alerta que será anunciado entre ambos os eventos, e outra para o Nível de Bateria, que anunciará o nível de bateria do Nicla Voice para o host. Observe que elas possuem UUIDs específicos e padronizados de Bluetooth Low Energy.

#include "NDP.h"
#include <ArduinoBLE.h>

// Serviço de Alerta BLE
BLEService alertService("1802");  // Alerta imediato

// Característica BLE Alerta
BLEUnsignedCharCharacteristic alertLevel("2A06", BLERead | BLENotify);

// Característica de Nível de Bateria Bluetooth® Low Energy
BLEUnsignedCharCharacteristic batteryLevelChar("2A19", BLERead | BLENotify);

O Nicla Voice’s integrado NDP precisa de alguns arquivos armazenados na flash externa da placa, que são:

  • mcu_fw_120_v91.synpkg
  • dsp_firmware_v91.synpkg
  • ei_model.synpkg

Importante! Os arquivos devem ser nomeados exatamente como mostrado acima.

Aqui você pode baixar esses arquivos, incluindo o modelo de Machine Learning já treinado e as ferramentas de upload.

Após baixar os arquivos necessários, para armazená-los na memória do Nicla Voice, você deve seguir as etapas detalhadas aqui.

Importante! Esses arquivos não serão sobrescritos após qualquer atualização do esboço.

// Carregamento de firmware e modelos de NDP
NDP.begin("mcu_fw_120_v91.synpkg");
NDP.load("dsp_firmware_v91.synpkg");
NDP.load("ei_model.synpkg");
Serial.println("Pacotes carregados");
NDP.getInfo();
Serial.println("Configurar microfone");
NDP.turnOnMicrophone();

A principal responsabilidade do código do Nicla Voice é ouvir e identificar os sons treinados. A seção de código abaixo é encarregada de comparar a categoria inferida e tomar uma determinada ação com base nisso.

No caso em que o Nicla detecta a abertura da porta, o parâmetro de rótulo será alterado para NN0:opened, isso acionará um comando de envio de alerta de Bluetooth Low Energy seguido por uma pausa na escuta para evitar alertas duplicados e um piscar do LED verde para indicar visualmente o evento. O mesmo ocorre para o rótulo NN0:forcing, com a diferença de que, neste caso, o LED pisca em vermelho e a mensagem de alerta é alterada.

/**
Callback de Interrupção de Inferência a ser executado a cada inferência acionada,
ele controla os LEDs embutidos e envia os alertas através do BLE.

Rótulos possíveis: NN0:opened, NN0:forcing

Alertas: 1 = alerta leve (para porta aberta), 2 = alerta alto (para detecção de intruso)

@param label O rótulo da categoria inferida
/
void BLEsend(char* label) {

  if (strcmp(label, "NN0:opened") == 0) {
    alertLevel.writeValue(1);

    NDP.noInterrupts();
    nicla::leds.begin();
    nicla::leds.setColor(green);
    delay(3000);
    nicla::leds.end();
    NDP.interrupts();
  }
  if (strcmp(label, "NN0:forcing") == 0) {
    alertLevel.writeValue(2);
    NDP.noInterrupts();
    nicla::leds.begin();
    nicla::leds.setColor(red);
    delay(3000);
    nicla::leds.end();
    NDP.interrupts();
  }
  if (!lowestPower) {
    Serial.println(label);
  }
}

Esses métodos são usados para atualizar as características desta aplicação.

alertLevel.writeValue(x);  // x = 1 se a porta estiver aberta ou x = 2 se a porta estiver forçada
batteryLevelChar.writeValue(HigherBatteryLevel);

Código do Portenta H7 Arduino Pro

O Portenta H7 precisa das seguintes bibliotecas:

  • ArduinoIoTCloud.h, que lida com a conexão Arduino Cloud e a publicação de variáveis de projeto. Pode ser instalado diretamente no Gerenciador de Bibliotecas do Arduino.
  • Arduino_ConnectionHandler.h, que gerencia a conexão Wi-Fi® e pode ser instalado diretamente no Gerenciador de Bibliotecas do Arduino.
  • thingProperties.h, gerado automaticamente pelo Arduino Cloud.
Na seção de parâmetros globais, temos duas variáveis que armazenarão o status local dos alertas e o nível da bateria do Nicla Voice.
#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>
#include "thingProperties.h"
#include <ArduinoBLE.h>

#define DEBUG false
// Parâmetros Globais
byte BatteryValue = 0;  // último nível de bateria recebido.
byte AlertValue = 0;    // último valor de alerta recebido.

No arquivo thingProperties.h, encontramos a definição de várias variáveis importantes para conectar adequadamente nosso projeto à internet e à Arduino Cloud.

  • Devemos atualizar a variável THING_ID com o ID do Thing na Arduino Cloud.
  • Para uma conexão bem-sucedida à internet, devemos atualizar as variáveis SSID e PASS com nossas credenciais Wi-Fi.

Na função initProperties(), listamos as variáveis que serão monitoradas na IoT Cloud e seu método de atualização, que neste caso é ON_CHANGE, o que significa que o Portenta H7 enviará o valor de qualquer variável para a nuvem apenas se ela for alterada em relação ao valor anterior.

const char THING_ID[] = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // Arduino Cloud Thing ID

const char SSID[]     = "xxxxxxxx";    // SSID da rede
const char PASS[]     = "xxxxxxxx";    // Senha da rede

String DoorEvent = "Sistema iniciado";  
int battery;
bool BLEstatus;
bool alertStatus;

void initProperties(){
  ArduinoCloud.setThingId(THING_ID);
  ArduinoCloud.addProperty(DoorEvent, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(battery, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(BLEstatus, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(alertStatus, READ, ON_CHANGE, NULL);
}

WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);

A principal responsabilidade do código do Portenta H7 é conectar-se ao Nicla Voice e estar ciente de novas notificações para encaminhá-las para a Nuvem. Para alcançar isso, a primeira coisa feita pelo Portenta é inicializar a comunicação Bluetooth Low Energy, em seguida, inicializar o serviço Arduino Cloud e começar a escanear periféricos.

// Inicializar BLE
  if (!BLE.begin()) {
    Serial.println("Falha ao iniciar o BLE!");
    while (1) {
    }
  }

 // Definido em thingProperties.h
  initProperties();

  // Conectar à Arduino Cloud
  if (!ArduinoCloud.begin(ArduinoIoTPreferredConnection)) {
    Serial.println("Falha ao iniciar ArduinoCloud!");
  }

  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

    // Iniciar escaneamento para periféricos
  BLE.scan();
  Serial.println("Escaneando periféricos.");

O processo de escaneamento será interrompido automaticamente quando encontrar um dispositivo chamado “Nicla Lock”, e então ele procurará pelos seus serviços e características com a função NiclaLockHandler().

void loop() {

  // Verificar se um periférico foi descoberto
  BLEDevice peripheral = BLE.available();

  // Acender o LED verde se a placa estiver conectada com sucesso à Nuvem. Ligado com baixa intensidade.
  if (ArduinoCloud.connected()) {
    digitalWrite(LEDG, LOW);
  } else {
    digitalWrite(LEDG, HIGH);
  }

  if (peripheral) {
    // Periférico descoberto, imprimir endereço, nome local e serviço anunciado
    Serial.print("Encontrado ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    // Verificar se o periférico é um Nicla Lock:
    if (peripheral.localName() == "Nicla Lock") {
      // Parar o escaneamento
      BLE.stopScan();

      // Manipulador de conexão do nó Nicla Voice
      NiclaLockHandler(peripheral);

      // Periférico desconectado, iniciar o escaneamento novamente
      BLE.scan();
    }
  }
  ArduinoCloud.update();
}

Para apenas se conectar ao Nicla Voice, o Portenta procura pelo “Serviço de Alerta” específico usando seu UUID 1802 e pelas características necessárias, o “Nível da Bateria” usando o UUID 2A19 e o “Nível do Alerta” usando o UUID 2A06.

// Descobrir atributos do periférico
  Serial.println("Procurando pelo serviço 1802 ...");

  if (peripheral.discoverService("1802")) {
    Serial.println("Serviço descoberto");
  } else {
    Serial.println("Falha na descoberta de atributos.");
    peripheral.disconnect();

    while (1)
      ;
    return;
  }

  // Recuperar as características da chave simples
  BLECharacteristic batteryLevelChar = peripheral.characteristic("2A19");
  BLECharacteristic alertLevel = peripheral.characteristic("2A06");

  // Inscrever-se no processo de características da chave simples
  Serial.println("Inscrição na característica da chave simples ...");
  if (!batteryLevelChar || !alertLevel) {
    Serial.println("nenhuma característica de chave simples encontrada!");
    peripheral.disconnect();
    return;
  } else if (!batteryLevelChar.canSubscribe() || !alertLevel.canSubscribe()) {
    Serial.println("característica de chave simples não é inscritível!");

    peripheral.disconnect();
    return;
  } else if (!batteryLevelChar.subscribe() || !alertLevel.subscribe()) {
    Serial.println("falha na inscrição!");
    peripheral.disconnect();
    return;
  } else {
    Serial.println("Inscrito no Nível de Bateria e Característica de Alerta");
  }

Finalmente, o Portenta verifica continuamente se uma característica foi atualizada para carregá-la na Nuvem.

// enquanto o periférico estiver conectado
  while (peripheral.connected()) {
    
    // verificar se o valor da característica foi atualizado
    if (batteryLevelChar.valueUpdated()) {

      batteryLevelChar.readValue(BatteryValue);

      Serial.print("Nível da Bateria: ");
      Serial.print(BatteryValue);
      Serial.println(" %");

      battery = BatteryValue;
    }

    // verificar se o valor da característica foi atualizado
    if (alertLevel.valueUpdated()) {

      alertLevel.readValue(AlertValue);

      Serial.print("Alerta: ");
      Serial.println(AlertValue);

      
      if (AlertValue == 1) {    // se o Alerta = 1 significa que a porta foi aberta
        control = !control;     // como as variáveis são atualizadas se mudarem, adicione um ponto "." simples para poder atualizá-las se ocorrerem duas vezes consecutivas.
        if (control) {
          DoorEvent = "Porta aberta";
        } else {
          DoorEvent = "Porta aberta.";
        }

        alertStatus = false;

      } else if (AlertValue == 2) {   // se o Alerta = 2 significa que a porta foi forçada
        control = !control;           // como as variáveis são atualizadas se mudarem, adicione um ponto "." simples para poder atualizá-las se ocorrerem duas vezes consecutivas.
        if (control) {
          DoorEvent = "Intruso detectado!";
        } else {
          DoorEvent = "Intruso detectado!.";
        }

        alertStatus = true;
      }
    }

    // desligar o LED verde se desconectado da Nuvem.
    if (ArduinoCloud.connected()) {
      digitalWrite(LEDG, LOW);
    } else {
      digitalWrite(LEDG, HIGH);
    }

    ArduinoCloud.update();
  }

O Dashboard

Aproveitando a Arduino Cloud, podemos integrar sem problemas um dashboard simples, mas poderoso, para monitorar e visualizar o status do sistema em tempo real:

dashboard arduino cloud

Dentro do painel da Arduino Cloud, as variáveis do sistema podem ser monitoradas. Temos um indicador de nível de bateria acompanhado por um gráfico de séries temporais, um widget com aparência de bate-papo para armazenar os eventos historicamente, um LED vermelho que acende quando um intruso é detectado pelo sistema, e um LED verde para mostrar o status de conexão Bluetooth Low Energy entre o Nicla Voice e o hospedeiro Portenta H7.

Podemos acessar facilmente esse painel de um PC, telefone celular ou tablet de qualquer lugar, recebendo uma atualização instantânea onde quer que estejamos. Além disso, podemos configurar diferentes integrações para complementar nosso projeto, por exemplo, configurar uma automação do IFTTT para receber um e-mail, uma notificação no celular ou até mesmo acionar alguma automação, como acender todas as luzes em casa sempre que um alerta for disparado.

dashboard arduino cloud foto 2

Conclusão

Neste artigo, aprendemos como implementar um projeto Machine Learning Tools alimentado pelo Edge Impulse e pela Arduino Cloud na borda usando um Nicla Voice e um Portenta H7. Esta aplicação poderia ser uma demonstração simples de como o ambiente Arduino simplifica o fluxo de trabalho para desenvolver soluções inteligentes para resolver situações da vida real, integrando algoritmos “complexos” e poderosos com apenas alguns passos fáceis de seguir. Cobrimos o reconhecimento de som, comunicação Bluetooth Low Energy e monitoramento em tempo real na Nuvem.


Este post é uma tradução adaptada do artigo escrito por Christopher Mendez. O artigo original pode ser encontrado aqui.

Faça seu comentário

Acesse sua conta e participe