Neste tutorial, exploraremos uma aplicação para a placa Raspberry Pi Pico: utilizar a RP Pico para simular um teclado USB para interação com um computador.
Para isso, será utilizada a biblioteca Keyboard.h, que permite ao RP Pico enviar pressionamentos de tecla para um computador conectado através da porta USB nativa de seu computador. Também será demonstrado como a placa RP Pico pode detectar e interagir com as funções Num Lock, Caps Lock e Scroll Lock de um computador hospedeiro.
Por fim, será demonstrado como criar um Gerenciador de Autenticação com a placa RP Pico. Ao integrar três push buttons à placa Raspberry Pi Pico, será possibilitado a execução de ações específicas no sistema operacional Windows 11 (SO do Computador). Ao pressionar o botão LOGIN, a senha armazenada na memória FLASH da RP Pico será enviada para permitir o acesso à sessão do Windows. Para evitar equívocos causados pelo Caps Lock, será implementada uma função que formata corretamente a senha, independentemente do estado do Caps Lock.
Outras funcionalidades incluirão o botão LOGOUT, que enviará um comando para realizar o logout no Windows, e o botão BLOQUEAR, que permitirá bloquear o sistema, exigindo que o usuário faça login novamente para acessar a sessão atual do Windows.
Neste post será necessário os seguintes materiais:
Para utilizar a placa Raspberry Pi Pico deve-se instalar o núcleo Arduino Pico na IDE Arduino. Para isso, siga os passos abaixo:
Para que a placa Raspberry Pi Pico possa enviar comandos para o computador, é necessário utilizar a biblioteca Keyboard.h. Esta biblioteca permite enviar pressionamentos de tecla para um computador conectado através da porta USB do RP Pico.
Para programar a placa RP Pico, será utilizado o núcleo Arduino Pico desenvolvido por Earle F. Philhower, III (earlephilhower). Este núcleo possui dois stacks USB. As stacks USB são implementações de protocolos e drivers USB que possibilita a comunicação entre dispositivos Arduino e outros dispositivos por meio da interface USB (Universal Serial Bus: Porta Serial Universal). As duas stacks USB existentes no núcleo do Arduino Pico são: Arduino e Adafruit TinyUSB. A stack Arduino (Pico SDK) é a versão mais simples e a stack Adafruit TinyUSB é a mais completa.
A escolha entre essas duas pilhas USB pode ser feita através do menu da Arduino IDE. Para isso,na Arduino IDE, navegue no menu Ferramentas ➜ USB Stack. Então, selecione a opção pico-SDK (stack Arduino) ou a opção Adafruit TinyUSB.
Neste post, estaremos utilizando a Stack Arduino (Pico SDK), pois a mesma fornece as funcionalidades necessárias.
Para a utilização da biblioteca Keyboard.h não é necessário nenhuma instalação de biblioteca, apenas é necessário ter o núcleo Arduino-Pico (de earlephilhower) instalado em sua IDE Arduino. Para instruções de como instalar este núcleo, confira o tópico anterior Configurando IDE Arduino para a RP Pico.
Nas funções da biblioteca Keyboard.h em que ocorre o pressionamento de tecla, pode-se utilizar caracteres ASCII. Estes caracteres podem ser expressos em um inteiro, em um caractere, em um hexadecimal ou em um binário. Veja na tabela abaixo os caracteres ASCII compatíveis:
*Caracteres ASCII azuis são chamados de caracteres de controle, códigos de controle ou caracteres não imprimíveis; Caracteres ASCII vermelhos são caracteres visíveis/imprimíveis que incluem letras maiúsculas, letras minúsculas, números e pontuação básica; Códigos Hexadecimais devem ser precedidos de ‘0x’; Códigos Binários devem ser precedidos de ‘0b’.
Assim como ocorre com os caracteres ASCII, também se pode utilizar pressionamentos de teclas modificadoras de teclado e teclas especiais. Confira abaixo as teclas modificadoras e teclas especiais:
Nota: Quando a placa RP Pico usa comandos de pressionamentos de tecla, é assumido o controle do teclado de seu Computador. Para controlar quando o pressionamento ocorre, é utilizado o botão físico BOOTSEL da placa RP Pico. Para detalhes de como efetuar a leitura do botão BOOTSEL da placa Raspberry Pi Pico, consulte o artigo BOOTSEL da Raspberry Pi Pico no Arduino IDE daqui do blog Eletrogate:
void begin(const uint8_t *layout = KeyboardLayout_en_US)
: Inicia a emulação de um teclado conectado a um computador. Esta função inicia o teclado com o layout fornecido. O layout padrão é o teclado em inglês dos Estados Unidos (en_US).
layout
: representa o layout do teclado. O layout padrão é KeyboardLayout_en_US. a biblioteca oferece suporte aos seguintes layouts de teclado nacionais:
#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado Keyboard.print("ESP32!"); // Envia uma série de pressionamentos de caracteres while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
void end(void)
: Encerra a emulação do teclado, desligando a comunicação com o computador ao qual o teclado está conectado.
#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() {} void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado Keyboard.begin(); // Inicia a comunicação com o teclado Keyboard.print("Teste!"); // Envia uma série de pressionamentos de caracteres Keyboard.end(); // Finaliza a comunicação com o teclado while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t write(uint8_t k)
: Envia um pressionamento de tecla para um computador conectado. Isso é semelhante a pressionar e soltar uma tecla do teclado. Somente caracteres ASCII presentes no teclado são suportados, além de modificadores de teclado adicionais e teclas especiais (como CTRL, SHIFT, ALT, entre outras).
k
: O byte a ser escrito, representando a tecla a ser pressionada e solta. Este byte pode ser um inteiro, um caractere, um hexadecimal ou um binário. Confira a tabela de Caracteres ASCII e a tabela de Modificadores de teclado e teclas especiais.#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado Keyboard.write(65); // pressiona e solta a tecla com código ASCII decimal 65 - letra A Keyboard.write(0x42); // pressiona e solta a tecla com código ASCII hexadecimal 42 - letra B Keyboard.write(0b1000011); // pressiona e solta a tecla com código ASCII binário 1000011 - letra C Keyboard.write('D'); // pressiona e solta a tecla de caractere ASCII 'D' while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t write(const uint8_t *buffer, size_t size)
: Envia uma série de pressionamentos de teclas para um computador conectado. Isso é semelhante a pressionar e soltar sequencialmente várias teclas do teclado. Somente caracteres ASCII presentes no teclado são suportados, além de modificadores de teclado adicionais e teclas especiais (como CTRL, SHIFT, ALT, entre outras).
buffer
: Um ponteiro para o array de bytes (buffer) contendo as teclas a serem pressionadas, com cada byte representando a tecla a ser pressionada e solta. Este byte pode ser um inteiro, um caractere, um hexadecimal ou um binário. Confira a tabela de Caracteres ASCII e a tabela de Modificadores de teclado e teclas especiais;size
: O tamanho do buffer, indicando a quantidade de teclas a serem pressionadas.size
nesta função.#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado uint8_t keyBuffer[] = { 'c', 'a', 'l', 'c', 'u', 'l', 'a', 'd', 'o', 'r', 'a' , '\n'}; // Define um buffer com as teclas a serem pressionadas size_t tamanhoBuffer = sizeof(keyBuffer)/sizeof(uint8_t); // Calcula o tamanho do buffer em bytes Keyboard.write(keyBuffer,tamanhoBuffer); // pressiona e solta cada tecla do buffer keyBuffer formando a palavra 'calculadora' com uma quebra de linha while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t press(uint8_t k)
: Simula a pressionamento (como se uma tecla fosse pressionada e mantida pressionada no teclado) de uma tecla no Computador conectado. Está função é útil ao usar teclas modificadoras (como SHIFT, CTRL, ALT, F1, F2, WIN, TAB, entre outros).
k
: O byte que representa a tecla a ser pressionada. Confira a tabela de Caracteres ASCII e a tabela de Modificadores de teclado e teclas especiais.#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado //Série de pressionamentos para abrir o Gerenciador de Tarefas do Windows (Ctrl + Shift + Esc) Keyboard.press(KEY_LEFT_CTRL); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_CTRL (tecla Ctrl esquerda) Keyboard.press(KEY_LEFT_SHIFT); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_SHIFT (tecla Shift esquerda) Keyboard.press(KEY_ESC); // pressiona e mantém pressionada a tecla com chave KEY_ESC (tecla Esc) delay(100); // atraso de 100 milissegundos Keyboard.releaseAll(); // solta todas as teclas pressionadas while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t release(uint8_t k)
: Simula a liberação da tecla especificada que estava mantida pressionada no Computador conectado.
k
: O byte que representa a tecla a ser solta. Confira a tabela de Caracteres ASCII e a tabela de Modificadores de teclado e teclas especiais.#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado //Série de pressionamentos para colar a última coisa que estiver na área de trânsferência Keyboard.press(KEY_LEFT_CTRL); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_CTRL (tecla Ctrl esquerda) Keyboard.press('v'); // pressiona e mantém pressionada a tecla com caractere ASCII 'v' (tecla v minúsculo) delay(100); // atraso de 100 milissegundos Keyboard.release(KEY_LEFT_CTRL); // solta a tecla pressionada especificada Keyboard.release('v'); // solta a tecla pressionada especificada while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
void releaseAll(void)
: Simula a liberação de todas as teclas que foram previamente pressionadas no teclado do Computador conectado.
#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado //Série de pressionamentos para abrir o histórico da área de transferência Keyboard.press(KEY_LEFT_GUI); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_GUI (tecla Windows esquerda) Keyboard.press('v'); // pressiona e mantém pressionada a tecla com caractere ASCII 'v' (tecla v minúsculo) delay(100); // atraso de 100 milissegundos Keyboard.releaseAll(); // solta todas as teclas pressionadas while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t consumerPress(uint16_t k)
: Simula o pressionamento de uma tecla de controle multimídia, como play, pause, volume up, volume down, entre outras, no Computador conectado.
k
: O byte que representa a tecla a ser solta. Confira a tabela de Modificadores de teclado e teclas especiais.#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado //Série de pressionamentos para deixar o sistema de áudio do Windows Mudo ou 'desmutado' Keyboard.consumerPress(KEY_MUTE); // pressiona e mantém pressionada a tecla com chave KEY_MUTE (tecla mudo) delay(100); // atraso de 100 milissegundos Keyboard.consumerRelease(); // solta todas as teclas pressionadas de controle de mídia while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t consumerRelease()
: Simula a liberação das teclas de controle multimídia no Computador conectado.
#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado //Série de pressionamentos para pausar/dar play na mídia atual que está tocando no Windows Keyboard.consumerPress(KEY_PLAY_PAUSE); // pressiona e mantém pressionada a tecla com chave KEY_PLAY_PAUSE (tecla play / pause) delay(100); // atraso de 100 milissegundos Keyboard.consumerRelease(); // solta todas as teclas de controle de mídia pressionadas while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t Print::print(const char str[])
: Envia um ou mais pressionamentos de tecla para um computador conectado.
str
: Um char, int ou uma string representando as teclas a serem enviadas.#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado Keyboard.print("abc"); // Envia uma série de pressionamentos de caracteres while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
size_t Print::println(const char c[])
: Envia um ou mais pressionamentos de tecla para um computador conectado, seguido por um pressionamento na tecla Enter.
c
: Um char, int ou uma string representando as teclas a serem enviadas.#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) { // Verifica se o botão BOOTSEL foi pressionado Keyboard.println("xyz"); // Envia uma série de pressionamentos de caracteres while (BOOTSEL) {} // Aguarda o usuário soltar o botão BOOTSEL } delay(10); // Atraso de 10 milissegundos }
Para a placa Raspberry Pi Pico detectar quando o computador estiver com as funções Num Lock, Caps Lock e Scroll Lock ativas é utilizada uma função callback na programação da placa. Esta função é a onLed. Veja abaixo a sintaxe dela:
void onLED(LedCallbackFcn fcn, void *cbData = nullptr)
:
Ela possui os seguintes parãmetros:
fcn
: parâmetro do tipo LedCallbackFcn
que aceita uma função de callback cuja assinatura é definida como typedef void(*LedCallbackFcn)(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData);
. Os parâmetros desta assinatura da callback são:
numlock
: parâmetro booleano que indica se a função Num Lock está ativa ou não (ao estar ativada trava as funções no teclado numérico do computador).capslock
: parâmetro booleano que indica se a função Caps Lock está ativa ou não (ao estar ativada deixa as letras em maiúsculas).scrolllock
: parâmetro booleano que indica se a função Scroll Lock está ativa ou não (ao estar ativada bloqueia a rolagem da página).compose
: parâmetro booleano que indica o estado da função Compose ou não (ao estar ativada permite a criação de caracteres especiais, veja mais sobre em Compose key – Wikipedia).kana
: parâmetro booleano que indica o estado da função Kana ou não (ao estar ativada permite a inserção de caracteres em sistemas de escrita japonesa, veja mais sobre em Japanese input method – Wikipedia).cbData
: parãmetro que permite que dados adicionais possam ser passados para a função de callback.cbData
: parãmetro OPCIONAL que permite que dados adicionais possam ser passados para a função de callback.Veja o sketch abaixo que exibe no monitor serial o status atual de Num Lock, Caps Lock e Scroll Lock:
#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado bool nl, cl, sl; // variáveis globais que armazenam o status atual de Num Lock, Caps Lock e Scroll Lock void ledCallBack(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData) { nl = numlock; // Atualiza o status de Num Lock na variável global cl = capslock; // Atualiza o status de Caps Lock na variável global sl = scrolllock; // Atualiza o status de Scroll Lock na variável global } void setup() { Serial.begin(115200); // configura o monitor serial em 115200 de baudrate Keyboard.onLED(ledCallBack); // Associa a função de callback para monitorar os estados das teclas Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { Serial.println("--------------------------------------------\n"); Serial.println("Num Lock \t Caps Lock \t Scroll Lock"); Serial.print(" "); Serial.print(nl); // Exibe o status atual de Num Lock Serial.print("\t\t "); Serial.print(cl); // Exibe o status atual de Caps Lock Serial.print("\t\t "); Serial.println(sl); // Exibe o status atual de Scroll Lock Serial.println("--------------------------------------------\n"); delay(100); }
Ao sketch ser executado na placa RP Pico e ao ser apertada as teclas Num Lock, Caps Lock ou Scroll Lock do computador, o monitor serial exibe:
Quando uma String é passada como parâmetro para a função print da biblioteca Keyboard.h e o computador de destino estiver com a função Caps Lock ativada, a String pode ser recebida incorretamente. Veja o exemplo:
#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado void setup() { Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) {// Verifica se o botão BOOTSEL foi pressionado Keyboard.println("ABCdef"); // Envia uma série de pressionamentos de caracteres while (BOOTSEL);// Aguarda o usuário soltar o botão BOOTSEL } delay(10); // atraso de 10 milissegundos no loop principal }
Neste código anterior, ao pressionar o botão BOOTSEL seria enviado para o computador:
ABCdef
abcDEF
Como visto, quando a função Caps Lock estiver ativada, os caracteres maiúsculos são recebidos como minúsculos e os caracteres minúsculos são recebidos como maiúsculos.
Para resolver isso, basta formatar adequadamente a string antes de enviar para o computador de acordo com o status da função Caps Lock no computador. Para formatar a string, foi criada a função formatarString
:
// Função para formatar a string, levando em consideração o estado do Caps Lock . // Lógica de funcionamento: // - se a função Caps Lock do computador estiver acionada: // -> os caracteres da string que forem maiúsculos serão transformados em minúsculos, // e os caracteres da string que forem minúsculos serão transformados em maiúsculos; // // - se a função Caps Lock do computador NÃO estiver acionada: // -> os caracteres da string que forem maiúsculos permanecerão maiúsculos, // e os caracteres da string que forem minúsculos permanecerão minúsculos. // String formatarString(String string, bool capsLockAtivo) { if (capsLockAtivo) { // Verifica se o Caps Lock está ativado for (int i = 0; i < string.length(); i++) { // Percorre cada caractere da string if (isAlpha(string[i])) { // Verifica se o caractere é uma letra if (isUpperCase(string[i])) { // Verifica se o caractere é maiúsculo string[i] = toLowerCase(string[i]); // Converte para minúsculo } else { // se não, caso o caractere seja minúsculo, ... string[i] = toUpperCase(string[i]); // Converte para maiúsculo } } } } return string; // Retorna a string formatada }
Para utilizar esta função no sketch, basta informar nos parâmetros a string a ser formatada e o status da função Caps Lock no computador. Veja o Exemplo:
#include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado bool cl; // variável global que armazena o status atual de Caps Lock void ledCallBack(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData) { cl = capslock; // Atualiza o status de Caps Lock na variável global } void setup() { Keyboard.onLED(ledCallBack); // Associa a função de callback para monitorar os estados das teclas Keyboard.begin(); // Inicia a comunicação com o teclado } void loop() { if (BOOTSEL) {// Verifica se o botão BOOTSEL foi pressionado Keyboard.println(formatarString("ABCdef", cl)); // Envia uma série de pressionamentos de caracteres, com a string sendo formatada adequadamente while (BOOTSEL);// Aguarda o usuário soltar o botão BOOTSEL } delay(10); // atraso de 10 milissegundos no loop principal } // Função para formatar a string, levando em consideração o estado do Caps Lock . // Lógica de funcionamento: // - se a função Caps Lock do computador estiver acionada: // -> os caracteres da string que forem maiúsculos serão transformados em minúsculos, // e os caracteres da string que forem minúsculos serão transformados em maiúsculos; // // - se a função Caps Lock do computador NÃO estiver acionada: // -> os caracteres da string que forem maiúsculos permanecerão maiúsculos, // e os caracteres da string que forem minúsculos permanecerão minúsculos. // String formatarString(String string, bool capsLockAtivo) { if (capsLockAtivo) { // Verifica se o Caps Lock está ativado for (int i = 0; i < string.length(); i++) { // Percorre cada caractere da string if (isAlpha(string[i])) { // Verifica se o caractere é uma letra if (isUpperCase(string[i])) { // Verifica se o caractere é maiúsculo string[i] = toLowerCase(string[i]); // Converte para minúsculo } else { // se não, caso o caractere seja minúsculo, ... string[i] = toUpperCase(string[i]); // Converte para maiúsculo } } } } return string; // Retorna a string formatada }
Agora, neste código, ao pressionar o botão BOOTSEL seria enviado para o computador:
ABCdef
ABCdef
Como visto, não existe mais o problema anterior de “inversão” maiúsculo/minúsculo.
Agora será mostrado como criar um Gerenciador de Autenticação com a placa Raspberry Pi Pico. Ao se clicar em um dos três pushbuttons conectados à placa RP Pico, será enviado ao computador com Sistema Operacional Windows 11 uma determinada ação:
Clique aqui para fazer o download do sketch completo.
Antes de prosseguir, modifique o valor das seguintes variáveis no sketch:
SENHA_WINDOWS
pela sua senha de autenticação no Windows 11;Em seguida, faça o upload do sketch para a placa RP Pico.
Veja abaixo o sketch (contendo os arquivos gerenciador_autenticacao_rp_pico.ino e credencial.h):
/****************************************************************************** Simule um Teclado com Raspberry Pi Pico + Gerenciador de Autenticação com RP Pico Criado em 05 de Fevereiro de 2024 por Michel Galvão (https://micsg.com.br) Sketch Principal Eletrogate | Arduino, Robótica, IoT, Apostilas e Kits https://www.eletrogate.com/ ******************************************************************************/ #include <Keyboard.h> // Inclui a biblioteca para o uso da emulação de teclado #include "credencial.h" // Inclui o arquivo credencial.h que armazena a senha do Computador Windows #define pinLogin 17 // Define o pino do botão para acionar a função login #define pinLogout 16// Define o pino do botão para acionar a função logout #define pinBloquear 15// Define o pino do botão para acionar a função bloqueio bool cl; // variável global que armazena o status atual de Caps Lock void ledCallBack(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData) { cl = capslock; // Atualiza o status de Caps Lock na variável global } void setup() { Serial.begin(115200); // configura o monitor serial em 115200 de baudrate Keyboard.onLED(ledCallBack); // Associa a função de callback para monitorar os estados das teclas Keyboard.begin(); // Inicia a comunicação com o teclado pinMode(pinLogin, INPUT_PULLUP);// Configura o pino do botão login como entrada com resistor de pull-up interno pinMode(pinLogout, INPUT_PULLUP);// Configura o pino do botão logout como entrada com resistor de pull-up interno pinMode(pinBloquear, INPUT_PULLUP);// Configura o pino do botão bloqueio como entrada com resistor de pull-up interno } void loop() { if (!digitalRead(pinLogin)) { // se a leitura do botão login for igual à 0 (LOW), ... // Estrutura de controle para esperar o usuário soltar o botão Login do { // Início do bloco 'do' delay(100); // Aguarda por 100 milissegundos } while (!digitalRead(pinLogin));// Continua repetindo o loop enquanto o botão de login estiver em nível lógico baixo (pressionado) Serial.println("Login acionado"); // Informa pelo Monitor Serial que a Função Login será executada Keyboard.write(KEY_RETURN); // pressiona e solta a tecla ENTER delay(500); // pausa o programa por 350 milissegundos Keyboard.print(formatarString(senhaWindows, cl)); // Envia uma série de pressionamentos dos caracteres da variável contendo a senha de login do Windows 11, com a senha sendo formatada adequadamente delay(150); // pausa o programa por 150 milissegundos Keyboard.write(KEY_RETURN); // pressiona e solta a tecla ENTER } if (!digitalRead(pinLogout)) { // se a leitura do botão logout for igual à 0 (LOW), ... // Estrutura de controle para esperar o usuário soltar o botão Logout do { // Início do bloco 'do' delay(100); // Aguarda por 100 milissegundos } while (!digitalRead(pinLogout)); // Continua repetindo o loop enquanto o botão de login estiver em nível lógico baixo (pressionado) Serial.println("Logout acionado"); // Informa pelo Monitor Serial que a Função Logout será executada Keyboard.press(KEY_LEFT_CTRL); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_CTRL (tecla Ctrl esquerda) Keyboard.press(KEY_LEFT_ALT); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_ALT (tecla Alt) Keyboard.press(KEY_DELETE); // pressiona e mantém pressionada a tecla com chave KEY_DELETE (tecla Delete) Keyboard.releaseAll(); // solta todas as teclas pressionadas delay(500); // pausa o programa por 350 milissegundos Keyboard.write(KEY_LEFT_ALT); // pressiona e solta a tecla ALT delay(150); // pausa o programa por 100 milissegundos Keyboard.write('s'); // pressiona e solta a tecla de caractere ASCII 's' (para fazer logout no Windows 11) } if (!digitalRead(pinBloquear)) { // se a leitura do botão bloquear for igual à 0 (LOW), ... // Estrutura de controle para esperar o usuário soltar o botão Bloquear do { // Início do bloco 'do' delay(100); // Aguarda por 100 milissegundos } while (!digitalRead(pinBloquear)); // Continua repetindo o loop enquanto o botão de bloqueio estiver em nível lógico baixo (pressionado) Serial.println("Bloqueio acionado"); // Informa pelo Monitor Serial que a Função Bloquear será executada Keyboard.press(KEY_LEFT_CTRL); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_CTRL (tecla Ctrl esquerda) Keyboard.press(KEY_LEFT_ALT); // pressiona e mantém pressionada a tecla com chave KEY_LEFT_ALT (tecla Alt) Keyboard.press(KEY_DELETE); // pressiona e mantém pressionada a tecla com chave KEY_DELETE (tecla Delete) Keyboard.releaseAll(); // solta todas as teclas pressionadas delay(500); // pausa o programa por 350 milissegundos Keyboard.write(KEY_LEFT_ALT); // pressiona e solta a tecla ALT delay(150); // pausa o programa por 100 milissegundos Keyboard.write('b'); // pressiona e solta a tecla de caractere ASCII 'b' (para bloquear o Windows 11) } delay(10); // atraso de 10 milissegundos no loop principal } // Função para formatar a string, levando em consideração o estado do Caps Lock . // Lógica de funcionamento: // - se a função Caps Lock do computador estiver acionada: // -> os caracteres da string que forem maiúsculos serão transformados em minúsculos, // e os caracteres da string que forem minúsculos serão transformados em maiúsculos; // // - se a função Caps Lock do computador NÃO estiver acionada: // -> os caracteres da string que forem maiúsculos permanecerão maiúsculos, // e os caracteres da string que forem minúsculos permanecerão minúsculos. // String formatarString(String string, bool capsLockAtivo) { if (capsLockAtivo) { // Verifica se o Caps Lock está ativado for (int i = 0; i < string.length(); i++) { // Percorre cada caractere da string if (isAlpha(string[i])) { // Verifica se o caractere é uma letra if (isUpperCase(string[i])) { // Verifica se o caractere é maiúsculo string[i] = toLowerCase(string[i]); // Converte para minúsculo } else { // se não, caso o caractere seja minúsculo, ... string[i] = toUpperCase(string[i]); // Converte para maiúsculo } } } } return string; // Retorna a string formatada }
/****************************************************************************** Simule um Teclado com Raspberry Pi Pico + Gerenciador de Autenticação com RP Pico Criado em 05 de Fevereiro de 2024 por Michel Galvão (https://micsg.com.br) Credencial Eletrogate | Arduino, Robótica, IoT, Apostilas e Kits https://www.eletrogate.com/ ******************************************************************************/ const char *senhaWindows = "SENHA_WINDOWS"; // variável que armazena a senha de autenticação do Windows
Aqui está um resumo explicativo com base no código:
Keyboard.h
para emular um teclado.credencial.h
para obter a senha do Windows.pinLogin
, pinLogout
, e pinBloquear
são definidos como os pinos dos botões para acionar as funções de login, logout e bloqueio, respectivamente.credencial.h
:
senhaWindows
.Veja no vídeo abaixo o funcionamento do projeto:
Em um passo além do projeto original, pode-se utilizar um Módulo Leitor Biométrico (Impressão Digital) – DY50 ou um Kit Módulo RFID Mfrc522 13.56 Mhz para aprimorar ainda mais a autenticação no Windows e permitir ao usuário que, facilmente, possa se autenticar utilizando sua digital, um cartão RFID ou um chaveiro RFID.
Curtiu o post? Avalie e deixe um comentário! Siga-nos também no Instagram e nos marque quando fizer algum projeto nosso: @eletrogate. Até a próxima!
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!