Sommario:

Magic Button 4k: il telecomando wireless BMPCC 4k (o 6k) da 20 USD: 4 passaggi (con immagini)
Magic Button 4k: il telecomando wireless BMPCC 4k (o 6k) da 20 USD: 4 passaggi (con immagini)

Video: Magic Button 4k: il telecomando wireless BMPCC 4k (o 6k) da 20 USD: 4 passaggi (con immagini)

Video: Magic Button 4k: il telecomando wireless BMPCC 4k (o 6k) da 20 USD: 4 passaggi (con immagini)
Video: ATEM Mini Tips Marathon — All 16 Tips in One Video! 2024, Luglio
Anonim
Image
Image

Molte persone mi hanno chiesto di condividere alcuni dettagli sul mio controller wireless per BMPCC4k. La maggior parte delle domande riguardava il controllo bluetooth, quindi menzionerò alcuni dettagli al riguardo. Presumo che tu abbia familiarità con l'ambiente Arduino ESP32.

Questa versione del telecomando può controllare la registrazione, la messa a fuoco e l'apertura della fotocamera tramite bluetooth. Dai un'occhiata al video. È abbastanza facile aggiungere più funzioni di controllo secondo il manuale di controllo bluetooth del BMPCC4k. Fondamentalmente qualsiasi cosa nella fotocamera può essere controllata, per quanto ho visto.

Sarebbe un passo facile aggiungere un modulo LIDAR per misurare la distanza di un soggetto, in modo da poter ottenere una sorta di sistema di messa a fuoco automatica… Anche se è discutibile se riesci a ottenere una messa a fuoco sufficientemente accurata su aree specifiche come gli occhi, ecc.

AGGIORNAMENTO 2020: ho realizzato la versione 3.0. Si basa su una ruota a rotazione libera che utilizza un encoder magnetico. Si collega anche al mio motore follow focus, che in pratica diventa un secondo dispositivo bluetooth (l'ESP32 supporta più connessioni bluetooth). Il nuovo video lo dimostra.

Se desideri ordinare la versione 3, dai un'occhiata al sito web di MagicButton

Forniture

Qualsiasi modulo ESP32 con wifi e bluetooth. Ho usato il TTGO micro32 perché è minuscolo:

Una rotella di messa a fuoco, qualsiasi potenziometro andrebbe bene. Ho usato quanto segue perché è minuscolo: https://www.aliexpress.com/item/32963061806.html?s… Questo tipo ha arresti duri al limite superiore e inferiore. In una versione futura utilizzerò un encoder rotativo. In questo modo la messa a fuoco o l'apertura non "saltano" all'impostazione della ruota corrente quando entro in una modalità.

Un pulsante di registrazione/modalità. Ho usato quanto segue:

Altri componenti standard come resistori, cappucci, … (vedi schema)

Passaggio 1: il codice

Uso la capacità wifi dell'ESP32 per connettermi a una rete nota in modalità AP o, quando sono sul campo, diventa una stazione (STA) a cui posso connettermi. In questo modo posso configurare il modulo. Non entrerò nei dettagli della sezione wifi/pagina web, potrei aggiungerla in una fase successiva.

L'ESP32 si connette alla fotocamera e diventa un client Bluetooth LE. Il codice bluetooth incluso nel framework ESP32 di Arduino non funziona con BMPCC4k. Wakwak-koba l'ha riparato per noi. Grazie Wakwak-koba! Ho usato la libreria BLE da qui:

github.com/wakwak-koba/arduino-esp32

Tuttavia quella versione della lib BLE è ancora in fase di sviluppo e l'ultima versione di BLEUUID.cpp non sembra funzionare in questo momento, quindi prendi la versione "verificata" precedente di questo file.

Per il resto, la maggior parte del mio codice bluetooth è molto simile agli esempi BLE inclusi nel framework Arduino:

Alcuni UUID BLE e variabili definiscono:

statico BLEUUID BlackMagic("00001800-0000-1000-8000-00805f9b34fb");

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

La scansione e il ciclo principale:

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks{

void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.print("BLE Advertised Device trovato: "); Serial.println(advertisedDevice.toString().c_str()); if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(BlackMagic)) { Serial.print("Trovato il nostro dispositivo!"); AdvertedDevice.getScan()->stop(); myDevice = new BLEAdvertisedDevice(advertisedDevice); doConnect =vero; } } }; static void scanCompleteCB(BLEScanResults scanResults) { Serial.println("scansione eseguita"); scansione = falso; } void loop(void) { if (!connected && ((uint32_t)(millis() - Timer) > BLE_RESCAN_TIME || (!scansione))) { Serial.println("scansione…"); scansione =vero; pBLEScan->start(BLE_SCAN_TIME, scanCompleteCB); Timer = millis(); } if (doConnect ==true) { if (connectToServer()) { Serial.println("Siamo ora connessi al server BLE."); connesso = vero; } else { Serial.println("Non siamo riusciti a connetterci al server; non c'è altro da fare."); } doConnect =falso; } }

