Fazendo um botão de mudo de hardware em Zoom

Recentemente, o Instagram me mostrou um anúncio de um botão de zoom mudo dedicado, que acabou sendo muito relevante para mim.







Sim, eu ligo para o Zoom todos os dias. Sim, tenho um filho que costuma interferir nessas ligações. Algoritmo de entrega de anúncios do Instagram, você ganhou, eu preciso deste botão.



Mas tenho preconceitos. Instagram anuncia um projeto com o Kickstarter. Além disso, não quero contribuir com a receita de anúncios do Facebook nem mesmo clicando neste vídeo. A expressão de Jenny Odell “Não há horas gratuitas” descreve totalmente meu ponto de vista sobre a qualidade do produto nos anúncios do Instagram. Além disso, meu limite de financiamento para projetos do Kickstarter está quase esgotado.



Apoiei muitos projetos no Kickstarter, e às vezes o resultado desses projetos me lembrava o hambúrguer que Michael Douglas comprou no filme "I've Enough!"





Então, vamos montar esse botão nós mesmos.



A primeira coisa a pensar é qual botão eu gostaria de pressionar?



Eu amo teclados com interruptores Cherry MX. Existem três tipos de interruptores mecânicos: lineares, táteis e clicáveis. Linear - o tipo mais simples de interruptor que se move para cima e para baixo quase sem feedback. Os interruptores táteis têm uma protuberância no meio do curso que permite sentir quando uma tecla é pressionada. E interruptores clicáveis ​​têm feedback tátil mais forte E produzem um clique audível quando pressionados.



Normalmente, compraríamos um testador de switch para descobrir qual tipo está respondendo a nós. , e também perguntamos aos nossos colegas que som o teclado deve fazer para que não nos matem. Mas estamos no meio da pandemia COVID, então não há colegas por perto! Opte por um switch Cherry MX Blue com feedback tátil confortável que é extremamente alto. O site Cherry MX chama essa opção de "clicável e visível", mas isso ainda é muito pouco dito.





Parece bonito, mas você poderia pensar em algo melhor. Se estou feliz em acertar o botão Cherry MX Blue, não seria ainda melhor acertar o comicamente grande Cherry MX Blue?



E esta é a grande mudança da Novelkeys .





É 4 vezes maior em cada dimensão e 64 vezes maior em volume do que um switch convencional. Ele ainda tem uma tampa enorme!





Infelizmente, o Big Switch não é vendido em uma caixa, então tive que usar a impressão 3D. Um belo case foi encontrado no Thingiverse: NovelKeys Big Switch Case . Sempre vale a pena procurar remixes para o caso de alguém querer melhorar o design original. Nesse caso, houve um remix que adicionou um compartimento para o Pro Micro, e a chave ficou mais apertada, então eu imprimi.





Agora que temos um gabinete, precisamos de uma placa que inserimos nele e anexamos ao switch.



O Pro Micro possui um chip ATmega32U4 para emular um dispositivo USB HID, como um teclado USB. Além disso, esta placa é pequena.





Existem dois contatos de metal na parte inferior do interruptor grande.





Quando uma tecla é pressionada dentro da chave, um circuito é fechado entre esses dois contatos.





Vamos dar uma olhada no layout do pino do Pro Micro:





Você pode conectar o GND a um pino de metal e o Pino 2 ao outro. O pino 2 é um pino de E / S digital que mostra ALTO quando uma tecla é pressionada e BAIXO quando não é.



Também seria ótimo ter algum tipo de indicador visual do status Mudo, para que você possa adicionar um LED.



Eu pedi um LED de 10 mm:





E um resistor de 220 ohms:





A perna longa dos LEDs se conecta ao PWR e a perna curta se conecta ao GND. Vamos inserir um resistor entre a perna longa e o outro pino para reduzir a quantidade de corrente. Selecionei o pino 9 na parte inferior do quadro. Liguei a perna curta ao GND. Achei útil esta página sobre LEDs e resistores.



Eu soldei este fio 20 AWG entre a placa e o switch:





O resultado é a seguinte construção:





Vamos colocar tudo em nossa caixa impressa:





Agora precisamos escrever o código.



Comecei com o código que Sparkfun escreveu para criar um enorme botão Salvar e o modifiquei um pouco.



O princípio é o seguinte: quando você pressiona uma tecla, ela envia um atalho de teclado Zoom para ligar e desligar o som (no Mac é Cmd-Shift-A). Você precisará alterar as configurações de zoom para que este atalho de teclado seja reconhecido mesmo quando o zoom estiver fora de foco. Marque a caixa Ativar atalho global :





Também queremos ligar ou desligar o LED após cada pressionamento de tecla. Decidi que o LED seria análogo à luz "On Air" - quando o LED azul está aceso, meu som está ligado e as pessoas ouvem o que estou dizendo.



Mas se você apenas ligar e desligar o LED cada vez que pressiona uma tecla, como manter a sincronia com o estado Mudo no próprio Zoom?



A conveniência do Pro Micro é que ele também possui uma conexão serial. Geralmente é usado para imprimir informações de depuração no IDE do Arduino, mas podemos usá-lo para mantê-lo em sincronia com o estado de áudio no Zoom.



Este é o código que carregamos no próprio Pro Micro:



#include "Keyboard.h"

// OS parameters
typedef enum {
  LINUX,
  WINDOWS,
  MAC
} os_types;

