Page 2 of 3
Re: Arduino Shield Thread
Posted:
Thu Mar 02, 2017 7:34 pm
by Benjamin Higginbotham
Wait... so I *can* read incoming camera info?
Scenario: I have 4 cameras in one location and 8 more in a remote location about 4000 km away. All of them are BMD cams of sorts and I want to use one switcher interface to paint them all. Can I use one shield at the origin site to read all of the camera settings for all cameras, sling that down the wire over a private WAN and have a shield on the other end spit out commanding for distribution to my cameras via SDI?
I was under the impression this was not possible?
Re: Arduino Shield Thread
Posted:
Thu Mar 02, 2017 9:19 pm
by Xtreemtec
Well iT is. Skaarhoj already does this with there sdi tally iris Control box..
What you are suggesting should be possible.. Takes à lot of programming. Also there are issues that the shield is missing incoming packets.. Tally is data that is send 10 times à second.. But shading data like step up gain.. Could be lost in the process.. So it is not het completely Foolproof
Re: Arduino Shield Thread
Posted:
Thu Mar 02, 2017 9:39 pm
by Baz
Then of course you must be able to extract the ch15/16 talkback.
Re: Arduino Shield Thread
Posted:
Thu Mar 02, 2017 9:42 pm
by Benjamin Higginbotham
Baz wrote:Then of course you must be able to extract the ch15/16 talkback.
We don't need comms, only control. My cameras are in areas where... uh... people can't really be.
Re: Arduino Shield Thread
Posted:
Thu Mar 02, 2017 9:48 pm
by Xtreemtec
Bug Benjamin. What you want To do could have been done since the release of the shield and an atmega plus ethernet shield..
Sending off the network protocol of atem to the Remote arduino and use that as a converter......
Mark Gilbert from Strata had No problem taking over My atem by the internet from Engeland..
So atem Control over the internet has been done before...
Re: Arduino Shield Thread
Posted:
Thu Mar 02, 2017 9:51 pm
by Benjamin Higginbotham
We control over our network today. That's not in question. The part in question is input from our current switcher which is something we don't do. Instead we have a second system that we control and send the commanding out. Not desired.
So have the shield take SDI input from the ATEM, convert the commands it reads to IP, send it to the remote side and from there we're already OK converting back to commanding on SDI. It's that input side we always seemed to be missing.
Re: Arduino Shield Thread
Posted:
Tue Mar 14, 2017 10:57 pm
by Radosław Przybył
AFAIK reading camera settings is not possible. You can controll as many as 253 or 254 cameras simultaneously connected to single SDI network with one SDI controller. You can upload and synchronize all settings to all or some of cameras, but you can not read current camera settings via SDI Shield. It is one directional communication (you can pickup some information from incoming signal - wchich usualy comes from mixer)
Am I wrong? Is there any possibility to read camera settings? Am I missing a part of documentation? It could be great expansion for my SDI Remote&Sequencer prototype.
Re: Arduino Shield Thread
Posted:
Wed Mar 15, 2017 4:49 am
by Baz
Re: Arduino Shield Thread
Posted:
Thu Mar 16, 2017 7:29 pm
by Radosław Przybył
Just finished prototype development SDI Remote. Proud
- sdiremote_small.jpg (306.76 KiB) Viewed 24001 times
Re: Arduino Shield Thread
Posted:
Mon Mar 20, 2017 8:10 pm
by Anna Woodson
Anyone have a recommendation for a power supply to be used with this shield? I thought I could use the same as my Arduino, but it has a different size barrel. I'm not seeing the barrel size anywhere in the manual.
Thanks!
Re: Arduino Shield Thread
Posted:
Mon Mar 20, 2017 10:35 pm
by Radosław Przybył
Mine from Arduino fits.
Re: Arduino Shield Thread
Posted:
Mon Mar 20, 2017 11:11 pm
by Håvard Njåstad
Most stuff (arduino) tend to use 5.5 X 2.1mm barrels, but all blackmagic equipment (blackmagic arduino shield) use 5.5 X 2.5mm, so any generic 12v adapter with those dimensions will fit
Re: Arduino Shield Thread
Posted:
Thu Mar 23, 2017 8:49 am
by Radosław Przybył
Is Ursa Mini Pro compatible with SDI Shield?
Re: Arduino Shield Thread
Posted:
Thu Mar 23, 2017 9:50 am
by Xtreemtec
Offcoarse it is. The protocol Didnt change..
Re: Arduino Shield Thread
Posted:
Fri Mar 24, 2017 11:51 pm
by Radosław Przybył
Hello! I am back with technical question. Is Message grouping working OOB with high level commands like sdiCameraControl.writeVarType? I need to change a lot of camera params in short periods of time (perfectly every frame) - will they group automatically in send buffer before sending or should I use low level commands to fill send buffer manually before sending them to camera on next frame?
Regrads
Re: Arduino Shield Thread
Posted:
Wed Mar 29, 2017 7:31 pm
by Anna Woodson
Has anyone used this shield with an Arduino Mega? Since it's communicating through I2C, it should all be the same code. But I seem to be missing something.
Re: Arduino Shield Thread
Posted:
Wed Mar 29, 2017 11:21 pm
by Gary Adams
Hello Anna. The Shield will work with the Mega. You will need to jumper A4 to SDA and A5 to SLL on the Mega.
Regards, Gary
Re: Arduino Shield Thread
Posted:
Fri Mar 31, 2017 1:07 pm
by Xtreemtec
And you need to bend the i2c pins on the shield to prevent they connect to other pins on the mega.. otherwise those ports Will block the i2c.
Re: Arduino Shield Thread
Posted:
Tue May 23, 2017 12:50 pm
by Radosław Przybył
I have no URSA Mini, could you help me with shutter settings? When sending a message in group "Video" no 6 (shutter speed (ordinal)) to Ursa - will it iterate through all 10 shutter settings only? From 360 to 45 degree?
Using SKAARHOJ Kit - Joystick and LCD
Posted:
Fri Jun 09, 2017 12:44 pm
by Jakob Hansen
Hi all,
We have a BMD Studio Micro camera, that we wanted to control for shading.
The otherwise fantastic SKAARHOJ CCU controllers were out of range given our budget.
Instead we decided to try our luck with the BMD Shield, combined with the nice little DIY kit from SKAARHOJ (FaderBoard & Joystick add-on for the Shield).
Initially, we tried going with the faderboard, which connects directly to the top of the shield.
The idea was to switch to different operating modes via the 3 buttons.
But - that doesn't work very well when you want to control different parameters with a fixed encoding fader/rotary knob, as we soon discovered!
Instead, I decided to try and use the Joystick, combined with a LCD for parameter readout.
To get the extra connections required for combining the BMD Shield, SKAARHOJ Joystick and LCD, we had to upgrade to a Arduino Mege (2560).
Thanks to a couple of posts on this forum, we managed to sort the wiring properly.
If you look at the schematic, you get a crude idea of the required wiring.
- CCU_Controller_Schema.jpg (283.74 KiB) Viewed 23256 times
Please note, that the BMD Shield is connected directly to the top of the Mega! So all wiring runs between Shield, JoystickBoard and LCD.
The LCD unit is just the model (LCM1602C) which was supplied in our Arduino Starterkit. It's a 16X2LCD.
- Mega_Shield_LCD.jpg (138.03 KiB) Viewed 23256 times
The code is based on the BMD library's example, "CustomJoystickControl".
As a cheap solution to a shading controller for the Micro, this setup performs great.
- DIY-project vs Ikegami CCP
- Ikegami_vs_DIY.jpg (45.45 KiB) Viewed 23256 times
- Code: Select all
#include <BMDSDIControl.h>
#include <LiquidCrystal.h>
#include <math.h>
#include <Wire.h>
/**
Blackmagic Design 3G-SDI Shield Sketch
Joystick control - JAHA 2017-05-05
This sketch controls a BMD cam via a BMD 3G-SDI shield,
which supports a SKAARHOJ joystick&buttons PCB and controls a SDI-connected BMD-camera.
The three buttons are mapped as follows:
- Button 1, which selects WB-mode
- Button 2, which selects and cycles through black/gamma/gain adj modes
- Button 3, which selects focus-mode on the camera
The joystick is mapped as follows:
- X axis adjusts the mode X parameter
- Y axis adjusts the mode Y parameter
- Pressing the Joystick resets all correction parameters.
*/
// Camera#
const int cameraNumber = 2;
// LCD pin mappings
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
// Hardware pin mappings
const int joystickButtonPin = A0;
const int joystickXPin = A1;
const int joystickYPin = A2;
const int button1Pin = 5;
const int button2Pin = 6;
const int button3Pin = 7;
// Blackmagic Design SDI control shield globals
const int shieldAddress = 0x6E;
BMD_SDITallyControl_I2C sdiTallyControl(shieldAddress);
BMD_SDICameraControl_I2C sdiCameraControl(shieldAddress);
// Button debouncing globals
unsigned long lastStableButtonTime[32];
int rawButtonLevels[32];
int stableButtonLevels[32];
// Joystick sample rate limiter globals
unsigned long lastJoystickUpdateTime;
// Global joystick detection parameters
int currentJoystickX = 0;
int currentJoystickY = 0;
// Camera parameter adjustment-state, globals
// Manual WhiteBalance
float manualWbValueController = 6; //4000
const float manualWbValueSensHigh = 0.2; // joy max deflection adjust
const float manualWbValueSensNormal = 0.05; // joy normal deflection adjust
const float manualWbFloor = 0; // 2500
const float manualWbTop = 17; // 8000
const int16_t manualWbValues[18] = { 2500, 2800, 3000, 3200, 3400, 3600, 4000, 4500, 4800, 5000,5200, 5400, 5600, 6000, 6500, 7000, 7500, 8000 };
int16_t manualWbValueSendToDevice;
// Lift/Blacklevel
float liftValue = 0;
const float liftValueSensHigh = 0.005;
const float liftValueSensNormal = 0.001;
float liftValueArray[4] = { 0.0, 0.0, 0.0, 0.0 };
const float liftFloor = -2;
const float liftTop = 2;
// Gamma
float gammaValue = 0;
const float gammaValueSensHigh = 0.005;
const float gammaValueSensNormal = 0.001;
float gammaValueArray[4] = { 0.0, 0.0, 0.0, 0.0 };
const float gammaFloor = -4;
const float gammaTop = 4;
// Gain
float gainValue = 1;
const float gainValueSensHigh = 0.03;
const float gainValueSensNormal = 0.01;
float gainValueArray[4] = { 0.0, 0.0, 0.0, 0.0 };
const float gainFloor = 0;
const float gainTop = 16;
// MasterGain
float masterGainValueController = 1.0;
const float masterGainSensHigh = 0.1;
const float masterGainSensNormal = 0.05;
const int masterGainValues[5] = { 1, 2, 4, 8, 16 }; // gain x1, x2, x4, x8, x16
const int masterGainFloor = 0; //x1
const int masterGainTop = 4; //x16
int masterGainSendToDevice;
// Focus
float focusValue = 0.5;
const float focusValueSensHigh = 0.01;
const float focusValueSensNormal = 0.002;
const float focusFloor = 0.0;
const float focusTop = 1.0;
// ModeSelect - global parameter, determines operation-mode
// 1 - Whitebalance
// 2 - Lift (CC) & mastergain
// 3 - Gamma (CC) & mastergain
// 4 - Gain (CC) & mastergain
// 5 - Focus
int ModeSelect = 0; // current mode
int previousMode = 0; // previous mode
// ColorCorrection-mode
int currentCCMode = 1; // current ColorCorrectionMode: Lift, Gamma, Gain
bool ccMode; // flag true if CCmode is active
void setup() {
Serial.begin(9600);
Serial.println("startup");
lcd.begin(16, 2);
lcd.print("CCU controller");
// Configure digital inputs
pinMode(joystickButtonPin, INPUT_PULLUP);
pinMode(button1Pin, INPUT_PULLUP);
pinMode(button2Pin, INPUT_PULLUP);
pinMode(button3Pin, INPUT_PULLUP);
// Set up the BMD SDI control library
sdiTallyControl.begin();
sdiCameraControl.begin();
// The shield supports up to 400KHz, use faster
// I2C speed to reduce latency
Wire.setClock(400000);
// Enable both tally and control overrides
sdiTallyControl.setOverride(true);
sdiCameraControl.setOverride(true);
// reset camera to defaults
DoParameterUpdateResetAll();
// display welcome message
lcd.setCursor(0, 0);
lcd.print("CCU controller");
}
void loop() {
DetectOperationMode();
ReadJoystickInput();
DoParameterUpdate();
}
void DetectOperationMode() {
// Detect button1 - WhiteBalance
if (getButtonStableEdge(button1Pin) == true && getButtonStableLevel(button1Pin) == LOW) {
// When the button is low (pressed) the WB-mode is activated
ModeSelect = 1;
ccMode = false;
Serial.println("Mode1 detected"); //debug only
CheckDisplayClear();
}
// Detect button2, cycle through black/gamma/gain adjustment modes
if (getButtonStableEdge(button2Pin) == true && getButtonStableLevel(button2Pin) == LOW) {
// detect if we should step to next cc-mode
if (ccMode) {
currentCCMode = currentCCMode + 1;
if (currentCCMode > 3)
currentCCMode = 1;
}
ccMode = true;
if (currentCCMode == 1) {
ModeSelect = 2; // Lift
}
else if (currentCCMode == 2) {
ModeSelect = 3; // Gamma
}
else if (currentCCMode == 3) {
ModeSelect = 4; // Gain
}
Serial.println("Mode2, 3 or 4 detected"); // debug only
Serial.println(ModeSelect);
CheckDisplayClear();
}
// Detect button3, select focus mode
if (getButtonStableEdge(button3Pin) == true && getButtonStableLevel(button3Pin) == LOW) {
ModeSelect = 5; // Focus
ccMode = false;
Serial.println("Mode5 detected"); // debug only
CheckDisplayClear();
}
// If the reset button is pressed, clear all color correction values
if (getButtonStableEdge(joystickButtonPin) == true && getButtonStableLevel(joystickButtonPin) == LOW) {
DoParameterUpdateResetAll();
Serial.println("Reset detected");
}
}
void ReadJoystickInput() {
if (getJoystickUpdateReady() == true) {
switch (ModeSelect) {
case (0): // ignore
break;
case (1): // Whitebalance
Serial.println("ReadJoy > case 1");
// joystick Y = whitebalance K
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
manualWbValueController = manualWbValueController + manualWbValueSensHigh; // using wb sensitivity-constant
}
else if (currentJoystickY > 0) {
manualWbValueController = manualWbValueController + manualWbValueSensNormal;
}
else if (currentJoystickY < -80) {
manualWbValueController = manualWbValueController - manualWbValueSensHigh;
}
else if (currentJoystickY < 0) {
manualWbValueController = manualWbValueController - manualWbValueSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
manualWbValueController = constrain(manualWbValueController, manualWbFloor, manualWbTop);
break;
case (2): // CC Lift
Serial.println("ReadJoy > case 2");
// joystick Y = lift
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
liftValue = liftValue + liftValueSensHigh; // using lift sensitivity-constant
}
else if (currentJoystickY > 0) {
liftValue = liftValue + liftValueSensNormal;
}
else if (currentJoystickY < -80) {
liftValue = liftValue - liftValueSensHigh;
}
else if (currentJoystickY < 0) {
liftValue = liftValue - liftValueSensNormal;
}
ReadJoystickInputMasterGain();
// Don't allow the values to exceed the minimum/maximum
liftValue = constrain(liftValue, liftFloor, liftTop);
break;
case (3): // CC Gamma
Serial.println("ReadJoy > case 3");
// joystick Y = gamma
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
gammaValue = gammaValue + gammaValueSensHigh; // using gamma sensitivity-constant
}
else if (currentJoystickY > 0) {
gammaValue = gammaValue + gammaValueSensNormal;
}
else if (currentJoystickY < -80) {
gammaValue = gammaValue - gammaValueSensHigh;
}
else if (currentJoystickY < 0) {
gammaValue = gammaValue - gammaValueSensNormal;
}
ReadJoystickInputMasterGain();
// Don't allow the values to exceed the minimum/maximum
gammaValue = constrain(gammaValue, gammaFloor, gammaTop);
break;
case (4): // CC Gain
Serial.println("ReadJoy > case 4");
// joystick Y = gain
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
gainValue = gainValue + gainValueSensHigh; // use gain sensitivity-constant
}
else if (currentJoystickY > 0) {
gainValue = gainValue + gainValueSensNormal;
}
else if (currentJoystickY < -80) {
gainValue = gainValue - gainValueSensHigh;
}
else if (currentJoystickY < 0) {
gainValue = gainValue - gainValueSensNormal;
}
ReadJoystickInputMasterGain();
// Don't allow the values to exceed the minimum/maximum
gainValue = constrain(gainValue, gainFloor, gainTop);
break;
case (5): // Focus
Serial.println("ReadJoy > case 5");
// joystick Y
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
focusValue = focusValue + focusValueSensHigh; // use focus sensitivity-constant
}
else if (currentJoystickY > 0) {
focusValue = focusValue + focusValueSensNormal;
}
else if (currentJoystickY < -80) {
focusValue = focusValue - focusValueSensHigh;
}
else if (currentJoystickY < 0) {
focusValue = focusValue - focusValueSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
focusValue = constrain(focusValue, focusFloor, focusTop);
break;
}
}
}
void ReadJoystickInputMasterGain() {
// joystick X = masterGain
currentJoystickX = getJoystickAxisPercent(joystickXPin);
if (currentJoystickX > 80) {
masterGainValueController = masterGainValueController + masterGainSensHigh;
}
else if (currentJoystickX > 0) {
masterGainValueController = masterGainValueController + masterGainSensNormal;
}
else if (currentJoystickX < -80) {
masterGainValueController = masterGainValueController - masterGainSensHigh;
}
else if (currentJoystickX < 0) {
masterGainValueController = masterGainValueController - masterGainSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
masterGainValueController = constrain(masterGainValueController, masterGainFloor, masterGainTop);
}
void DoParameterUpdate() {
// Send new parameter adjustment to the camera
switch (ModeSelect) {
case (0): // ignore
break;
case (1): // Whitebalance
// joystick Y (manualWbValue)
DoParameterUpdateWhiteBalance();
break;
case (2): // CC Lift
// joystick Y = lift (liftValue)
// joystick X = masterGain
DoParameterUpdateLift();
DoParameterUpdateMasterGain();
break;
case (3): // CC Gamma
// joystick Y = gamma
// joystick X = masterGain
DoParameterUpdateGamma();
DoParameterUpdateMasterGain();
break;
case (4): // CC Gain
// joystick Y = gain
// joystick X = masterGain
DoParameterUpdateGain();
DoParameterUpdateMasterGain();
break;
case (5): // Focus
// joystick X
DoParameterUpdateFocus();
break;
}
}
void DoParameterUpdateWhiteBalance() {
Serial.println("ParameterUpdate > case 1");
manualWbValueSendToDevice = manualWbValues[round(manualWbValueController)];
sdiCameraControl.writeCommandInt16(
cameraNumber, // Destination: Camera number
1, // Category: Video
2, // Param: White balance
0, // Operation: Set Absolute,
manualWbValueSendToDevice // manualWbValue
);
UpdateDisplay(5, "WhiteBalance", manualWbValueSendToDevice);
}
void DoParameterUpdateLift() {
Serial.println("ParameterUpdate > Lift");
liftValueArray[0] = liftValue;
liftValueArray[1] = liftValue;
liftValueArray[2] = liftValue;
liftValueArray[3] = liftValue;
// set lift values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
8, // Category: Color Correction
0, // Param: Offset Adjust
0, // Operation: Set Absolute,
liftValueArray // lift values
);
UpdateDisplay(5, "Black", liftValue);
}
void DoParameterUpdateGamma() {
Serial.println("ParameterUpdate > Gamma");
gammaValueArray[0] = gammaValue;
gammaValueArray[1] = gammaValue;
gammaValueArray[2] = gammaValue;
gammaValueArray[3] = gammaValue;
// set gamma values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
8, // Category: Color Correction
1, // Param: Gamma adjust
0, // Operation: Set Absolute,
gammaValueArray // gamma value
);
UpdateDisplay(5, "Gamma", gammaValue);
}
void DoParameterUpdateGain() {
Serial.println("ParameterUpdate > Gain");
gainValueArray[0] = gainValue;
gainValueArray[1] = gainValue;
gainValueArray[2] = gainValue;
gainValueArray[3] = gainValue;
// set gain values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
8, // Category: Color Correction
2, // Param: Gain adjust
0, // Operation: Set Absolute,
gainValueArray // gain value
);
UpdateDisplay(5, "Gain", gainValue);
}
void DoParameterUpdateFocus() {
Serial.println("ParameterUpdate > focus");
// set focus values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
0, // Category: Lens
0, // Param: Focus
0, // Operation: Set Absolute,
focusValue // focus value
);
UpdateDisplay(1, "Focus", focusValue);
UpdateDisplay(3, "", focusValue);
}
void DoParameterUpdateResetAll() {
// Reset color correction
for (int i = 0; i < 10; i++) {
Serial.println("Reset camera parameters"); // looping to increase readability in serial-monitor
}
manualWbValueController = 6; //4000K
liftValue = 0.02;
gammaValue = 0.15;
gainValue = 1.4;
focusValue = 0.52;
masterGainValueController = 3;
DoParameterUpdateWhiteBalance();
DoParameterUpdateLift();
DoParameterUpdateGamma();
DoParameterUpdateGain();
DoParameterUpdateMasterGain();
DoParameterUpdateFocus();
lcd.clear();
/*
// Reset all color correction parameters in the camera
sdiCameraControl.writeCommandVoid(
cameraNumber, // Destination: Camera
8, // Category: Color Correction
7 // Param: Reset Defaults
);
// Request auto-iris adjustment in the camera
sdiCameraControl.writeCommandVoid(
cameraNumber, // Destination: Camera
0, // Category: Lens
5 // Param: Auto Iris
);
*/
}
void DoParameterUpdateMasterGain() {
masterGainSendToDevice = masterGainValues[round(masterGainValueController)];
sdiCameraControl.writeCommandInt8(
cameraNumber, // Destination: Camera number
1, // Category: Video
1, // Param: Sensor gain
0, // Operation: Set Absolute,
masterGainSendToDevice // masterGainValue
);
UpdateDisplay(6, "mGain", masterGainSendToDevice);
}
bool getJoystickUpdateReady() {
// Determines if we are ready for another joystick update (this is
// a rate limiter to ensure that the user can slowly adjust the
// parameters easily with the joystick)
unsigned long currentTime = millis();
if ((lastJoystickUpdateTime - currentTime) > 100) {
lastJoystickUpdateTime = currentTime;
return true;
}
return false;
}
int getJoystickAxisPercent(int analogPin) {
// Reads the joystick axis on the given analog pin as a [-100 - 100] scaled value
int rawAnalogValue = analogRead(analogPin);
int scaledAnalogValue = map(rawAnalogValue, 0, 1023, -100, 100);
// Consider values close to zero as zero, so that when the joystick is
// centered it reports zero even if it is slightly mis-aligned
if (abs(scaledAnalogValue) < 10) {
scaledAnalogValue = 0;
}
return scaledAnalogValue;
}
bool getButtonStableEdge(int digitalPin) {
// Detects debounced edges (i.e. presses and releases) of a button
bool previousLevel = stableButtonLevels[digitalPin];
bool newLevel = getButtonStableLevel(digitalPin);
return previousLevel != newLevel;
}
int getButtonStableLevel(int digitalPin) {
// Reads a digital pin and filters it, returning the stable button position
int pinLevel = digitalRead(digitalPin);
unsigned long currentTime = millis();
// If the button is rapidly changing (bouncing) during a press, keep
// resetting the last stable time count
if (pinLevel != rawButtonLevels[digitalPin]) {
lastStableButtonTime[digitalPin] = currentTime;
rawButtonLevels[digitalPin] = pinLevel;
}
// Once the button has been stable for
if ((currentTime - lastStableButtonTime[digitalPin]) > 20) {
stableButtonLevels[digitalPin] = pinLevel;
}
return stableButtonLevels[digitalPin];
}
void UpdateDisplay(int _position, char _text[], float _value) {
// split lcd-display into 6 areas:
// upper-left = 1
// upper-right = 2
// lower-left = 3
// lower-right = 4
// left upper+lower = 5
// right upper+lower = 6
if (_position <= 0 || _position > 6) {
Serial.print("lcd-position out of bounds");
return;
}
// /*
Serial.print(_text);
Serial.print(" ");
Serial.println(_value);
// */
switch (_position) {
case (1): // row = 0, column = 0, upper left
lcd.setCursor(0, 0);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (2): // row = 7, column = 0, upper right
lcd.setCursor(7, 0);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (3): // row = 0, column = 1, lower left
lcd.setCursor(0, 1);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (4): // row = 7, column = 1, lower right
lcd.setCursor(7, 1);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (5): // text + value, left part of lcd
lcd.setCursor(0, 0);
lcd.print(_text);
lcd.setCursor(0, 1);
lcd.print(_value);
break;
case (6): // text + value, right part of lcd
lcd.setCursor(7, 0);
lcd.print(_text);
lcd.setCursor(7, 1);
lcd.print(_value);
break;
}
}
void CheckDisplayClear() {
if (previousMode != ModeSelect) {
lcd.clear();
Serial.print("CLEAR CLEAR CLEAR CLEAR CLEAR CLEAR CLEAR CLEAR");
}
previousMode = ModeSelect;
}
Re: Arduino Shield Thread
Posted:
Mon Jun 12, 2017 4:43 pm
by Denny Smith
Nice job, looks good, and it works!
Cheers
Re: Arduino Shield Thread
Posted:
Sun Sep 17, 2017 8:48 pm
by Marco Monaldi
hello Jakob i am trying to use 3g-sdi shield with an i2c display (with controller HD44780) but when sketch runs the sdiCameraControl.begin () command; the display will no longer work and even Serial.print commands will not work. You have some solution. thank you.
Micro Studio Master/Slave via Arduino
Posted:
Tue Sep 26, 2017 10:24 am
by Marc Briede
I am thinking about a master/slave configuration for a micro studio 4k camera. I'd like to read camera data (gain, iris, white balance, shutter speed) from one micro studio via the arduino shield and push the values to other micro studios.
But as far as I read there is no possibility to read out camera data. Is there a chance to work around?
Re: Arduino Shield Thread
Posted:
Tue Sep 26, 2017 11:10 am
by Marco Monaldi
Someone knows if I can use the 3G-SDI Arduino Shield with Arduino Due ?
Re: Arduino Shield Thread
Posted:
Tue Sep 26, 2017 4:15 pm
by Xtreemtec
No,
The shield is 5V and the due is 3,3v. So without the propper level schifting you Will blow up your Due processor.
Re: Arduino Shield Thread
Posted:
Thu Sep 28, 2017 7:34 pm
by Kasper Skaarhoj
It's actually fairly tricky, more than just level shifting. We have found a way, we have also found out why it doesn't work with such as Arduino Due and another fast 3V3 processor we tried. It's actually a timing issue in BMDs implementation, so ideally they fix it in a new firmware. We should write a mail to Hersh about it I think...
Re: Arduino Shield Thread
Posted:
Thu Oct 12, 2017 11:22 am
by Marco Monaldi
hello Jakob, I'm taking inspiration from your project and I am controlling with LCD menus and rotary encoders to vary the parameters of Gain, Gamma, Lift (R G B Y separately) Iris, Zoom, Focus, Hue - Sat, MasterGain and Lift Master.
Re: Arduino Shield Thread
Posted:
Thu Oct 12, 2017 7:00 pm
by Xtreemtec
English please!!!
Re: Arduino Shield Thread
Posted:
Fri Oct 13, 2017 11:23 am
by Marco Monaldi
I'm sorry Xtreemtec. I speak Italian and I do not speak English well. in the last post I forgot to post in English.
Re: Arduino Shield Thread
Posted:
Fri Oct 13, 2017 4:21 pm
by Xtreemtec
Marco Monaldi wrote:I'm sorry Xtreemtec. I speak Italian and I do not speak English well. in the last post I forgot to post in English.
No problem.. But this is an English only forum.
Re: Arduino Shield Thread
Posted:
Sun Oct 15, 2017 6:42 pm
by Marco Monaldi
work in progress
Re: Arduino Shield Thread
Posted:
Sat Mar 24, 2018 1:45 pm
by Marco Monaldi
Hello everyone. I can not find the shutter command. I saw in the manual
Blackmagic_3G-SDI_Arduino_Shield_Manual.pdf without finding it.
Can anyone help me ?
Re: Arduino Shield Thread
Posted:
Sat Mar 24, 2018 2:41 pm
by Xtreemtec
Camera manual page 227
http://documents.blackmagicdesign.com/C ... Manual.pdf1.11 Shutter Angle
1.12 Shutter Speed
And keep in mind that you set 1.10 in 0 mode (Manual exposure instead of auto)
Re: Arduino Shield Thread
Posted:
Sat Mar 24, 2018 4:15 pm
by Marco Monaldi
thank you very much for your reply.
Re: Arduino Shield Thread
Posted:
Thu Apr 12, 2018 3:51 pm
by JoshGarcia
Hi everybody. I was completely new to Arduino and C. I took some online courses and 3 months later I was able to complete version 1 of my controller. I used push buttons to change the parameters I set for different camera control. I want to change everything over to be controller via rotary encoder with push button. I Googled many different codes for rotary encoder with menus, but I can't seem to get them to work. If anybody could help me a small example of how you could send commands to the camera via rotary encoder that would be amazing. Anything to help me is appreciated. Until then I will continue to try and figure it out.
Re: Arduino Shield Thread
Posted:
Thu Apr 12, 2018 5:23 pm
by Xtreemtec
Rotary encoders in Arduino are much harder to work with.. They depend on interrupts and you need some coding skills to understand how that works and how not to break your code by using them.. Not for the novice users..
Re: Arduino Shield Thread
Posted:
Fri Apr 27, 2018 1:07 pm
by Marco Monaldi
Hello everyone
in an old post I asked for the shutter command and thanks to Xtreemtec who provided the documentation I tried to make the control.
but my camera does not respond to commands.
I have a Blackmagic Micro Studio Camera 4K
in the documentation provided on the site (Blackmagic_3G-SDI_Arduino_Shield_Manual.pdf) there is no Shutter Speed and Exposure Mode command.
in the doubling (Blackmagic URSA Broadcast Manual.pdf) there are the commands.
so I tried this way
int cameraNumber = 1;
int8_t SetAutoExposureMode;
SetAutoExposureMode = 0;
cameraControl.writeCommandInt8 (
cameraNumber, // Destination: Camera number
1, // Category: Video
10, // Param: Auto Exposure Mode
0, // Operation: Set Absolute,
SetAutoExposureMode // exposure mode
);
const int ShutterSpeedValue [15] = {50, 60, 75, 90, 100, 120, 150, 180, 250, 360, 500, 725, 1000, 1450, 2000};
int32_t ShutterSpeedSendtoDevice;
ShutterSpeedSendtoDevice = ShutterSpeedValue [0]; // for 1/50
cameraControl.writeCommandInt32 (
cameraNumber, // Destination: Camera number
1, // Category: Video
12, // Param: Shutter speed
0, // Operation: Set Absolute,
ShutterSpeedSendtoDevice // Shutter speed
);
I tried but it does not work
Re: Arduino Shield Thread
Posted:
Sat Apr 28, 2018 9:25 pm
by Xtreemtec
The 3G sdi shield docu is outdated Protocol v1.1 While we are at a higher version now..
Loose the 0 for absolute.. The index shows a "-" So i think the 0 for Absolute is misplaced.. 1,12,Shutterspeed i think that will be it looking at the manual..
Also be sure you have the latest FW running on the camera
Re: Arduino Shield Thread
Posted:
Thu May 03, 2018 4:32 pm
by Marco Monaldi
thank you Xtreemtec.
I found an update for the Blackmagic Micro Studio Camera 4K on the site.
Blackmagic Camera 4.7 Update
Can I install the latest version 5.0.1? I do not know if the latest version also includes the functions of 4.7.
I will try to install the 4.7 to see if I can remote the Shutter.
Thanks for your help.
Re: Arduino Shield Thread
Posted:
Mon May 07, 2018 3:05 pm
by Xtreemtec
It will always install the latest available version on the camera. Even if it is 2 versions back of the current fw. (happens a lot to older Ursa models)
BMD almost always only add and improve functions.. Never pull out functions.. (or at least very rare to do so)
Re: Arduino Shield Thread
Posted:
Fri Jul 06, 2018 2:03 pm
by aislaih
Hey there,
I'm trying to add the ability to control shutter speed with my Arduino shield I'm using a similar code to one of the projects that can be found in an earlier post (the one with an LCD display). My code displays all the shutter speed values on the LCD display. but for some reason it is not sending the data to the controller. I am pretty confident that I did everything the way I'm supposed to. I even updated My camera to the most recent version but I still have no idea why it's not working.
Any help or tips would be greatly appreciated!
PARTIAL CODE: (let me know if you require full code)
- Code: Select all
// shutter speed
float shutterSpeedValueController = 1;
const float shutterSpeedSensHigh = 0.1;
const float shutterSpeedSensNormal = 0.05;
const float shutterSpeedFloor = 0; // 50
const float shutterSpeedTop = 14; // 2000
const int32_t shutterSpeedValues[15] = {50, 60, 75, 90, 100, 120, 150, 180, 250, 360, 500, 725, 1000, 1450, 2000};
int32_t shutterSpeedValueSendToDevice;
..........
if (getButtonStableEdge(button6Pin) == true && getButtonStableLevel(button6Pin) == LOW) {
ModeSelect = 8; // Shutter Speed
ccMode = false;
Serial.println("Mode8 detected"); // debug only
DoParameterUpdateShutterSpeed();
CheckDisplayClear();
}
.............
case (8): // Shutter Speed
Serial.println("ReadJoy > case 8");
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
shutterSpeedValueController = shutterSpeedValueController + shutterSpeedSensHigh;
}
else if (currentJoystickY > 0) {
shutterSpeedValueController = shutterSpeedValueController + shutterSpeedSensNormal;
}
else if (currentJoystickY < -80) {
shutterSpeedValueController = shutterSpeedValueController - shutterSpeedSensHigh;
}
else if (currentJoystickY < 0) {
shutterSpeedValueController = shutterSpeedValueController - shutterSpeedSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
shutterSpeedValueController = constrain(shutterSpeedValueController, shutterSpeedFloor, shutterSpeedTop);
break;
................
case (8): //Shutter Speed
Serial.println("CLICKED>>>>>>>>>");
DoParameterUpdateShutterSpeed();
break;
..............
void DoParameterUpdateShutterSpeed() {
Serial.println("ParameterUpdate > case 8");
shutterSpeedValueSendToDevice = shutterSpeedValues[round(shutterSpeedValueController)];
sdiCameraControl.writeCommandInt32(
cameraNumber, // Destination: Camera number
1, // Category: Video
12, // Param: Shutter speed
0, // Operation: Set Absolute,
shutterSpeedValueSendToDevice // shutterSpeedValue
);
UpdateDisplay(5, "ShutterSpeed", shutterSpeedValueSendToDevice);
}
THANKS!!
Re: Arduino Shield Thread
Posted:
Wed Jul 11, 2018 10:55 am
by Xtreemtec
UPDATE Arduino Shield Software Version 1.1 is released.
See link for more information>>
https://www.blackmagicdesign.com/developer/product/arduino@ Ahmed, Without the full code we can not check the issue. Reading trough the posted bits don't put a red flag up directly..
Re: Arduino Shield Thread
Posted:
Mon Jul 16, 2018 3:54 pm
by aislaih
Thanks for the timely reply @Xtreemtec
I just updated my shield to the latest version. Thanks for the link
I still cannot seem to get the shutter speed values to send to the Camera. Everything else in the code works perfectly.
Here is the full code:
- Code: Select all
#include <BMDSDIControl.h>
#include <LiquidCrystal_I2C.h>
#include <math.h>
#include <Wire.h>
/**
Blackmagic Design 3G-SDI Shield Sketch
Joystick control - JAHA 2017-05-05
This sketch controls a BMD cam via a BMD 3G-SDI shield,
which supports a SKAARHOJ joystick&buttons PCB and controls a SDI-connected BMD-camera.
The three buttons are mapped as follows:
- Button 1, which selects WB-mode
- Button 2, which selects and cycles through black/gamma/gain adj modes
- Button 3, which selects focus-mode on the camera
- Button 4, which switches between 3 frame rates
- Button 5, which switches between 8 camera numbers
The joystick is mapped as follows:
- X axis adjusts the mode X parameter
- Y axis adjusts the mode Y parameter
- Pressing the Joystick resets all correction parameters.
*/
// LCD pin mappings
//const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
//LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE );
//LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
// Hardware pin mappings
const int joystickButtonPin = A0;
const int joystickXPin = A1;
const int joystickYPin = A2;
const int button1Pin = 2;
const int button2Pin = 3;
const int button3Pin = 4;
const int button4Pin = 5;
const int button5Pin = 6;
const int button6Pin = 7;
// Blackmagic Design SDI control shield globals
const int shieldAddress = 0x6E;
BMD_SDITallyControl_I2C sdiTallyControl(shieldAddress);
BMD_SDICameraControl_I2C sdiCameraControl(shieldAddress);
// Button debouncing globals
unsigned long lastStableButtonTime[32];
int rawButtonLevels[32];
int stableButtonLevels[32];
// Joystick sample rate limiter globals
unsigned long lastJoystickUpdateTime;
// Global joystick detection parameters
int currentJoystickX = 0;
int currentJoystickY = 0;
// Camera parameter adjustment-state, globals
// Manual WhiteBalance
float manualWbValueController = 6; //4000
const float manualWbValueSensHigh = 0.2; // joy max deflection adjust
const float manualWbValueSensNormal = 0.05; // joy normal deflection adjust
const float manualWbFloor = 0; // 2500
const float manualWbTop = 17; // 8000
const int16_t manualWbValues[18] = { 2500, 2800, 3000, 3200, 3400, 3600, 4000, 4500, 4800, 5000, 5200, 5400, 5600, 6000, 6500, 7000, 7500, 8000 };
int16_t manualWbValueSendToDevice;
// Lift/Blacklevel
float liftValue = 0;
const float liftValueSensHigh = 0.005;
const float liftValueSensNormal = 0.001;
float liftValueArray[4] = { 0.0, 0.0, 0.0, 0.0 };
const float liftFloor = -2;
const float liftTop = 2;
// Gamma
float gammaValue = 0;
const float gammaValueSensHigh = 0.005;
const float gammaValueSensNormal = 0.001;
float gammaValueArray[4] = { 0.0, 0.0, 0.0, 0.0 };
const float gammaFloor = -4;
const float gammaTop = 4;
// Gain
float gainValue = 1;
const float gainValueSensHigh = 0.03;
const float gainValueSensNormal = 0.01;
float gainValueArray[4] = { 0.0, 0.0, 0.0, 0.0 };
const float gainFloor = 0;
const float gainTop = 16;
// MasterGain
float masterGainValueController = 1.0;
const float masterGainSensHigh = 0.1;
const float masterGainSensNormal = 0.05;
const int masterGainValues[5] = { 1, 2, 4, 8, 16 }; // gain x1, x2, x4, x8, x16
const int masterGainFloor = 0; //x1
const int masterGainTop = 4; //x16
int masterGainSendToDevice;
// dimention
float dimentionValueController = 1.0;
const float mdimentionSensHigh = 0.1;
const float dimentionSensNormal = 0.05;
const int dimentionValues[2] = { 1080, 4 }; // gain x1, x2, x4, x8, x16
const int dimentionFloor = 0; //x1
const int dimentionTop = 4; //x16
int dimentionSendToDevice;
//frame rate
int rate = 0;
int d = 3;
int fr = 30;
// Camera#
int cameraNumber;
int camNum;
// Focus
float focusValue = 0.5;
const float focusValueSensHigh = 0.01;
const float focusValueSensNormal = 0.002;
const float focusFloor = 0.0;
const float focusTop = 1.0;
// shutter speed
float shutterSpeedValueController = 1;
const float shutterSpeedSensHigh = 0.1;
const float shutterSpeedSensNormal = 0.05;
const float shutterSpeedFloor = 0; // 50
const float shutterSpeedTop = 14; // 2000
const int32_t shutterSpeedValues[15] = {50, 60, 75, 90, 100, 120, 150, 180, 250, 360, 500, 725, 1000, 1450, 2000};
int32_t shutterSpeedValueSendToDevice;
// ModeSelect - global parameter, determines operation-mode
// 1 - Whitebalance
// 2 - Lift (CC) & mastergain
// 3 - Gamma (CC) & mastergain
// 4 - Gain (CC) & mastergain
// 5 - Focus
int ModeSelect = 0; // current mode
int previousMode = 0; // previous mode
// ColorCorrection-mode
int currentCCMode = 1; // current ColorCorrectionMode: Lift, Gamma, Gain
bool ccMode; // flag true if CCmode is active
void setup() {
Serial.begin(9600);
Serial.println("startup");
lcd.begin(20, 4);
lcd.setCursor(0, 0);
lcd.print("CCU controller");
// Configure digital inputs
pinMode(joystickButtonPin, INPUT_PULLUP);
pinMode(button1Pin, INPUT_PULLUP);
pinMode(button2Pin, INPUT_PULLUP);
pinMode(button3Pin, INPUT_PULLUP);
pinMode(button4Pin, INPUT_PULLUP);
pinMode(button5Pin, INPUT_PULLUP);
pinMode(button6Pin, INPUT_PULLUP);
//
// // Set up the BMD SDI control library
sdiTallyControl.begin();
sdiCameraControl.begin();
//
// // The shield supports up to 400KHz, use faster
// // I2C speed to reduce latency
Wire.setClock(400000);
//
// // Enable both tally and control overrides
sdiTallyControl.setOverride(true);
sdiCameraControl.setOverride(true);
//
// // reset camera to defaults
DoParameterUpdateResetAll();
//
// // display welcome message
lcd.setCursor(0, 0);
lcd.print("CCU controller");
}
void loop() {
DetectOperationMode();
ReadJoystickInput();
DoParameterUpdate();
}
void DetectOperationMode() {
// Detect button1 - WhiteBalance
if (getButtonStableEdge(button1Pin) == true && getButtonStableLevel(button1Pin) == LOW) {
// When the button is low (pressed) the WB-mode is activated
ModeSelect = 1;
ccMode = false;
Serial.println("Mode1 detected"); //debug only
CheckDisplayClear();
}
// Detect button2, cycle through black/gamma/gain adjustment modes
if (getButtonStableEdge(button2Pin) == true && getButtonStableLevel(button2Pin) == LOW) {
// detect if we should step to next cc-mode
if (ccMode) {
currentCCMode = currentCCMode + 1;
if (currentCCMode > 3)
currentCCMode = 1;
}
ccMode = true;
if (currentCCMode == 1) {
ModeSelect = 2; // Lift
}
else if (currentCCMode == 2) {
ModeSelect = 3; // Gamma
}
else if (currentCCMode == 3) {
ModeSelect = 4; // Gain
}
Serial.println("Mode2, 3 or 4 detected"); // debug only
Serial.println(ModeSelect);
CheckDisplayClear();
}
// Detect button3, select focus mode
if (getButtonStableEdge(button3Pin) == true && getButtonStableLevel(button3Pin) == LOW) {
ModeSelect = 5; // Focus
ccMode = false;
Serial.println("Mode5 detected"); // debug only
CheckDisplayClear();
}
if (getButtonStableEdge(button4Pin) == true && getButtonStableLevel(button4Pin) == LOW) {
ModeSelect = 6; // FrameRate
ccMode = false;
Serial.println("Mode6 detected"); // debug only
DoParameterUpdateFrameRate();
CheckDisplayClear();
}
if (getButtonStableEdge(button5Pin) == true && getButtonStableLevel(button5Pin) == LOW) {
ModeSelect = 7; // FrameRate
ccMode = false;
Serial.println("Mode7 detected"); // debug only
DoParameterUpdateCameraNumber();
CheckDisplayClear();
}
if (getButtonStableEdge(button6Pin) == true && getButtonStableLevel(button6Pin) == LOW) {
ModeSelect = 8; // FrameRate
ccMode = false;
Serial.println("Mode8 detected"); // debug only
DoParameterUpdateShutterSpeed();
CheckDisplayClear();
}
// If the reset button is pressed, clear all color correction values
if (getButtonStableEdge(joystickButtonPin) == true && getButtonStableLevel(joystickButtonPin) == LOW) {
DoParameterUpdateResetAll();
Serial.println("Reset detected");
}
}
void ReadJoystickInput() {
if (getJoystickUpdateReady() == true) {
switch (ModeSelect) {
case (0): // ignore
break;
case (1): // Whitebalance
Serial.println("ReadJoy > case 1");
// joystick Y = whitebalance K
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
manualWbValueController = manualWbValueController + manualWbValueSensHigh; // using wb sensitivity-constant
}
else if (currentJoystickY > 0) {
manualWbValueController = manualWbValueController + manualWbValueSensNormal;
}
else if (currentJoystickY < -80) {
manualWbValueController = manualWbValueController - manualWbValueSensHigh;
}
else if (currentJoystickY < 0) {
manualWbValueController = manualWbValueController - manualWbValueSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
manualWbValueController = constrain(manualWbValueController, manualWbFloor, manualWbTop);
break;
case (2): // CC Lift
Serial.println("ReadJoy > case 2");
// joystick Y = lift
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
liftValue = liftValue + liftValueSensHigh; // using lift sensitivity-constant
}
else if (currentJoystickY > 0) {
liftValue = liftValue + liftValueSensNormal;
}
else if (currentJoystickY < -80) {
liftValue = liftValue - liftValueSensHigh;
}
else if (currentJoystickY < 0) {
liftValue = liftValue - liftValueSensNormal;
}
ReadJoystickInputMasterGain();
// Don't allow the values to exceed the minimum/maximum
liftValue = constrain(liftValue, liftFloor, liftTop);
break;
case (3): // CC Gamma
Serial.println("ReadJoy > case 3");
// joystick Y = gamma
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
gammaValue = gammaValue + gammaValueSensHigh; // using gamma sensitivity-constant
}
else if (currentJoystickY > 0) {
gammaValue = gammaValue + gammaValueSensNormal;
}
else if (currentJoystickY < -80) {
gammaValue = gammaValue - gammaValueSensHigh;
}
else if (currentJoystickY < 0) {
gammaValue = gammaValue - gammaValueSensNormal;
}
ReadJoystickInputMasterGain();
// Don't allow the values to exceed the minimum/maximum
gammaValue = constrain(gammaValue, gammaFloor, gammaTop);
break;
case (4): // CC Gain
Serial.println("ReadJoy > case 4");
// joystick Y = gain
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
gainValue = gainValue + gainValueSensHigh; // use gain sensitivity-constant
}
else if (currentJoystickY > 0) {
gainValue = gainValue + gainValueSensNormal;
}
else if (currentJoystickY < -80) {
gainValue = gainValue - gainValueSensHigh;
}
else if (currentJoystickY < 0) {
gainValue = gainValue - gainValueSensNormal;
}
ReadJoystickInputMasterGain();
// Don't allow the values to exceed the minimum/maximum
gainValue = constrain(gainValue, gainFloor, gainTop);
break;
case (5): // Focus
Serial.println("ReadJoy > case 5");
// joystick Y
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
focusValue = focusValue + focusValueSensHigh; // use focus sensitivity-constant
}
else if (currentJoystickY > 0) {
focusValue = focusValue + focusValueSensNormal;
}
else if (currentJoystickY < -80) {
focusValue = focusValue - focusValueSensHigh;
}
else if (currentJoystickY < 0) {
focusValue = focusValue - focusValueSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
focusValue = constrain(focusValue, focusFloor, focusTop);
break;
case (6): // ignore
break;
case (7): // ignore
break;
case (8): // Shutter Speed
Serial.println("ReadJoy > case 8");
currentJoystickY = getJoystickAxisPercent(joystickYPin);
if (currentJoystickY > 80) {
shutterSpeedValueController = shutterSpeedValueController + shutterSpeedSensHigh;
}
else if (currentJoystickY > 0) {
shutterSpeedValueController = shutterSpeedValueController + shutterSpeedSensNormal;
}
else if (currentJoystickY < -80) {
shutterSpeedValueController = shutterSpeedValueController - shutterSpeedSensHigh;
}
else if (currentJoystickY < 0) {
shutterSpeedValueController = shutterSpeedValueController - shutterSpeedSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
shutterSpeedValueController = constrain(shutterSpeedValueController, shutterSpeedFloor, shutterSpeedTop);
break;
}
}
}
void ReadJoystickInputMasterGain() {
// joystick X = masterGain
currentJoystickX = getJoystickAxisPercent(joystickXPin);
if (currentJoystickX > 80) {
masterGainValueController = masterGainValueController + masterGainSensHigh;
}
else if (currentJoystickX > 0) {
masterGainValueController = masterGainValueController + masterGainSensNormal;
}
else if (currentJoystickX < -80) {
masterGainValueController = masterGainValueController - masterGainSensHigh;
}
else if (currentJoystickX < 0) {
masterGainValueController = masterGainValueController - masterGainSensNormal;
}
// Don't allow the values to exceed the minimum/maximum
masterGainValueController = constrain(masterGainValueController, masterGainFloor, masterGainTop);
}
void DoParameterUpdate() {
// Send new parameter adjustment to the camera
switch (ModeSelect) {
case (0): // ignore
break;
case (1): // Whitebalance
// joystick Y (manualWbValue)
DoParameterUpdateWhiteBalance();
break;
case (2): // CC Lift
// joystick Y = lift (liftValue)
// joystick X = masterGain
DoParameterUpdateLift();
DoParameterUpdateMasterGain();
break;
case (3): // CC Gamma
// joystick Y = gamma
// joystick X = masterGain
DoParameterUpdateGamma();
DoParameterUpdateMasterGain();
break;
case (4): // CC Gain
// joystick Y = gain
// joystick X = masterGain
DoParameterUpdateGain();
DoParameterUpdateMasterGain();
break;
case (5): // Focus
// joystick X
DoParameterUpdateFocus();
break;
case (6): //Do nothing
break;
case (7): //Do nothing
break;
case (8): //Shutter Speed
Serial.println("CLICKED>>>>>>>>>");
DoParameterUpdateShutterSpeed();
break;
}
}
void DoParameterUpdateWhiteBalance() {
Serial.println("ParameterUpdate > case 1");
manualWbValueSendToDevice = manualWbValues[round(manualWbValueController)];
sdiCameraControl.writeCommandInt16(
cameraNumber, // Destination: Camera number
1, // Category: Video
2, // Param: White balance
0, // Operation: Set Absolute,
manualWbValueSendToDevice // manualWbValue
);
UpdateDisplay(5, "WhiteBalance", manualWbValueSendToDevice);
}
void DoParameterUpdateLift() {
Serial.println("ParameterUpdate > Lift");
liftValueArray[0] = liftValue;
liftValueArray[1] = liftValue;
liftValueArray[2] = liftValue;
liftValueArray[3] = liftValue;
// set lift values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
8, // Category: Color Correction
0, // Param: Offset Adjust
0, // Operation: Set Absolute,
liftValueArray // lift values
);
UpdateDisplay(5, "Black", liftValue);
}
void DoParameterUpdateGamma() {
Serial.println("ParameterUpdate > Gamma");
gammaValueArray[0] = gammaValue;
gammaValueArray[1] = gammaValue;
gammaValueArray[2] = gammaValue;
gammaValueArray[3] = gammaValue;
// set gamma values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
8, // Category: Color Correction
1, // Param: Gamma adjust
0, // Operation: Set Absolute,
gammaValueArray // gamma value
);
UpdateDisplay(5, "Gamma", gammaValue);
}
void DoParameterUpdateGain() {
Serial.println("ParameterUpdate > Gain");
gainValueArray[0] = gainValue;
gainValueArray[1] = gainValue;
gainValueArray[2] = gainValue;
gainValueArray[3] = gainValue;
// set gain values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
8, // Category: Color Correction
2, // Param: Gain adjust
0, // Operation: Set Absolute,
gainValueArray // gain value
);
UpdateDisplay(5, "Gain", gainValue);
}
void DoParameterUpdateFocus() {
Serial.println("ParameterUpdate > focus");
// set focus values
sdiCameraControl.writeCommandFixed16(
cameraNumber, // Destination: Camera number
0, // Category: Lens
0, // Param: Focus
0, // Operation: Set Absolute,
focusValue // focus value
);
UpdateDisplay(1, "Focus", focusValue);
UpdateDisplay(3, "", focusValue);
}
void DoParameterUpdateResetAll() {
// Reset color correction
for (int i = 0; i < 10; i++) {
Serial.println("Reset camera parameters"); // looping to increase readability in serial-monitor
}
manualWbValueController = 6; //4000K
shutterSpeedValueController = 1;
liftValue = 0.02;
gammaValue = 0.15;
gainValue = 1.4;
focusValue = 0.52;
masterGainValueController = 3;
d = 3;
fr = 30;
//
DoParameterUpdateWhiteBalance();
DoParameterUpdateLift();
DoParameterUpdateGamma();
DoParameterUpdateGain();
DoParameterUpdateMasterGain();
DoParameterUpdateFocus();
DoParameterUpdateShutterSpeed();
DoParameterUpdateFrameRate();
lcd.clear();
delay(200);
/*
// Reset all color correction parameters in the camera
sdiCameraControl.writeCommandVoid(
cameraNumber, // Destination: Camera
8, // Category: Color Correction
7 // Param: Reset Defaults
);
// Request auto-iris adjustment in the camera
sdiCameraControl.writeCommandVoid(
cameraNumber, // Destination: Camera
0, // Category: Lens
5 // Param: Auto Iris
);
*/
}
void DoParameterUpdateMasterGain() {
masterGainSendToDevice = masterGainValues[round(masterGainValueController)];
sdiCameraControl.writeCommandInt8(
cameraNumber, // Destination: Camera number
1, // Category: Video
1, // Param: Sensor gain
0, // Operation: Set Absolute,
masterGainSendToDevice // masterGainValue
);
UpdateDisplay(6, "mGain", masterGainSendToDevice);
}
void checkRate(int r) {
if (r > 2) {
rate = 0;
}
}
void DoParameterUpdateFrameRate() {
Serial.print("rate= ");
Serial.println(rate);
switch (rate) {
case (0): //
{
d = 3;
fr = 30;
UpdateDisplay(1, "fRate", 0.0);
UpdateDisplay(3, "1080p 30fps", 0.0);
++rate;
checkRate(rate);
break;
}
case (1): //
d = 3;
fr = 60;
UpdateDisplay(1, "fRate", 90000);
UpdateDisplay(3, "1080p 60fps", 900);
++rate;
checkRate(rate);
break;
case (2): //
d = 6;
fr = 30;
UpdateDisplay(1, "fRate", 90000);
UpdateDisplay(3, "4K 30fps ", 900);
++rate;
checkRate(rate);
break;
// case (3): //
// d = 6;
// fr = 60;
// UpdateDisplay(1, "fRate", 90000);
// UpdateDisplay(3, "4K 60fps ", 900);
// ++rate;
// checkRate(rate);
// break;
}
int8_t settings[] =
{
fr, // Frame rate 50
0, // M-Rate Regular
d, // Dimensions UHD
0, // Progressive
0 // Color Space YUV
};
sdiCameraControl.writeCommandInt8(
cameraNumber, // Camera 1
1, // Catergory Video
0, // Param Video Mode
0, // Operation: Assign Value
settings
);
}
void checkCamNum(int c) {
if (c > 7) {
camNum = 0;
}
}
void DoParameterUpdateCameraNumber() {
Serial.print("Cam# ");
Serial.println(camNum);
switch (camNum) {
case (0): //
{
cameraNumber = 1;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
}
case (1): //
cameraNumber = 2;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
case (2): //
cameraNumber = 3;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
case (3): //
cameraNumber = 4;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
case (4): //
cameraNumber = 5;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
case (5): //
cameraNumber = 6;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
case (6): //
cameraNumber = 7;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
case (7): //
cameraNumber = 8;
UpdateDisplay(7, "Cam# ", cameraNumber);
++camNum;
checkCamNum(camNum);
break;
}
}
void DoParameterUpdateShutterSpeed() {
Serial.println("ParameterUpdate > case 8");
shutterSpeedValueSendToDevice = shutterSpeedValues[round(shutterSpeedValueController)];
sdiCameraControl.writeCommandInt32(
cameraNumber, // Destination: Camera number
1, // Category: Video
12, // Param: Shutter speed
0, // Operation: Set Absolute,
shutterSpeedValueSendToDevice // shutterSpeedValue
);
UpdateDisplay(5, "ShutterSpeed", shutterSpeedValueSendToDevice);
////_____________________________/////////
// cameraControl.writeCommandInt32 (
// cameraNumber, // Destination: Camera number
// 1, // Category: Video
// 12, // Param: Shutter speed
// 0, // Operation: Set Absolute,
// ShutterSpeedSendtoDevice // Shutter speed
//
// );
}
bool getJoystickUpdateReady() {
// Determines if we are ready for another joystick update (this is
// a rate limiter to ensure that the user can slowly adjust the
// parameters easily with the joystick)
unsigned long currentTime = millis();
if ((lastJoystickUpdateTime - currentTime) > 100) {
lastJoystickUpdateTime = currentTime;
return true;
}
return false;
}
int getJoystickAxisPercent(int analogPin) {
// Reads the joystick axis on the given analog pin as a [-100 - 100] scaled value
int rawAnalogValue = analogRead(analogPin);
int scaledAnalogValue = map(rawAnalogValue, 0, 1023, -100, 100);
// Consider values close to zero as zero, so that when the joystick is
// centered it reports zero even if it is slightly mis-aligned
if (abs(scaledAnalogValue) < 10) {
scaledAnalogValue = 0;
}
return scaledAnalogValue;
}
bool getButtonStableEdge(int digitalPin) {
// Detects debounced edges (i.e. presses and releases) of a button
bool previousLevel = stableButtonLevels[digitalPin];
bool newLevel = getButtonStableLevel(digitalPin);
return previousLevel != newLevel;
}
int getButtonStableLevel(int digitalPin) {
// Reads a digital pin and filters it, returning the stable button position
int pinLevel = digitalRead(digitalPin);
unsigned long currentTime = millis();
// If the button is rapidly changing (bouncing) during a press, keep
// resetting the last stable time count
if (pinLevel != rawButtonLevels[digitalPin]) {
lastStableButtonTime[digitalPin] = currentTime;
rawButtonLevels[digitalPin] = pinLevel;
}
// Once the button has been stable for
if ((currentTime - lastStableButtonTime[digitalPin]) > 20) {
stableButtonLevels[digitalPin] = pinLevel;
}
return stableButtonLevels[digitalPin];
}
void UpdateDisplay(int _position, char _text[], float _value) {
// split lcd-display into 6 areas:
// upper-left = 1
// upper-right = 2
// lower-left = 3
// lower-right = 4
// left upper+lower = 5
// right upper+lower = 6
if (_position <= 0 || _position > 7) {
Serial.print("lcd-position out of bounds");
return;
}
// /*
Serial.print(_text);
Serial.print(" ");
Serial.println(_value);
// */
switch (_position) {
case (1): // row = 0, column = 0, upper left
lcd.setCursor(0, 0);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (2): // row = 7, column = 0, upper right
lcd.setCursor(7, 0);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (3): // row = 0, column = 1, lower left
lcd.setCursor(0, 1);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (4): // row = 7, column = 1, lower right
lcd.setCursor(7, 1);
if (_text == "") {
lcd.print(_value);
}
else {
lcd.print(_text);
}
break;
case (5): // text + value, left part of lcd
lcd.setCursor(0, 0);
lcd.print(_text);
lcd.setCursor(0, 1);
lcd.print(_value);
break;
case (6): // text + value, right part of lcd
lcd.setCursor(7, 0);
lcd.print(_text);
lcd.setCursor(7, 1);
lcd.print(_value);
break;
case (7): // text + value, right part of lcd
lcd.setCursor(0, 2);
lcd.print(_text);
lcd.setCursor(0, 3);
lcd.print((int)_value);
break;
}
}
void CheckDisplayClear() {
if (previousMode != ModeSelect) {
lcd.clear();
delay(200);
Serial.print("CLEAR CLEAR CLEAR CLEAR CLEAR CLEAR CLEAR CLEAR");
}
previousMode = ModeSelect;
}
[img]
- 20180716_115021.jpg (908.05 KiB) Viewed 18267 times
[/img]
Any help would be greatly appreciated.
Thanks.
Re: Arduino Shield Thread
Posted:
Thu Jul 19, 2018 9:52 pm
by JoshGarcia
Hi all,
I'm trying to control the Recorded Channel 1 and Recorded Channel 2 levels in the audio menu on a URSA Broadcast. From what I can tell it looks like I should be writing the code to change the input levels under the audio parameter (sdiCameraControl.writeCommandFixed16(1, 2, 5, 0, val)). I wrote that code, and it seems to work fine on a Micro Studio 4k, but nothing changes on the URSA. There is no other parameter under the audio section that looks like it would work. I'm wondering if this is something that can be controlled on the URSA. Hopefully somebody can shed some light on this. Thanks in advance.
Re: Arduino Shield Thread
Posted:
Sun Jul 22, 2018 1:05 am
by Denny Smith
I do not think the audio levels can be controlled remotely on the Ursa Broadcast. The Micro Studio has SBus control of the audio when using the camera mic Ir an external mic, but not lone inputs.
The Broadcast audio levels can be controlled from the camera on the Mic Oreamps, but not the line level, which goes to Unity when Line inout is selected.
Cheers
Re: Arduino Shield Thread
Posted:
Wed Feb 20, 2019 12:48 am
by JepperTV
Hello,
I am trying to use the 3G SDI shield to manually Tally all four quadrants on a Multiview 4.
I figured out how to modify the "All Blink" test sketch so that all four tallies blink at the same time.
Now I need to figure out how to trigger that same quad tally with the flip of a dry switch.
Any help with the code and the wiring would be much appreciated.
Thank you!
Chris
Re: Arduino Shield Thread
Posted:
Wed Feb 20, 2019 4:32 pm
by Xtreemtec
Hi Chris,
I posted a code for this in this exact topic.
Here is the link. Have fun>
viewtopic.php?f=4&t=48175#p325706
Re: Arduino Shield Thread
Posted:
Wed Feb 20, 2019 6:31 pm
by JepperTV
Thank you Xtreemtec!
I had read that post but wasn't sure it was what I needed.
Does this code refer to each pin number that gets pulled to ground?
And if so, are they digital pins or analog?
- Code: Select all
int PGM1 = 2;
int PRV1 = 3;
int PGM2 = 4;
int PRV2 = 5;
int PGM3 = 6;
int PRV3 = 7;
int PGM4 = 8;
int PRV4 = 9;
Thank you,
Chris
Re: Arduino Shield Thread
Posted:
Wed Feb 20, 2019 7:49 pm
by JepperTV
Figured it out...digital pins.
Works like a charm!
Thank You!!
Re: Arduino Shield Thread
Posted:
Wed Feb 20, 2019 8:20 pm
by Xtreemtec
The numbers are the Arduino pin numbers. As labeled on the Arduino.
These are digital pins, And pull up in the processor is turned on. So when you make a connection from pin 2 (PGM1) to GND The red square will appear in Window 1.
if you make a connection between pin 7 and ground Green box will appear on window 3.
I see i have 1 small add on to this code.
- Code: Select all
sdiTallyControl.setCameraTally( 4, ( !digitalRead(PGM4)) , ( !digitalRead(PRV4)) );
Add this line below the others. Otherwise channel 4 wont go