Collegamento alla fotocamera:

bool connectToServer(){

Serial.print("Creazione di una connessione a "); Serial.println(myDevice->getAddress().toString().c_str()); BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT); BLEDevice::setSecurityCallbacks(new MySecurity()); BLESecurity *pSecurity = new 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(" - Connesso al server"); BLEDevice::setMTU(BLEDevice::getMTU()); // OTTIENI MODELLO DI TELECAMERA BLERemoteService *pRemoteService = pClient->getService(DevInfoServiceControlUUID); if (pRemoteService == nullptr) { Serial.print(" - Impossibile ottenere il servizio informazioni sul dispositivo"); Serial.println(DevInfoServiceControlUUID.toString().c_str()); andare a fallire; } Serial.println(" - Lettura delle informazioni sul dispositivo"); // Ottenere un riferimento alla caratteristica nel servizio del server BLE remoto. BLERemoteCharacteristic *pRemoteCamModelCharacteristic = pRemoteService->getCharacteristic(CamModelcharUUID); if (pRemoteCamModelCharacteristic == nullptr) { Serial.print(" - Impossibile trovare il modello della fotocamera"); Serial.println(CamModelcharUUID.toString().c_str()); andare a fallire; } // Legge il valore della caratteristica. std::string value = pRemoteCamModelCharacteristic->readValue(); Serial.print("La fotocamera è "); Serial.println(value.c_str()); if (CamModel != value.c_str()) { Serial.print(" - La fotocamera non è BMPCC4k"); andare a fallire; } // OTTIENI IL CONTROLLO pRemoteService = pClient->getService(ControlserviceUUID); if (pRemoteService == nullptr) { Serial.print(" - Impossibile ottenere il servizio fotocamera"); Serial.println(ControlserviceUUID.toString().c_str()); andare a fallire; } BLERemoteCharacteristic *pRemoteClientNameCharacteristic = pRemoteService->getCharacteristic(ClientNamecharUUID); if (pRemoteClientNameCharacteristic != nullptr) { pRemoteClientNameCharacteristic->writeValue(MyName.c_str(), MyName.length()); } pControlCharacteristic = pRemoteService->getCharacteristic(ControlcharUUID); if (pControlCharacteristic == nullptr) { Serial.print(" - Impossibile ottenere la caratteristica di controllo"); Serial.println(ControlcharUUID.toString().c_str()); andare a fallire; } pNotifCharacteristic = pRemoteService->getCharacteristic(NotifcharUUID); if (pNotifCharacteristic != nullptr) // && pNotifCharacteristic->canIndicate()) { Serial.println(" - sottoscrizione della notifica"); const uint8_t indicazioneOn = {0x2, 0x0}; pNotifCharacteristic->registerForNotify(notifyCallback, false); pNotifCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)indicationOn, 2, true); } restituisce vero; fail: pClient->disconnect(); restituire falso; }

La richiamata connessa/disconnessa:

class MyClientCallback: public BLEClientCallbacks{

void onConnect(BLEClient *pclient) { Serial.println("Siamo connessi."); } void onDisconnect(BLEClient *pclient) { connesso =false; pclient->disconnect(); Serial.println("Ci siamo disconnessi."); } };

La parte del codice pin:

Nella mia versione attuale posso inserire il codice PIN tramite l'interfaccia web, ma questi sono dettagli wifi/pagina web che potrei aggiungere in seguito.

class MySecurity: public BLESecurityCallbacks