// Change this to your operating system
const os_types OS = MAC;

// Pins
const int btn_pin = 2;
const int led_pin = 9;

// Constants
const int debounce_delay = 50;              // ms

// Globals
int btn_state = HIGH;
int btn_prev = HIGH;
unsigned long last_debounce_time = 0;
int os_ctrl;
int led_state = LOW;

void setup() {

  Serial.begin(57600); // opens serial port, sets data rate to 57600 bps
  
  // Set up LED and button pins
  pinMode(btn_pin, INPUT_PULLUP);  // Set the button as an input
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, led_state);

  // Begin keyboard
  Keyboard.begin();

  // Switch to correct control/command key
  switch(OS){
    case LINUX:
    case WINDOWS:
      os_ctrl = KEY_LEFT_CTRL;
      break;
    case MAC:
      os_ctrl = KEY_LEFT_GUI;
      break;
    default:
      os_ctrl = KEY_LEFT_CTRL;
      break;
  }

  // Get initial timestamp

  Serial.println("started");
  
}

void loop() {

  // Read current state of the button
  int btn_read = digitalRead(btn_pin);

  // Remember when the button changed states
  if ( btn_read != btn_prev ) {
    last_debounce_time = millis();
  }

  // Wait before checking the state of the button again
  if ( millis() > (last_debounce_time + debounce_delay) ) {
    if ( btn_read != btn_state ) {
      btn_state = btn_read;
      if ( btn_state == LOW ) {

        // Send cmd+shift+a
        Keyboard.press(KEY_LEFT_SHIFT);
        Keyboard.press(os_ctrl);
        Keyboard.press('a');
        delay(100);
        Keyboard.releaseAll();

        Serial.println("pressed");

        if (led_state == LOW) {
          led_state = HIGH;
        } else {
          led_state = LOW;
        }
        digitalWrite(led_pin, led_state);

      }
    }
  }

  // Remember the previous button position for next loop()
  btn_prev = btn_read;

  if (Serial.available() > 0) {

    String incomingString = Serial.readStringUntil('\n');

    if (incomingString == "muted") {
      led_state = LOW;
    } else if (incomingString == "unmuted") {
      led_state = HIGH;      
    }

    digitalWrite(led_pin, led_state);
    
  }
  
}
      
      





A seguir, podemos adicionar um Applescript para relatar o estado atual do Zoom. Eu encontrei um plug-in Zoom Streamdeck que continha o Applescript original e o modifiquei para relatar se o Zoom está aberto e qual é o estado de seu som. Eu também modifiquei o script para gerar JSON.



set zoomStatus to "closed"
set muteStatus to "disabled"
tell application "System Events"
	if exists (window 1 of process "zoom.us") then
		set zoomStatus to "open"
		tell application process "zoom.us"
			if exists (menu bar item "Meeting" of menu bar 1) then
				set zoomStatus to "call"
				if exists (menu item "Mute audio" of menu 1 of menu bar item "Meeting" of menu bar 1) then
					set muteStatus to "unmuted"
				else
					set muteStatus to "muted"
				end if
			end if
		end tell
	end if
end tell

copy "{\"mute\":\"" & (muteStatus as text) & "\",\"status\":\"" & (zoomStatus as text) & "\"}" to stdout
      
      





Se agora o executarmos durante uma chamada para Zoom, ele produzirá algo como este:



$ osascript get-zoom-status.scpt
{"mute":"muted","status":"call"}
      
      





Então escrevi um pequeno aplicativo em Node, usado como intermediário entre o Pro Micro e este script:



const { exec } = require('child_process');

const SerialPort = require('serialport');
const Readline = require('@serialport/parser-readline');
const port = new SerialPort('/dev/tty.usbmodemHIDPC1', {
    baudRate: 57600
});

var checkStatus = function() {
    console.log('Checking status...');
    exec('osascript get-zoom-status.scpt', (error, stdout, stderr) => {

        if (error) {
            console.error(`exec error: ${error}`);
            return;
        }

        var status = JSON.parse(stdout);
        if (status.mute == 'unmuted') {
            port.write('unmuted');
        } else {
            port.write('muted');
        }

    });
}

const parser = port.pipe(new Readline({ delimiter: '\r\n' }))
parser.on('data', function (data) {
    if (data == "pressed") {
        console.log('Button pressed.');
        checkStatus();
    }
})

checkStatus();
setInterval(checkStatus, 30000);
      
      





Este script faz duas coisas. Quando o botão é pressionado, ele envia um comando “pressionado” para a placa Pro Micro através da porta serial, que executa o Applescript para determinar o estado atual do áudio em Zoom. Em seguida, ele envia um comando “beep off” ou “beep on” para a placa Pro Micro, fazendo com que o LED mude para o estado apropriado. Também criei um cronômetro que executa um script a cada 30 segundos no caso de eu, acidentalmente, ativar ou desativar o som por meio da interface do Zoom em vez do botão, caso contrário, o estado só será atualizado quando o botão for pressionado.



Esta é a aparência do botão quando usado em uma chamada via Zoom:





Por favor, apoie meu Kickstarter - brincadeirinha, não tenho nenhum Kickstarter, mas espero que agora você possa criar um sozinho.






Anúncio



Solicite um servidor e comece a trabalhar imediatamente! Criação de VDS de qualquer configuração em um minuto. Épico :)






All Articles