Tabla de contenido:

Magic Button 4k: el 20USD BMPCC 4k (o 6k) Control remoto inalámbrico: 4 pasos (con imágenes)
Magic Button 4k: el 20USD BMPCC 4k (o 6k) Control remoto inalámbrico: 4 pasos (con imágenes)

Video: Magic Button 4k: el 20USD BMPCC 4k (o 6k) Control remoto inalámbrico: 4 pasos (con imágenes)

Video: Magic Button 4k: el 20USD BMPCC 4k (o 6k) Control remoto inalámbrico: 4 pasos (con imágenes)
Video: ATEM Mini Tips Marathon — All 16 Tips in One Video! 2024, Noviembre
Anonim
Image
Image

Mucha gente me ha pedido que comparta algunos detalles sobre mi controlador inalámbrico para BMPCC4k. La mayoría de las preguntas se referían al control de bluetooth, así que mencionaré algunos detalles al respecto. Supongo que está familiarizado con el entorno ESP32 Arduino.

Esta versión del control remoto puede controlar la grabación, el enfoque y la apertura de la cámara a través de bluetooth. Echale un vistazo al video. Es bastante fácil agregar más funciones de control según el manual de control de bluetooth del BMPCC4k. Básicamente, cualquier cosa en la cámara se puede controlar, por lo que he visto.

Sería un paso fácil agregar un módulo LIDAR para medir la distancia de un sujeto, de modo que pueda obtener algún tipo de sistema de enfoque automático … Aunque es cuestionable si puede obtener un enfoque lo suficientemente preciso en áreas específicas como los ojos, etc.

ACTUALIZACIÓN 2020: Hice la versión 3.0. Se basa en una rueda giratoria libre que utiliza un codificador magnético. También se conecta a mi motor de seguimiento de enfoque, que básicamente se convierte en un segundo dispositivo bluetooth (el ESP32 admite múltiples conexiones bluetooth). El nuevo video demuestra esto.

Si desea solicitar la versión 3, consulte el sitio web de MagicButton

Suministros

Cualquier módulo ESP32 con wifi y bluetooth. Usé el TTGO micro32 porque es pequeño:

Una rueda de enfoque, cualquier potenciómetro serviría. Usé lo siguiente porque es pequeño: https://www.aliexpress.com/item/32963061806.html? S… Este tipo tiene paradas difíciles en el límite superior e inferior. En una versión futura usaré un codificador rotatorio. De esta manera, el enfoque o la apertura no "saltan" a la configuración actual de la rueda cuando entro en un modo.

Un botón rec / mode. Usé lo siguiente: https://www.aliexpress.com/item/32806223591.html? S…

Otros componentes estándar como resistencias, tapas,… (ver esquema)

Paso 1: el código

Utilizo la capacidad wifi del ESP32 para conectarme a una red conocida en modo AP o, cuando estoy en el campo, se convierte en una estación (STA) a la que puedo conectarme. De esa forma puedo configurar el módulo. No entraré en detalles de la sección wifi / página web, podría agregar esto en una etapa posterior.

El ESP32 se conecta a la cámara y se convierte en un cliente Bluetooth LE. El código bluetooth incluido en el marco ESP32 de Arduino no funciona con el BMPCC4k. Wakwak-koba nos lo ha arreglado. ¡Gracias Wakwak-koba! Usé la biblioteca BLE desde aquí:

github.com/wakwak-koba/arduino-esp32

Sin embargo, esa versión de la biblioteca BLE todavía está en desarrollo y la última versión de BLEUUID.cpp no parece funcionar en este momento, así que tome la versión "verificada" anterior de este archivo.

Por lo demás, la mayor parte de mi código bluetooth es mucho según los ejemplos BLE incluidos en el marco de Arduino:

Algunos UUID y variables de BLE definen:

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

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