{ uint32_t onPassKeyRequest() { Serial.println("- INSERISCI IL PIN DI 6 CIFRE (termina con INVIO): "); pinCode =0; char ch; do { while (!Serial.available()) { ritardo (1); } ch = Serial.read(); if (ch >='0'&& ch <='9') { pinCode = pinCode *10+ (ch -'0'); Serial.print(ch); } } while ((ch !='\n')); codice PIN di ritorno; } void onPassKeyNotify(uint32_t pass_key) { ESP_LOGE(LOG_TAG, "La passkey Notifica numero:%d", pass_key); } bool onConfirmPIN(uint32_t pass_key) { ESP_LOGI(LOG_TAG, "La passkey YES/NO number:%d", pass_key); vTaskDelay(5000); ritornovero; } bool onSecurityRequest() { ESP_LOGI(LOG_TAG, "Richiesta di sicurezza"); ritornovero; } void onAuthenticationComplete(esp_ble_auth_cmpl_t auth_cmpl) { Serial.print("pair status = "); Serial.println(auth_cmpl.success); } };

Notifica BLE:

La telecamera notifica ai suoi client BLE eventuali modifiche alla telecamera, incluso quando la telecamera avvia e interrompe la registrazione. Questo codice attiva il mio LED quando avvia/arresta la registrazione.

static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t*pData, size_t length, bool isNotify) { // BMPCC4k BLE message format:// rec on is 255 9 0 0 10 1 1 2 2 0 64 0 2// rec off is 255 9 0 0 10 1 1 2 0 0 64 0 2if (lunghezza ==13&& pData[0] ==255&& pData[1] ==9&& pData[4] ==10&& pData[5] ==1) { if (pData[8] ==0) { stato rec =0; } if (pData[8] ==2) { recstatus =1; } } }

Passaggio 2: il codice parte 2

Questa è la parte che invia effettivamente i comandi alla telecamera.

Registrazione:

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

Messa a fuoco:

La fotocamera prevede un numero di 11 bit, che va da vicino a lontano. Consiglio di mettere un filtro sul valore ADC, altrimenti la messa a fuoco potrebbe essere nervosamente tremante.

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) { //passando da un valore ADC a 12 bit a un valore focus a 11 bit focus[8] = (uint8_t)(((val > >1) &0xFF)); focus[9] = (uint8_t)(((val >>1) &0xFF00) >>8); pControlCharacteristic->writeValue((uint8_t*)focus, 12, true); }

Apertura:

La fotocamera prevede un numero di 11 bit, che va da un valore di apertura basso a uno alto. Consiglio di mettere un filtro sul valore ADC, altrimenti il valore di apertura potrebbe essere nervoso.

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) { //passa da un valore ADC a 12 bit a un valore di apertura a 11 bit aperture[8] = (uint8_t)(((val >>1) &0xFF)); apertura[9] = (uint8_t)(((val >>1) &0xFF00) >>8); pControlCharacteristic->writeValue((uint8_t*)aperture, 12, true); }

Passaggio 3: il circuito

Il circuito
Il circuito

Ho allegato il PDF del mio circuito. In allegato anche alcune foto del PCB.

La scheda è alimentata con micro USB.

Dopo aver ricevuto il PCB ho deciso che volevo pilotare un LED RGB, quindi ho collegato due WS2812B in serie all'uscita "Button Led" (che necessitava di alcune patch di filo sul PCB). I PCB erano 8USD con OSHPark.com.

Puoi vedere alcune altre connessioni sul PCB come "adc" che non sto usando e che sono state rimosse dagli schemi allegati. Il piano era di utilizzare una rotella di messa a fuoco esterna in passato, ma attualmente sono perfettamente soddisfatto della rotella zigrinata.

Passaggio 4: conclusione

Spero che questo abbia aiutato.

Ho in mente alcuni aggiornamenti futuri, come l'utilizzo di un encoder rotativo senza arresti anomali. Ciò richiederà che il controller ottenga il valore corrente della messa a fuoco o dell'apertura dalla fotocamera e continui da lì. La funzione "notifyCallback" deve essere aggiornata per questo probabilmente.

Il PCB necessita di un aggiornamento per fornire correttamente i segnali per i LED RGB WS2812B.

Ho speso molto (un moooolto) tempo nel fare questo lavoro, specialmente la parte BLE. Se questo ti ha aiutato e vuoi offrirmi da bere, è molto apprezzato:) Questo è un link di donazione Paypal:

Consigliato: