Índice:

Botão mágico 4k: o controle remoto sem fio 20USD BMPCC 4k (ou 6k): 4 etapas (com imagens)
Botão mágico 4k: o controle remoto sem fio 20USD BMPCC 4k (ou 6k): 4 etapas (com imagens)
Anonim
Image
Image

Muitas pessoas me pediram para compartilhar alguns detalhes sobre meu controlador sem fio para o BMPCC4k. A maioria das perguntas era sobre o controle do bluetooth, então mencionarei alguns detalhes sobre isso. Presumo que você esteja familiarizado com o ambiente ESP32 Arduino.

Esta versão do controle remoto pode controlar a gravação, o foco e a abertura da câmera via bluetooth. Dê uma olhada no vídeo. É muito fácil adicionar mais funções de controle de acordo com o manual de controle bluetooth do BMPCC4k. Basicamente, qualquer coisa na câmera pode ser controlada, pelo que vi.

Seria uma etapa fácil adicionar um módulo LIDAR para medir a distância de um objeto, para que você possa obter algum tipo de sistema de foco automático … Embora seja questionável se você pode obter um foco preciso o suficiente em áreas específicas, como olhos, etc …

ATUALIZAÇÃO 2020: Fiz a versão 3.0. É baseado em uma roda giratória livre usando um codificador magnético. Ele também se conecta ao meu motor de follow focus, que basicamente se torna um segundo dispositivo bluetooth (o ESP32 suporta múltiplas conexões bluetooth). O novo vídeo demonstra isso.

Se você gostaria de solicitar a versão 3, dê uma olhada no site MagicButton

Suprimentos

Qualquer módulo ESP32 com wi-fi e bluetooth. Usei o TTGO micro32 porque ele é minúsculo:

Uma roda de foco, qualquer potenciômetro serviria. Usei o seguinte porque é minúsculo: https://www.aliexpress.com/item/32963061806.html? S… Esse tipo tem paradas rígidas nos limites superior e inferior. Em uma versão futura, usarei um codificador rotativo. Desta forma, o foco ou a abertura não "pula" para a configuração atual da roda quando entro em um modo.

Um botão rec / modo. Usei o seguinte: https://www.aliexpress.com/item/32806223591.html? S…

Outros componentes padrão, como resistores, tampas, … (consulte o esquema)

Etapa 1: O Código

Eu uso o recurso wi-fi do ESP32 para me conectar a uma rede conhecida no modo AP ou, quando estou em campo, ele se torna uma estação (STA) à qual posso me conectar. Assim posso configurar o módulo. Não vou entrar em detalhes sobre a seção wi-fi / página da web, posso adicionar isso em um estágio posterior.

O ESP32 se conecta à câmera e se torna um cliente Bluetooth LE. O código bluetooth incluído na estrutura ESP32 do Arduino não funciona com o BMPCC4k. Wakwak-koba consertou isso para nós. Obrigado Wakwak-koba! Usei a biblioteca BLE daqui:

github.com/wakwak-koba/arduino-esp32

No entanto, essa versão do BLE lib ainda está em desenvolvimento e a versão mais recente do BLEUUID.cpp parece não funcionar no momento, então pegue a versão anterior "verificada" deste arquivo.

De resto, a maior parte do meu código bluetooth é muito semelhante aos exemplos BLE incluídos na estrutura do Arduino:

Alguns BLE UUID e variáveis definem:

estático BLEUUID BlackMagic ("00001800-0000-1000-8000-00805f9b34fb");

estático BLEUUID ControlserviceUUID ("291D567A-6D75-11E6-8B77-86F30CA893D3"); estático BLEUUID DevInfoServiceControlUUID ("180A"); BLEUUID estático ControlcharUUID ("5DD3465F-1AEE-4299-8493-D2ECA2F8E1BB"); estático BLEUUID NotifcharUUID ("B864E140-76A0-416A-BF30-5876504537D9"); BLEUUID estático ClientNamecharUUID ("FFAC0C52-C9FB-41A0-B063-CC76282EB89C"); estático BLEUUID CamModelcharUUID ("2A24"); estático BLEScan * pBLEScan = BLEDevice:: getScan (); estático BLEAddress * pServerAddress; static BLEAdvertisedDevice * myDevice; static BLERemoteCharacteristic * pControlCharacteristic; static BLERemoteCharacteristic * pNotifCharacteristic; static boolean doConnect = 0; booleano estático conectado = 0; varredura de volatilebool = 0; volatileuint32_t pinCode;

A varredura e o loop principal:

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {

void onResult (BLEAdvertisedDevice advertisedDevice) {Serial.print ("Dispositivo anunciado BLE encontrado:"); Serial.println (advertisedDevice.toString (). C_str ()); if (advertisedDevice.haveServiceUUID () && advertisedDevice.getServiceUUID (). equals (BlackMagic)) {Serial.print ("Nosso dispositivo foi encontrado!"); advertisedDevice.getScan () -> stop (); myDevice = new BLEAdvertisedDevice (advertisedDevice); doConnect = true; }}}; static void scanCompleteCB (BLEScanResults scanResults) {Serial.println ("digitalização concluída"); digitalização = falso; } void loop (void) {if (! connected && ((uint32_t) (millis () - Timer)> BLE_RESCAN_TIME || (! scanning))) {Serial.println ("scanning…"); digitalização = verdadeiro; pBLEScan-> iniciar (BLE_SCAN_TIME, scanCompleteCB); Temporizador = milis (); } if (doConnect == true) {if (connectToServer ()) {Serial.println ("Agora estamos conectados ao servidor BLE."); conectado = verdadeiro; } else {Serial.println ("Falha ao conectar ao servidor; não há mais nada que faremos."); } doConnect = false; }}

Conectando-se à câmera:

bool connectToServer () {

Serial.print ("Formando uma conexão com"); Serial.println (meuDispositivo-> getAddress (). ToString (). C_str ()); BLEDevice:: setEncryptionLevel (ESP_BLE_SEC_ENCRYPT); BLEDevice:: setSecurityCallbacks (new MySecurity ()); BLESecurity * pSecurity = novo BLESecurity (); pSecurity-> setKeySize (); pSecurity-> setAuthenticationMode (ESP_LE_AUTH_REQ_SC_MITM_BOND); pSecurity-> setCapability (ESP_IO_CAP_IN); pSecurity-> setRespEncryptionKey (ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK); BLEClient * pClient = BLEDevice:: createClient (); pClient-> setClientCallbacks (new MyClientCallback ()); pClient-> conectar (meuDispositivo); Serial.println ("- Conectado ao servidor"); BLEDevice:: setMTU (BLEDevice:: getMTU ()); // OBTENHA O MODELO DE CÂMERA BLERemoteService * pRemoteService = pClient-> getService (DevInfoServiceControlUUID); if (pRemoteService == nullptr) {Serial.print ("- Falha ao obter o serviço de informações do dispositivo"); Serial.println (DevInfoServiceControlUUID.toString (). C_str ()); goto fail; } Serial.println ("- Lendo informações do dispositivo"); // Obtenha uma referência para a característica no serviço do servidor BLE remoto. BLERemoteCharacteristic * pRemoteCamModelCharacteristic = pRemoteService-> getCharacteristic (CamModelcharUUID); if (pRemoteCamModelCharacteristic == nullptr) {Serial.print ("- Falha ao encontrar o modelo da câmera"); Serial.println (CamModelcharUUID.toString (). C_str ()); goto fail; } // Leia o valor da característica. std:: string value = pRemoteCamModelCharacteristic-> readValue (); Serial.print ("Câmera é"); Serial.println (valor.c_str ()); if (CamModel! = value.c_str ()) {Serial.print ("- A câmera não é BMPCC4k"); goto fail; } // OBTENHA O CONTROLE pRemoteService = pClient-> getService (ControlserviceUUID); if (pRemoteService == nullptr) {Serial.print ("- Falha ao obter o serviço da câmera"); Serial.println (ControlserviceUUID.toString (). C_str ()); goto fail; } BLERemoteCharacteristic * pRemoteClientNameCharacteristic = pRemoteService-> getCharacteristic (ClientNamecharUUID); if (pRemoteClientNameCharacteristic! = nullptr) {pRemoteClientNameCharacteristic-> writeValue (MyName.c_str (), MyName.length ()); } pControlCharacteristic = pRemoteService-> getCharacteristic (ControlcharUUID); if (pControlCharacteristic == nullptr) {Serial.print ("- Falha ao obter característica de controle"); Serial.println (ControlcharUUID.toString (). C_str ()); goto fail; } pNotifCharacteristic = pRemoteService-> getCharacteristic (NotifcharUUID); if (pNotifCharacteristic! = nullptr) // && pNotifCharacteristic-> canIndicate ()) {Serial.println ("- assinando a notificação"); const uint8_t identificationOn = {0x2, 0x0}; pNotifCharacteristic-> registerForNotify (notificarCallback, false); pNotifCharacteristic-> getDescriptor (BLEUUID ((uint16_t) 0x2902)) -> writeValue ((uint8_t *) indicaçãoOn, 2, verdadeiro); } return true; falha: pClient-> desconectar (); retorna falso; }

O retorno de chamada conectado / desconectado:

class MyClientCallback: public BLEClientCallbacks {

void onConnect (BLEClient * pclient) {Serial.println ("Estamos conectados."); } void onDisconnect (BLEClient * pclient) {conectado = falso; pclient-> desconectar (); Serial.println ("Desconectamos."); }};

A parte do código PIN:

Na minha versão atual, posso inserir o código PIN através da interface da web, mas esses são detalhes de wi-fi / página da web que devo adicionar mais tarde.

classe MySecurity: public BLESecurityCallbacks

{uint32_t onPassKeyRequest () {Serial.println ("- INSIRA O PIN DE 6 DÍGITOS (termine com ENTER):"); pinCode = 0; char ch; do {while (! Serial.available ()) {delay (1); } ch = Serial.read (); if (ch> = '0' && ch <= '9') {pinCode = pinCode * 10 + (ch -'0 '); Serial.print (ch); }} while ((ch! = '\ n')); return pinCode; } void onPassKeyNotify (uint32_t pass_key) {ESP_LOGE (LOG_TAG, "O número de notificação da senha:% d", pass_key); } bool onConfirmPIN (uint32_t pass_key) {ESP_LOGI (LOG_TAG, "A senha SIM / NÃO número:% d", pass_key); vTaskDelay (5000); returntrue; } bool onSecurityRequest () {ESP_LOGI (LOG_TAG, "Solicitação de segurança"); returntrue; } void onAuthenticationComplete (esp_ble_auth_cmpl_t auth_cmpl) {Serial.print ("status do par ="); Serial.println (auth_cmpl.success); }};

Notificação BLE:

A câmera notifica seus clientes BLE sobre quaisquer alterações na câmera, incluindo quando a câmera inicia e pára de gravar. Este código alterna meu LED quando ele inicia / pára a gravação.

static void NoticeCallback (BLERemoteCharacteristic * pBLERemoteCharacteristic, uint8_t * pData, size_t length, bool isNotify) {// BMPCC4k formato de mensagem BLE: // rec on é 255 9 0 0 10 1 1 2 2 0 64 0 2 // rec off é 255 9 0 0 10 1 1 2 0 0 64 0 2if (length == 13 && pData [0] == 255 && pData [1] == 9 && pData [4] == 10 && pData [5] == 1) {if (pData [8] == 0) { recstatus = 0; } if (pData [8] == 2) {recstatus = 1; }}}

Etapa 2: O Código Parte 2

Esta é a parte que realmente envia os comandos para a câmera.

Gravação:

registro uint8_t = {255, 9, 0, 0, 10, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 0 = OFF, 2 = ON, [8] void Record (boolean RecOn) {if (! RecOn) record [8] = 0; senão registro [8] = 2; pControlCharacteristic-> writeValue ((uint8_t *) registro, 16, verdadeiro); }

Concentrando:

A câmera espera um número de 11 bits, variando de foco próximo a distante. Aconselho colocar um filtro em seu valor de ADC, caso contrário, o foco pode ficar nervosamente instável.

foco uint8_t = {255, 6, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0}; // 0,0… 1,0, 11 bits, [8] = LSB, [9] = MSBvoid Focus (uint16_t val) {// indo de um valor ADC de 12 bits para o foco de valor de 11 bits [8] = (uint8_t) (((val> > 1) & 0xFF)); foco [9] = (uint8_t) (((val >> 1) & 0xFF00) >> 8); pControlCharacteristic-> writeValue ((uint8_t *) focus, 12, true); }

Abertura:

A câmera espera um número de 11 bits, variando de um valor de abertura baixo a alto. Aconselho colocar um filtro em seu valor de ADC, caso contrário, o valor de abertura pode ficar nervosamente instável.

abertura uint8_t = {255, 6, 0, 0, 0, 3, 128, 0, 0, 0, 0, 0}; // 0,0… 1,0, [8] = LSB, [9] = MSBvoid Abertura (uint16_t val) {// indo de um valor ADC de 12 bits para a abertura do valor de 11 bits [8] = (uint8_t) (((val >> 1) & 0xFF)); abertura [9] = (uint8_t) (((val >> 1) & 0xFF00) >> 8); pControlCharacteristic-> writeValue ((uint8_t *) abertura, 12, verdadeiro); }

Etapa 3: o circuito

O circuito
O circuito

Anexei o PDF do meu circuito. Algumas fotos do PCB também estão anexadas.

A placa é alimentada com micro USB.

Depois de receber a placa de circuito impresso, decidi que queria acionar um LED RGB, então conectei dois WS2812B em série na saída "LED de botão" (que precisava de alguns patches de fio na placa de circuito impresso). O PCB foi 8USD com OSHPark.com.

Você pode ver mais algumas conexões no PCB, como "adc", que não estou usando e que foram removidas dos esquemas em anexo. O plano era usar um botão giratório externo no passado, mas atualmente estou perfeitamente feliz com o botão giratório.

Etapa 4: Conclusão

Espero que tenha ajudado.

Tenho em mente algumas atualizações futuras, como o uso de um codificador rotativo sem paradas bruscas. Isso exigirá que o controlador obtenha o valor atual do foco ou abertura da câmera e continue a partir daí. A função "notificarCallback" provavelmente precisa ser atualizada para isso.

O PCB precisa de uma atualização para fornecer os sinais para os LEDs RGB WS2812B corretamente.

Passei muito (muuuuito) tempo fazendo esse trabalho, especialmente a parte BLE. Se isso te ajudou e você quer me pagar uma bebida, isso é muito apreciado:) Este é um link de doação do Paypal:

Recomendado: