Sistema de Acesso Inteligente com Reconhecimento Facial para Desbloqueio
Componentes e Materiais
| Componente | Quantidade |
|---|---|
| Módulo WiFi Bolt IoT Bolt | 1 |
| Arduino UNO | 1 |
| Buzzer | 1 |
| Protoboard sem solda tamanho completo | 1 |
| Chave pushbutton SparkFun 12mm | 2 |
| LED 5mm Vermelho | 1 |
| LED 5mm Verde | 1 |
| Resistor 10k ohm | 2 |
| Resistor 330 ohm | 2 |
| Fios jumpers (genéricos) | 1 |
Ferramentas e Máquinas Necessárias
- Pistola de cola quente (genérica)
Aplicativos e Serviços Online
- Bolt IoT Bolt Cloud
- Microsoft Windows 10
- Microsoft Visual Studio
- Arduino IDE
- Face++
Sobre o Projeto
Bem-vindo, amigo curioso! Vivemos em uma era revolucionada pela internet onde agora é mais fácil do que nunca experimentar e inovar para criar ideias brilhantes que podem ter um impacto positivo em milhões ao redor do mundo.
Já quis adicionar um pouco de segurança extra às suas prateleiras, gavetas, guarda-roupas ou portas em casa? Quando se trata de inovação usando internet, entre milhares de plataformas e ferramentas disponíveis, duas que se destacam são Arduino e Bolt IoT. Neste projeto, vamos modificar uma prateleira padrão para ter um sistema de segurança que desbloqueia usando Verificação Facial. Vamos construir um Aplicativo Windows Forms em C# que pode armazenar, verificar e desbloquear rostos confiáveis. Ele usa FacePlusPlus API para verificação facial e API Bolt IoT Cloud para comunicar com o Módulo WiFi Bolt e Arduino. Vamos interligar o Módulo WiFi Bolt com um Arduino Uno, que controlará um motor servo para trancar/destrancar a porta.
Animado? Vamos começar.
Contexto
Fiz este projeto como parte do Desafio Inovação e Treinamento IoT, conduzido pela Internshala Trainings. O treinamento ajudou a entender o básico de lidar com serviços API, Programação Orientada a Objetos e, mais importante, usar o Módulo WiFi Bolt. Uma sinopse do Projeto Final feito como parte deste treinamento pode ser encontrada aqui. Muitos desses conceitos foram úteis durante o desenvolvimento deste projeto. Então um grande salve para a equipe da Internshala por tornar isso possível.
Passo 1: Construindo o Software
Vamos construir um Aplicativo Windows Forms usando Visual Studio. Esta aplicação roda em uma máquina Windows, e será responsável por gerenciar rostos autorizados, verificar um rosto usando a API FacePlusPlus e comunicar com o Módulo WiFi Bolt. Usaremos C# para codificar.
Inicie o Visual Studio e crie um novo projeto de Aplicativo Windows Forms. Se você é completamente novo no Visual Studio, recomendo aprender o básico de Desenvolvimento de Aplicativos Windows Forms usando Visual Studio. Este e este são bons recursos para começar.
Neste tutorial, explicarei apenas o código usando trechos do projeto que fazem as funções principais e importantes. Seria tedioso e desnecessário percorrer todo o código, pois a maior parte é autoexplicativa e bem documentada.
Nosso projeto Visual Studio faz uso de 3 bibliotecas para vários propósitos. Elas são:
- AForge .NET: Um framework .NET popular usado para processamento de imagens no Windows. Usamos para capturar imagens de uma webcam.
- Bolt IoT API .NET: Uma biblioteca cliente não oficial que escrevi em C#, para comunicar com a API Bolt Cloud.
- Newtonsoft JSON: Um framework JSON popular de alta performance para .NET. Usado para parsear respostas da API em nosso projeto.
NOTA: Para clareza no uso de diferentes métodos nas APIs acima, consulte suas respectivas documentações aqui, aqui e aqui.
Começando
Antes de pular para a codificação, precisamos configurar algumas coisas.
1. Credenciais da API Bolt Cloud
Se ainda não fez, acesse cloud.boltiot.com e crie uma conta. Uma vez logado, vincule seu Módulo WiFi com a Bolt Cloud. Para isso, baixe o App Bolt IoT Setup no seu celular. Siga as instruções no app para vincular seu dispositivo com sua conta. Isso envolve parear o Bolt com a rede WiFi local. Uma vez vinculado com sucesso, seu painel exibirá seu dispositivo. Agora você pode obter seu Device ID e API Key do painel.
2. Credenciais da API FacePlusPlus
Outro serviço de API no qual confiamos neste projeto é o FacePlusPlus API. É uma plataforma gratuita que oferece vários tipos de serviços de reconhecimento de imagem. Usamos para identificação facial. Crie uma conta e vá ao console FacePlusPlus. Vá em API Key sob Apps e clique em +Get API Key. Anote o recém-gerado API Key e API Secret.
Agora você deve ter o seguinte pronto:
private readonly string BOLT_DEVICE_ID = "BOLTXXXXXX";
private readonly string BOLT_API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
private readonly string FPP_API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
private readonly string FPP_API_SECRET = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
Criamos uma nova instância global da classe Bolt chamada myBolt, através da qual faremos todas as comunicações futuras com o Módulo WiFi:
myBolt = new Bolt(BOLT_API_KEY, BOLT_DEVICE_ID);
Dito isso, agora vamos ver como nossa aplicação executa algumas das funções principais.
1. Trancar/Destrancar Porta
Projetamos o circuito de forma que quando o Pino Digital 0 estiver HIGH, a porta deve trancar, e quando o Pino Digital 3 estiver HIGH, a porta deve destrancar. Isso ficará mais claro depois quando discutirmos os esquemáticos do circuito.
Para trancar, usamos o método DigitalMultiWrite da biblioteca para escrever valor HIGH no D0 e valor LOW no D3. Isso sinalizará o Arduino para trancar a porta. Similarmente para destrancar, escreveremos valor LOW no D0 e HIGH no D3. Isso sinalizará o Arduino para destrancar a porta. Discutiremos o código do Arduino e o design do circuito mais tarde neste tutorial.
Código que executa o travamento:
private async Task LockDoor() {
MultiPinConfig multiPinConfig = new MultiPinConfig();
MultiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.High); //Sinal de Travamento
multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.Low); //Sinal de Destravamento
await myBolt.DigitalMultiWrite(multiPinConfig);
multiPinConfig = new MultiPinConfig();
multiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.Low); //Sinal de Travamento
multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.Low); //Sinal de Destravamento
await myBolt.DigitalMultiWrite(multiPinConfig);
}
Código que executa o destravamento:
private async Task UnlockDoor() {
MultiPinConfig multiPinConfig = new MultiPinConfig();
multiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.Low); //Sinal de Travamento
multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.High); //Sinal de Destravamento
await myBolt.DigitalMultiWrite(multiPinConfig);
multiPinConfig = new MultiPinConfig();
multiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.Low); //Sinal de Travamento
multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.Low); //Sinal de Destravamento
await myBolt.DigitalMultiWrite(multiPinConfig);
}
2. Adicionar/Remover Rostos Confiáveis
Os dados de imagem do rosto confiável são codificados em uma string Base64 e armazenados localmente na máquina. Uma lista de nomes correspondentes de cada rosto também é armazenada. Em nosso programa, para adicionar um rosto, primeiro verificamos se há um rosto disponível no quadro atual. Fazemos isso usando a API Detect do FacePlusPlus. Ela retorna uma resposta JSON que conterá características do rosto detectado. Se nenhum rosto for detectado, a resposta será simplesmente []. Uma vez detectado um rosto, salvamos a string base64 codificada da imagem e o nome correspondente. Aqui está um vídeo demonstrativo de adição de um rosto confiável.
Remover um rosto é bem direto. Pressionar o botão remover excluirá os dados da imagem e o nome da lista salva.
Código que adiciona e salva a informação do rosto:
// Convertendo imagem para string base64 e adicionando à lista
ImageDataList.Add(ImageToBase64((Image)PreviewBox.Image.Clone()));
// Adicionando nome do rosto à lista
NameList.Add(FaceNameTextBox.Text.Trim());
// Salva os dados da imagem do rosto como string codificada em base, junto com seu nome
Properties.Settings.Default.Base64ImageData = ImageDataList;
Properties.Settings.Default.FaceNames = NameList;
Properties.Settings.Default.Save();
Código que remove a informação do rosto:
// Removendo informação do rosto na posição especificada na lista
NameList.RemoveAt(e.RowIndex);
ImageDataList.RemoveAt(e.RowIndex);
// Salvando a lista após remoção de um rosto
Properties.Settings.Default.FaceNames = NameList;
Properties.Settings.Default.Base64ImageData = ImageDataList;
Properties.Settings.Default.Save();
Confira o código no projeto anexado onde o processo é explicado como comentários em cada linha para ter uma ideia clara.
3. Verificação Facial
Verificamos se um rosto é confiável ou não usando a API Compare no FacePlusPlus. Durante este processo, iteramos linearmente através de cada rosto na lista salva e o comparamos com a imagem capturada. Se a API retornar uma confiança superior a 80%, destrancaremos a porta.
O código que faz essa comparação parece algo assim:
WebClient client = new WebClient();
byte[] response = client.UploadValues("https://api-us.faceplusplus.com/facepp/v3/compare", new NameValueCollection() {
{ "api_key", FPP_API_KEY },
{ "api_secret", FPP_API_SECRET },
{ "image_base64_1", face1Base64},
{ "image_base64_2", face2Base64}
});
string confidence = JObject.Parse(System.Text.Encoding.UTF8.GetString(response))["confidence"].ToString();
WebClient.UploadValues envia a requisição para a API FacePlusPlus junto com os dados de rosto codificados em base64 de dois rostos a serem comparados e nossas credenciais de API. A resposta é parseada usando a biblioteca Newtonsoft JSON e o valor confidence é obtido. Leia a documentação da API Compare para entender os argumentos claramente.
4. A Thread de Escuta da Campainha
Planejam fornecer um botão físico, algo como um botão de campainha, para que o usuário possa pressionar enquanto olha para a câmera para destrancar a porta. Para tornar isso possível, precisamos criar uma nova thread dedicada que escute continuamente por evento de pressionamento do botão de campainha.
Mais tarde neste tutorial, veremos como o botão é empregado e como ele fará o pino D4 do módulo WiFi Bolt ficar HIGH quando o botão for pressionado. Por enquanto, apenas assumiremos o acima. Então, nesta thread, continuamente DigitalRead o valor do pino D4. Se for HIGH, tomaremos isso como evento de campainha e faremos a captura e verificação facial.
Aqui está o código que rodará continuamente na thread de escuta da campainha:
while (ListenForBell) {
Response R = await myBolt.DigitalRead(DigitalPins.D4);
if (R.Value == "1") {
RingBell_Click(null, null);
Thread.Sleep(2000);
}
Thread.Sleep(2000);
}
Paramos e esperamos 2 segundos entre cada iteração. Caso contrário, esgotará rapidamente a cota de uso da API Bolt Cloud.
Passo 2: Construindo o Projeto Visual Studio
Baixe o projeto inteiro aqui. Abra o arquivo Facebolt Doorlock.sln no Visual Studio. Após a solução carregar, abra o arquivo Form1.cs e atualize o código com suas credenciais de API. Pressione o botão verde play chamado 'Start', para compilar e rodar o programa.
O programa permite selecionar entre dispositivos de câmera anexados ao sistema e ver um feed ao vivo da câmera. Você pode Adicionar/Remover um rosto confiável. Iniciar monitoramento facial. Uma vez que o programa verifica a conectividade do seu Dispositivo Bolt, você pode tocar a campainha ou trancar a porta diretamente do programa.
Tudo bem se você está confuso sobre como a verificação facial, travamento e destravamento funcionam no programa. Ficará mais claro quando virmos o design do esquema do circuito e o código do Arduino. Também vou detalhar o fluxo de eventos de cada operação no final.
Passo 3: Design do Circuito e Código Arduino
Em nosso circuito, pretendemos implementar os seguintes recursos:
- Indicação por LED vermelho e verde para estados de porta trancada e destrancada, respectivamente.
- Um botão pushbutton para atuar como interruptor de campainha. Quando pressionado, nossa aplicação WinForms deve verificar o rosto e abrir a porta após autenticação facial bem-sucedida.
- Outro botão pushbutton para trancar a porta.
- Um buzzer que bipa no evento de campainha e travamento da porta.
A conexão do circuito do nosso projeto é mostrada abaixo:
Se ainda não fez, baixe o Arduino IDE aqui e conecte seu Arduino ao sistema. Certifique-se de ter definido o modelo correto de Arduino e Porta nas configurações da IDE, antes de carregar o código.
Código Arduino:
#include <Servo.h>
#define ServoPin 4
#define LockSignalPin 2
#define UnLockSignalPin 3
#define BellButtonPin 5
#define LockButtonPin 8
#define RingBellSignalPin 6
#define BuzzerPin 7
#define GreenLedPin 9
#define RedLedPin 10
Servo myServo;
void setup() {
pinMode(LockSignalPin, INPUT);
pinMode(UnLockSignalPin, INPUT);
pinMode(BellButtonPin, INPUT);
pinMode(LockButtonPin, INPUT);
pinMode(BuzzerPin, OUTPUT);
pinMode(RedLedPin, OUTPUT);
pinMode(GreenLedPin, OUTPUT);
pinMode(RingBellSignalPin, OUTPUT);
digitalWrite(RedLedPin, LOW);
digitalWrite(GreenLedPin, LOW);
digitalWrite(RingBellSignalPin, LOW);
myServo.attach(ServoPin);
Serial.begin(9600);
}
void loop() {
int lockButton, lock, unlock, bell;
char snum[5];
lock = digitalRead(LockSignalPin);
unlock = digitalRead(UnLockSignalPin);
// Verifica se sinal de travamento do Bolt é HIGH
if(lock == HIGH) {
// Gira motor para posição trancada
myServo.write(120);
// Define indicações de LED
digitalWrite(GreenLedPin, LOW);
digitalWrite(RedLedPin, HIGH);
// Som de travamento no buzzer
digitalWrite(BuzzerPin, HIGH);
delay(1000);
digitalWrite(BuzzerPin, LOW);
delay(1000);
}
// Verifica se sinal de destravamento do Bolt é HIGH
else if(unlock == HIGH) {
// Gira motor para posição destrancada
myServo.write(0);
// Define indicações de LED
digitalWrite(GreenLedPin, HIGH);
digitalWrite(RedLedPin, LOW);
delay(2000);
}
bell = digitalRead(BellButtonPin);
if(bell == HIGH) // Usuário pressionou botão de campainha
{
// Sinaliza Bolt que botão de campainha foi pressionado
digitalWrite(RingBellSignalPin, HIGH);
// Um padrão de som de campainha!
digitalWrite(BuzzerPin, HIGH);
delay(100);
digitalWrite(BuzzerPin, LOW);
delay(20);
digitalWrite(BuzzerPin, HIGH);
delay(200);
digitalWrite(BuzzerPin, LOW);
delay(100);
digitalWrite(BuzzerPin, HIGH);
delay(100);
digitalWrite(BuzzerPin, LOW);
delay(20);
digitalWrite(BuzzerPin, HIGH);
delay(200);
digitalWrite(BuzzerPin, LOW);
delay(1500);
// Desliga o sinal
digitalWrite(RingBellSignalPin, LOW);
}
lockButton = digitalRead(LockButtonPin);
if(lockButton == HIGH) // Usuário pressionou botão de travar
{
// Gira motor para posição trancada
myServo.write(120);
// Define indicações de LED
digitalWrite(GreenLedPin, LOW);
digitalWrite(RedLedPin, HIGH);
// Som de travamento no buzzer
digitalWrite(BuzzerPin, HIGH);
delay(1000);
digitalWrite(BuzzerPin, LOW);
}
}
Fluxos de Eventos
Agora que temos tanto a aplicação WinForm quanto o design do Arduino prontos, vamos mergulhar no código e explorar o fluxo de controle de cada operação.
1. Pressionamento do Botão Campainha
2. Pressionamento do Botão Travar
Ambas as operações acima também podem ser executadas diretamente da Aplicação Windows Forms.
Aqui, podemos observar que o Módulo WiFi Bolt serve como uma importante interface sem fio entre a Aplicação Windows Forms e o Arduino. O uso da API Bolt Cloud nos permite estender nosso projeto e construir aplicações em outras plataformas como Android e destrancar a porta usando nossos telefones! Essa flexibilidade é o poder da IoT e da Plataforma Bolt.
Agora que completamos a parte de design de software, vamos em frente e construir um mecanismo de porta travável.
Passo 4: Construindo o Hardware
Tenho um sapateiro por aí, então neste projeto vou usá-lo para demonstração do travamento. Você pode usar uma prateleira, uma porta, um guarda-roupa ou qualquer coisa que tenha um mecanismo de travamento hackeável. É realmente com você.
Precisamos construir um mecanismo de acoplamento que conecte nosso motor servo com a trava. Para isso, minha ideia é usar um pescoço cortado de uma garrafa e a tampa de outra garrafa. Anexe o pescoço da garrafa ao motor servo e a tampa à trava. Então os acoplaremos usando uma linha de nylon. Isso resultará na ação de trancar/destrancar sempre que o motor girar.
O pescoço de garrafa necessário com um furo furado na tampa parece algo como mostrado abaixo. Anecaremos isso ao eixo de travamento do sapateiro.
A tampa de outra garrafa deve ser anexada ao motor servo. Usamos fios de cobre para conectar a tampa ao eixo giratório do motor.
Agora precisamos acoplar estes dois. Para isso usamos linha de nylon. Faça um laço usando a linha com o comprimento necessário e prenda a linha em ambas as tampas.
Uma vez acoplados, eles podem causar uma ação de rotação mútua:
Agora que temos nosso mecanismo de rotação pronto, é hora de hackear a trava e fixar nosso pescoço de garrafa nela. Furamos um furo nele, então tudo que precisamos fazer é desaparafusar o eixo de travamento do sapateiro, colocar o pescoço da garrafa acima dele e reaparafusar a trava de volta apertado.
Agora a única coisa restante é fixar o motor servo ao sapateiro. Usaremos uma pistola de cola quente para selar o motor no sapateiro.
Após ajustar o comprimento da linha e apertá-la suficientemente, nossa configuração final está pronta. Como visto abaixo, o motor servo pode corretamente trancar e destrancar a porta!
Você não necessariamente tem que usar o método de acoplamento pescoço de garrafa - linha. Use qualquer método que seja mais adequado e conveniente com seu sistema de trava.
Felizmente, eu tinha uma pequena abertura no lugar certo no sapateiro. Isso me permitiu passar as conexões do servo motor facilmente. Após um pequeno trabalho de decoração e rotulagem, nosso sapateiro inteligente final está pronto para ação.
Estamos prontos. Tudo que resta é ligar o circuito, adicionar um rosto confiável no aplicativo WinForms e aproveitar a segurança de trava facial em nossas portas. Você precisará alimentar tanto o Arduino quanto o Módulo WiFi Bolt. Uso um power bank de 10000 mAh para alimentar ambos. A WebCam que uso é uma Microsoft LifeCam VX-800. É velha mas ainda melhor que a câmera do laptop. Confira o vídeo de demonstração. Ele mostra o funcionamento do nosso projeto em detalhes.
A Demonstração em Vídeo
Assista nosso projeto em ação (Desculpe a qualidade do vídeo):
Conclusão
Ufa.. isso foi bem longo. Este projeto é fruto do treinamento IoT da Internshala, powered by Bolt IoT. Embora este projeto seja bem simples, ele nos mostra o potencial da Internet das Coisas e como pode tornar a vida diária das pessoas mais fácil.
De qualquer forma.. Foi uma ótima experiência de aprendizado para mim. Espero que vocês gostem de construir isso e estou animado para ver quais novas inovações vocês criarão. Concluo expressando meus sinceros agradecimentos à equipe de Treinamento da Internshala e Bolt IoT por tornar este empreendimento possível.
E isso é tudo!
Código
BoltDoorLock.ino
Código Arduino.
#include <Servo.h>
#define ServoPin 4
#define LockSignalPin 2
#define UnLockSignalPin 3
#define BellButtonPin 5
#define LockButtonPin 8
#define RingBellSignalPin 6
#define BuzzerPin 7
#define GreenLedPin 9
#define RedLedPin 10
Servo myServo;
void setup() {
pinMode(LockSignalPin, INPUT);
pinMode(UnLockSignalPin, INPUT);
pinMode(BellButtonPin, INPUT);
pinMode(LockButtonPin, INPUT);
pinMode(BuzzerPin, OUTPUT);
pinMode(RedLedPin, OUTPUT);
pinMode(GreenLedPin, OUTPUT);
pinMode(RingBellSignalPin, OUTPUT);
digitalWrite(RedLedPin, LOW);
digitalWrite(GreenLedPin, LOW);
digitalWrite(RingBellSignalPin, LOW);
myServo.attach(ServoPin);
Serial.begin(9600);
}
void loop() {
int lockButton, lock, unlock, bell;
char snum[5];
lock = digitalRead(LockSignalPin);
unlock = digitalRead(UnLockSignalPin);
// Verifica se sinal de travamento do Bolt é HIGH
if(lock == HIGH) {
// Gira motor para posição trancada
myServo.write(120);
// Define indicações de LED
digitalWrite(GreenLedPin, LOW);
digitalWrite(RedLedPin, HIGH);
// Som de travamento no buzzer
digitalWrite(BuzzerPin, HIGH);
delay(1000);
digitalWrite(BuzzerPin, LOW);
delay(1000);
}
// Verifica se sinal de destravamento do Bolt é HIGH
else if(unlock == HIGH) {
// Gira motor para posição destrancada
myServo.write(0);
// Define indicações de LED
digitalWrite(GreenLedPin, HIGH);
digitalWrite(RedLedPin, LOW);
delay(2000);
}
bell = digitalRead(BellButtonPin);
if(bell == HIGH) // Usuário pressionou botão de campainha
{
// Sinaliza Bolt que botão de campainha foi pressionado
digitalWrite(RingBellSignalPin, HIGH);
// Um padrão de som de campainha!
digitalWrite(BuzzerPin, HIGH);
delay(100);
digitalWrite(BuzzerPin, LOW);
delay(20);
digitalWrite(BuzzerPin, HIGH);
delay(200);
digitalWrite(BuzzerPin, LOW);
delay(100);
digitalWrite(BuzzerPin, HIGH);
delay(100);
digitalWrite(BuzzerPin, LOW);
delay(20);
digitalWrite(BuzzerPin, HIGH);
delay(200);
digitalWrite(BuzzerPin, LOW);
delay(1500);
// Desliga o sinal
digitalWrite(RingBellSignalPin, LOW);
}
lockButton = digitalRead(LockButtonPin);
if(lockButton == HIGH) // Usuário pressionou botão de travar
{
// Gira motor para posição trancada
myServo.write(120);
// Define indicações de LED
digitalWrite(GreenLedPin, LOW);
digitalWrite(RedLedPin, HIGH);
// Som de travamento no buzzer
digitalWrite(BuzzerPin, HIGH);
delay(1000);
digitalWrite(BuzzerPin, LOW);
}
}
Aplicação WinForms - Projeto Visual Studio (Facebolt Doorlock).zip
* Extraia o arquivo zip e abra o arquivo .sln no Visual Studio.
* Modifique o código com suas credenciais de API.
* Rode o projeto.
* Adicione um rosto confiável.
* Finalmente, inicie o monitoramento facial.
Sem preview (apenas download).
Bolt IoT Cloud API - Biblioteca Cliente
Esta é uma biblioteca cliente não oficial que escrevi, para comunicar com a API Bolt Cloud. Esta biblioteca é usada em nossa Aplicação WinForms para comunicar com o Módulo WiFi Bolt.
https://github.com/diozz/Bolt-IoT-API-.NET
Esquemáticos
Esquemático do Circuito Fritzing
facebolt_doorlock_2RfOtkPW2i.fzzProcesso de manufatura
- Construa um Controlador Doméstico Inteligente 433 MHz com Sensorflare e Raspberry Pi
- Construa uma Fechadura Inteligente de Travamento Automático Usando Proximidade Bluetooth do Smartphone
- Rastreamento Facial Pan/Tilt em Tempo Real no Raspberry Pi – Guia Prático
- Bartender Inteligente: Construa sua Própria Estação de Coquetéis com Raspberry Pi
- Otimizando Aperto de Parafusos com Ferramentas de Torque — Estratégias Comprovadas para Pré-Carga Confiável
- Maximize o ROI em Seus Investimentos em IoT: Um Guia Prático
- Proteja Seus Dispositivos Inteligentes: Melhores Práticas para Segurança IoT
- Compras Inteligentes: Unindo IA com Insight Humano
- Fechadura Inteligente Wi-Fi com Arduino e ESP8266 - Desbloqueio via Celular
- GE Digital Impulsiona Transformação na Manufatura com MES Inteligente