schoolpost/BlueMagic32

Cannot set focus

andrewmruddy opened this issue · 11 comments

Using the instantAutoFocus() and toggleRecording() methods, the camera operates as expected! Working great. However, when trying to set focus (float between 0.0 and 1.0), the camera is unresponsive. I figured it was my lens, but I am able to pull focus (not autofocus) remotely via the Bluetooth+ app for BMPCC4k/6k. Is this issue known/any workarounds?

the focus() method is one I have tested using the BMPCC4K and the Sigma 18-35mm + Metabones.

What exact camera/lens/adapter combo are you using?

I am using the BMPCC 6K and the Sigma 18-35mm. Same set up basically. Here is my test code:
void TriggerFocusRack(){
if (BMDConnection.available())
{
for(float i = 0.0; i <= 1.0; i=i+0.1){
BMDControl->focus(i);
Serial.println(i);
delay(250);
}
}
}

Found a post on the Blackmagic Forum saying that the Camera Control Protocol Lens.Focus parameter doesn't seem to work on the BMPCC 6K unless using the Add operation - i.e. you can only change focus relative to the current focus.

A workaround for me, pardon my test code, is to get the current focus on the camera and then either add or subtract the difference so that it equals my 'absolute' focus value, so I can kind-of perform a Set operation:

    float setFocus = 0.5;
    float currentFocus = BMDControl->getFocus();
    float focusDelta = 0.0;

    if( currentFocus > setFocus ){
      focusDelta = -( currentFocus - setFocus );
    } else {
      focusDelta = ( setFocus - currentFocus );
    }

    // Jumble of math below for focusVal is just doing what BlueMagicCameraController::mapFloat() does
    uint16_t focusVal = (uint32_t)( ( focusDelta - 0.0 ) * (2047.0 - 0.0) / (1.0 - 0.0) + 0.0 );             
    uint8_t focusL = focusVal & 0xff;
    uint8_t focusH = (focusVal >> 8);

    // On all cameras, 'add focusVal' to the current focus.
    uint8_t data[12] = {255, 6, 0, 0, 0, 0, 128, 1, focusL, focusH, 0, 0};
    
    BMDControl->custom(data, 12);

Good find! @BenjaminNelan I have a prelimary fix in the latest PR, if you have an EF camera and would be able to test that would be great!

During connection we check to see if the camera is a BMPCC4K, if it is not it will be default to an "EF CAMERA" and the focus() method will use your above code for setting the focus.

Hi @schoolpost ,
is there a chance to test your your preliminary release?
I have a BMPCC 6K with some Sigma EF lenses available.

@BenjaminNelan :
Thank you for posting your code snippet - do you have simple test sketch?

@schoolpost :
I do also think I have found an issue regarding "getShutter()". If you set your camera to display shutter speed instead of shutter angle it will always return 180 even if the shutter angle would be e.g. 360 (or 1/25s at 25 FPS).

@PhotoVideoGuy Thanks for bumping this - I actually need to experiment some more.

I thought I had it figured out - but unfortunately when linked up to a potentiometer it seems like it's incredibly sensitive. You turn slightly left, focus is set to max, slightly to the right, focus is set to minimum. I wasn't able to figure it out before I went on a shoot so just settled for an autofocus trigger.

Whether it's issue with the code I listed above or how I'm reading the potentiometer I'm not sure, but now that you've reminded me I'll take another look. Will get back to you in a bit.

@BenjaminNelan
M5StickC_Rotary_Demo
Hi,
I switched all my projects from potentiometers to rotary encoders.
Potentiometers were unreliable - especially outdoors.

As far as I understand the camera problem (relative focus) (not the source code) a rotary encoder might be the better choice for focussing the 6K anyway. No calculations - just add or substract a fixed value from the current focus to move the focus in either directions.

You can download the sample sketch of the GIF / Video above here:
https://www.dropbox.com/s/7y6s1e20f1qex1v/m5stickc_bluemagic_rotary_demo_01.ino?dl=0

It is very basic, but it might help you to switch from potentiometers to rotary encoders, asap.

BTW: Are you active at the BMD Forums? I could not find your user name.

Found a post on the Blackmagic Forum saying that the Camera Control Protocol Lens.Focus parameter doesn't seem to work on the BMPCC 6K unless using the Add operation - i.e. you can only change focus relative to the current focus.

A workaround for me, pardon my test code, is to get the current focus on the camera and then either add or subtract the difference so that it equals my 'absolute' focus value, so I can kind-of perform a Set operation:

    float setFocus = 0.5;
    float currentFocus = BMDControl->getFocus();
    float focusDelta = 0.0;

    if( currentFocus > setFocus ){
      focusDelta = -( currentFocus - setFocus );
    } else {
      focusDelta = ( setFocus - currentFocus );
    }

    // Jumble of math below for focusVal is just doing what BlueMagicCameraController::mapFloat() does
    uint16_t focusVal = (uint32_t)( ( focusDelta - 0.0 ) * (2047.0 - 0.0) / (1.0 - 0.0) + 0.0 );             
    uint8_t focusL = focusVal & 0xff;
    uint8_t focusH = (focusVal >> 8);

    // On all cameras, 'add focusVal' to the current focus.
    uint8_t data[12] = {255, 6, 0, 0, 0, 0, 128, 1, focusL, focusH, 0, 0};
    
    BMDControl->custom(data, 12);

this was super helpful. I did not even realize there was an offset instead of assign bit until I dove deeper after your reply.

Hi @schoolpost , @jkronk and @BenjaminNelan hoping you guys could please help me with my mod to this project?
I want to use the M5 trigger record example file, except display camera settings when not recording, then when the main button is pressed show the timecode and dispaly the LED light. Once the recording is stopped then camera settings are displayed.

This is the M5 code that I ended up getting to work on my M5StickC

#include <M5StickC.h>
#include <BlueMagic32.h>

#define LED_PIN 10

void setup()
{

  M5.begin();
  Serial.begin(115200);

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

  BMDConnection.begin("BlueMagic32");
  BMDControl = BMDConnection.connect();

  M5.Lcd.setTextColor(TFT_WHITE);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(TFT_BLACK);
}

void loop()
{
  M5.update();

  if (M5.BtnB.wasPressed())
  {
    ESP.restart();
  }

  if (BMDConnection.available())
  {

    M5.Lcd.drawCentreString(BMDControl->timecode(), 80, 34, 2);

    if (M5.BtnA.wasPressed())
    {
      BMDControl->toggleRecording();
    }

    if (BMDControl->isRecording())
    {
      M5.Lcd.setTextColor(RED);
      digitalWrite(LED_PIN, LOW);
    }
    else
    {
      M5.Lcd.setTextColor(TFT_WHITE);
      digitalWrite(LED_PIN, HIGH);
    }

    M5.Lcd.fillScreen(TFT_BLACK);
  }
}
```

 

Disclaimer: I have no idea what I'm doing.

@schoolpost I ran a quick test on the update code in this pull request on a BMPCC6k (Software Version 7.3) with a canon 16-35 f4L lens and canon 70-200 2.8L IS MK II and had some odd behavior. This seems to match the behavior I saw when trying to test calibration on the AXC-BM3DF.

I think where we are going wrong with the new EF focus implementation is where we set float currentFocus = getFocus() [BlueMagicCameraController.cpp line 196]. From what I can tell in testing, getFocus() returns a 0 on this camera 100% of the time. So we aren't actually tracking the relative focus as we make changes even after setting the focus to 0.5 on connection.

My proposed solution is a spaghettified version of code that @jkronk provided keeping track of currentFocus in a really obtuse way. This works on both EF lenses I have to hand and I will be able to test on 2 more very common canon EF lenses by the end of the week.

Testing Code - Press the A button and watch the focus rack to .5, 0, .2, .8, 0 to ensure we can go both directions:

#include <M5StickC.h>
#include <BlueMagic32.h>

void setup()
{
  M5.begin();
  Serial.begin(115200);

  BMDConnection.begin("BlueMagic32");
  BMDControl = BMDConnection.connect();

  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(TFT_BLACK);
}

void printOnScreen(int x, int y, String text)
{
  M5.Lcd.setCursor(x, y, 2);
  M5.Lcd.setTextColor(TFT_WHITE);
  M5.Lcd.setTextSize(1);
  M5.Lcd.println(text);
}

void TriggerFocusRack()
{
  if (BMDConnection.available())
  {
    for (float i = 0.0; i <= 1.0; i = i + 0.1) {
      BMDControl->focus(i);
      Serial.println(i);
      delay(250);
      Serial.println(String(BMDControl->getFocus())); //prints a 0 all of the time
    }
  }
}

float focusTest(float currentFocus, float setFocus)
{
    float focusDelta = 0.0;

    if( currentFocus > setFocus ){
      focusDelta = -( currentFocus - setFocus );
    } else {
      focusDelta = ( setFocus - currentFocus );
    }

    // Jumble of math below for focusVal is just doing what BlueMagicCameraController::mapFloat() does
    uint16_t focusVal = (uint32_t)( ( focusDelta - 0.0 ) * (2047.0 - 0.0) / (1.0 - 0.0) + 0.0 );             
    uint8_t focusL = focusVal & 0xff;
    uint8_t focusH = (focusVal >> 8);

    // On all cameras, 'add focusVal' to the current focus.
    uint8_t data[12] = {255, 6, 0, 0, 0, 0, 128, 1, focusL, focusH, 0, 0};
    
    BMDControl->custom(data, 12);

    float newFocus = 0.0;
    newFocus = setFocus;

    return newFocus;
}

void loop()
{
  M5.update();

  if (M5.BtnA.wasPressed())
  {
    BMDControl->focus(0.5); //start at the middle
    float currentFocus = 0.5;
    
    delay(1000);
    Serial.println("Current: " + String(currentFocus));
    float setFocus = 0.0;
    currentFocus = focusTest(currentFocus, setFocus);
    Serial.println("New: " + String(currentFocus));

    delay(1000);
    Serial.println("Current: " + String(currentFocus));
    setFocus = 0.2;
    currentFocus = focusTest(currentFocus, setFocus);
    Serial.println("New: " + String(currentFocus));

    delay(1000);
    Serial.println("Current: " + String(currentFocus));
    setFocus = 0.8;
    currentFocus = focusTest(currentFocus, setFocus);
    Serial.println("New: " + String(currentFocus));

    delay(1000);
    Serial.println("Current: " + String(currentFocus));
    setFocus = 0.0;
    currentFocus = focusTest(currentFocus, setFocus);
    Serial.println("New: " + String(currentFocus));
    
  }

  if (BMDConnection.available())
  {

    if (BMDControl->changed())
    {

      M5.Lcd.fillScreen(TFT_BLACK);

      printOnScreen(0, 0, "F" + String(BMDControl->getAperture(), 1));
      printOnScreen(0, 16, String(BMDControl->getShutter()) + "°");
      printOnScreen(0, 32, String(BMDControl->getIso()));
      printOnScreen(0, 48, String(BMDControl->getWhiteBalance()) + "K");
      printOnScreen(0, 64, String(BMDControl->getFocus())); //shows a 0 all of the time
    }
  }
}

Note:
I had to modify the Bluetooth Scan code section due to my m5stickc running into some Guru Meditation errors in the scan process. I am not nearly skilled enough to troubleshoot where they are occurring or why. I couldn't get the ESP Exception Decoder to correctly interpret the errors. It seems to be an issue in the onResult function but only after the first item in the scan.
I resolved this by setting bool scanned = true in BlueMagicCameraConnection.cpp and hard coding my camera's mac address in BLEAddress address = BLEAddress("FF:FF:FF:FF:FF:FF"). This could indicate a hardware error specific to my m5stick which may be causing other issues.

Edit: It looks like my issue with ble connection has been experienced by at least one other user: 11

@schoolpost I'm having trouble understanding how we are reading settings off the camera. I don't see that referenced in the BM Control reference from their site. Did you reference some documentation for what is available off the camera?