El escaneo y el bucle 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 ("¡Encontramos nuestro dispositivo!"); advertisedDevice.getScan () -> detener (); myDevice = nuevo BLEAdvertisedDevice (advertisedDevice); doConnect = verdadero; }}}; static void scanCompleteCB (BLEScanResults scanResults) {Serial.println ("escaneo hecho"); escaneo = falso; } bucle void (void) {if (! connected && ((uint32_t) (millis () - Timer)> BLE_RESCAN_TIME || (! scan))) {Serial.println ("scan…"); escaneo = verdadero; pBLEScan-> iniciar (BLE_SCAN_TIME, scanCompleteCB); Temporizador = milis (); } if (doConnect == true) {if (connectToServer ()) {Serial.println ("Ahora estamos conectados al servidor BLE."); conectado = verdadero; } else {Serial.println ("No hemos podido conectarnos al servidor; no haremos nada más"); } doConnect = falso; }}

Conexión a la cámara:

bool connectToServer () {

Serial.print ("Estableciendo una conexión con"); Serial.println (myDevice-> getAddress (). ToString (). C_str ()); BLEDevice:: setEncryptionLevel (ESP_BLE_SEC_ENCRYPT); BLEDevice:: setSecurityCallbacks (new MySecurity ()); BLESecurity * pSecurity = nuevo 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-> connect (myDevice); Serial.println ("- Conectado al servidor"); BLEDevice:: setMTU (BLEDevice:: getMTU ()); // OBTENER MODELO DE CÁMARA BLERemoteService * pRemoteService = pClient-> getService (DevInfoServiceControlUUID); if (pRemoteService == nullptr) {Serial.print ("- No se pudo obtener el servicio de información del dispositivo"); Serial.println (DevInfoServiceControlUUID.toString (). C_str ()); ir a fallar; } Serial.println ("- Leer información del dispositivo"); // Obtener una referencia a la característica en el servicio del servidor BLE remoto. BLERemoteCharacteristic * pRemoteCamModelCharacteristic = pRemoteService-> getCharacteristic (CamModelcharUUID); if (pRemoteCamModelCharacteristic == nullptr) {Serial.print ("- No se pudo encontrar el modelo de la cámara"); Serial.println (CamModelcharUUID.toString (). C_str ()); ir a fallar; } // Leer el valor de la característica. std:: valor de cadena = pRemoteCamModelCharacteristic-> readValue (); Serial.print ("La cámara es"); Serial.println (valor.c_str ()); if (CamModel! = value.c_str ()) {Serial.print ("- La cámara no es BMPCC4k"); ir a fallar; } // OBTENER CONTROL pRemoteService = pClient-> getService (ControlserviceUUID); if (pRemoteService == nullptr) {Serial.print ("- No se pudo obtener el servicio de la cámara"); Serial.println (ControlserviceUUID.toString (). C_str ()); ir a fallar; } BLERemoteCharacteristic * pRemoteClientNameCharacteristic = pRemoteService-> getCharacteristic (ClientNamecharUUID); if (pRemoteClientNameCharacteristic! = nullptr) {pRemoteClientNameCharacteristic-> writeValue (MyName.c_str (), MyName.length ()); } pControlCharacteristic = pRemoteService-> getCharacteristic (ControlcharUUID); if (pControlCharacteristic == nullptr) {Serial.print ("- No se pudo obtener la característica de control"); Serial.println (ControlcharUUID.toString (). C_str ()); ir a fallar; } pNotifCharacteristic = pRemoteService-> getCharacteristic (NotifcharUUID); if (pNotifCharacteristic! = nullptr) // && pNotifCharacteristic-> canIndicate ()) {Serial.println ("- suscribiéndose a la notificación"); const uint8_t identityOn = {0x2, 0x0}; pNotifCharacteristic-> registerForNotify (notificarCallback, falso); pNotifCharacteristic-> getDescriptor (BLEUUID ((uint16_t) 0x2902)) -> writeValue ((uint8_t *) indicaciónOn, 2, verdadero); } devuelve verdadero; falla: pCliente-> desconectar (); falso retorno; }

La devolución de llamada conectada / desconectada:

class MyClientCallback: public BLEClientCallbacks {

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

La parte del código pin:

En mi versión actual, puedo ingresar el código PIN a través de la interfaz web, pero estos son detalles de wifi / página web que podría agregar más adelante.

clase MySecurity: public BLESecurityCallbacks

{uint32_t onPassKeyRequest () {Serial.println ("- POR FAVOR INGRESE PIN DE 6 DÍGITOS (termine con ENTER):"); pinCode = 0; char ch; hacer {mientras (! Serial.available ()) {retraso (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 contraseña_clave) {ESP_LOGE (LOG_TAG, "Número de notificación de clave de acceso:% d", clave_contraseña); } bool onConfirmPIN (uint32_t clave_contraseña) {ESP_LOGI (LOG_TAG, "La clave SÍ / NO número:% d", clave_contraseña); vTaskDelay (5000); returntrue; } bool onSecurityRequest () {ESP_LOGI (LOG_TAG, "Solicitud de seguridad"); returntrue; } void onAuthenticationComplete (esp_ble_auth_cmpl_t auth_cmpl) {Serial.print ("estado del par ="); Serial.println (auth_cmpl.success); }};

Notificación BLE:

La cámara notifica a sus clientes BLE sobre cualquier cambio de cámara, incluso cuando la cámara inicia y detiene la grabación. Este código alterna mi LED cuando comienza / detiene la grabación.

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

Paso 2: El Código Parte 2

Esta es la parte que realmente envía los comandos a la cámara.

Grabación:

uint8_t registro = {255, 9, 0, 0, 10, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 0 = APAGADO, 2 = ENCENDIDO, [8] anular Registro (booleano RecOn) {if (! RecOn) registro [8] = 0; más registro [8] = 2; pControlCharacteristic-> writeValue ((uint8_t *) registro, 16, verdadero); }

Enfoque:

La cámara espera un número de 11 bits, que va desde el enfoque cercano al lejano. Aconsejo poner un filtro en su valor de ADC, de lo contrario, el enfoque podría estar nervioso.

uint8_t focus = {255, 6, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0}; // 0.0… 1.0, 11bit, [8] = LSB, [9] = MSBvoid Focus (uint16_t val) {// pasando de un valor ADC de 12 bits a un valor de enfoque de 11 bits focus [8] = (uint8_t) (((val> > 1) & 0xFF)); foco [9] = (uint8_t) (((val >> 1) & 0xFF00) >> 8); pControlCharacteristic-> writeValue ((uint8_t *) foco, 12, verdadero); }

Abertura:

La cámara espera un número de 11 bits, que varía de un valor de apertura bajo a uno alto. Aconsejo poner un filtro en su valor de ADC, de lo contrario, el valor de apertura podría temblar nerviosamente.

uint8_t apertura = {255, 6, 0, 0, 0, 3, 128, 0, 0, 0, 0, 0}; // 0.0… 1.0, [8] = LSB, [9] = MSBvoid Aperture (uint16_t val) {// pasando de un valor ADC de 12 bits a un valor de apertura de 11 bits apertura [8] = (uint8_t) (((val >> 1) & 0xFF)); apertura [9] = (uint8_t) (((val >> 1) & 0xFF00) >> 8); pControlCharacteristic-> writeValue ((uint8_t *) apertura, 12, verdadero); }

Paso 3: el circuito

El circuito
El circuito

Adjunto el PDF de mi circuito. También se adjuntan algunas fotografías de la PCB.

La placa se alimenta con micro USB.

Después de recibir el PCB, decidí que quería manejar un LED RGB, así que conecté dos WS2812B en serie a la salida "Button Led" (que necesitaba algunos parches de cables en el PCB). Los PCB costaban 8 USD con OSHPark.com.

Puede ver algunas conexiones más en la PCB, como "adc", que no estoy usando y que se eliminaron de los esquemas adjuntos. El plan era usar una rueda de enfoque externa en el pasado, pero actualmente estoy perfectamente contento con la pequeña rueda de control.

Paso 4: Conclusión

Espero que esto haya ayudado.

Tengo en mente algunas actualizaciones futuras, como usar un codificador rotatorio sin paradas bruscas. Esto requerirá que el controlador obtenga el valor actual del enfoque o apertura de la cámara y continúe desde allí. La función "notificarCallback" debe actualizarse para eso probablemente.

La PCB necesita una actualización para proporcionar las señales para los LED RGB WS2812B correctamente.

Pasé mucho (muchísimo) tiempo haciendo que esto funcionara, especialmente la parte BLE. Si esto te ayudó y quieres invitarme a una bebida, te lo agradezco mucho:) Este es un enlace de donación de Paypal:

Recomendado: