I have been using this lens for several experiment and the GUI developed by Optotune works just fine.
However, sometimes I needed to have better control and play with the lens. For a couple of experiments we used this lens as a key component working in an automated environment on where a software was dynamically changing the lens parameter (focal length, therefore electronic lens current) according to different scenarios. This first software was written in C++ code.
Next I have decided to move to the development in MATLAB. To do that I have written a code that is able to simply control the electronic lens (current setting).
Following the instructions of the Optotune datasheet I have used the crc16ibm.
I would like to share this, since so many times I have been on the other side and is nice to give back.
Hopefully someone might find it useful.
Note that the code is not fully optimized and is very simple though but it does the job and was the result of a couple of hours.
It has 3 functions and 1 main.
function reverse_16:
function [data] = reverse_16(message_byte)
dr = bin2dec(fliplr(dec2bin(message_byte, 16)))
data = dr;
end
function reverse_8:
function [data] = reverse_8(message_byte)
dr = bin2dec(fliplr(dec2bin(message_byte, 8)))
data = dr;
end
function crc16ibm:
function [data] = crc16ibm(message, n)
% crc16ibm returns a 16 bit number value.
remainder = 0; remainder_bin = '0000000000000000'; %initializations
polynomial = 32773; % is the polynomail used in the CRCIBM16 - in hexadecimal is 0x8005.
%message = [hex2dec('41'), hex2dec('77'), 5, 117, 0, 0]; %
for i=1 : n
if i == 3;
end
a = reverse_8(message(i));
a_bin = dec2bin(a);
a_bin_str = num2str(a_bin);
size_a = length(a_bin_str);
remainder = a_bin_str;
while size_a <16 font="">
remainder = strcat(remainder,'0');
size_a = length(remainder);
end;
remainder_array= []; remainder_bin_array = []; %need to define these for the EXOR operation
for k = 1 : 16
remainder_array(k) = str2num(remainder(k));
remainder_bin_array(k) = str2num(remainder_bin(k));
end;
remainder_bin_array = xor(remainder_array , remainder_bin_array);
remainder_bin='';
for i = 1 :length(remainder_bin_array)
remainder_bin = strcat(remainder_bin,num2str(remainder_bin_array(i)));
end;
for j = 1 : 8
if remainder_bin(1) == '1'
remainder_bin = strcat(remainder_bin,'0'); %is a shift to the left therefore adding '0'
remainder_bin = remainder_bin(2:end); %need to remove the first value to keep it as a 16-bit number
%need to perform the exor operation
polynomial_bin = dec2bin(polynomial);
pol_array= []; remainder_array = [];
for k=1:length(polynomial_bin)
pol_array(k) = str2num(polynomial_bin(k));
remainder_array(k) = str2num(remainder_bin(k));
end;
C = xor(remainder_array, pol_array); % the result of the EXOR operation
remainder_bin = ''; %need to transfrom back to char string...
for i = 1 :length(C)
remainder_bin = strcat(remainder_bin,num2str(C(i)));
end;
else
remainder_bin = strcat(remainder_bin,'0'); %is a shift to the left therefore adding '0'
remainder_bin = remainder_bin(2:end); %need to remove the first value to keep it as a 16-bit number
end
pippo(j) = bin2dec(remainder_bin); %temp variable, debug purposes
end
end
remainder_bin;
% need to make a reverse 16..
remainder = bin2dec(remainder_bin);
data= reverse_16(remainder);
end
Main:
% ECVFL control using matlab the Optotune Lensdriver
clear all; close all; clc; %clear all
s = serial('COM6'); %depends could change
set(s,'BaudRate',115200); %specfication according to Optotune datasheet
fopen(s); %open COM port
fprintf(s,'Start'); %initial command just to check the ECVFL
out = fscanf(s) %prompt print of 'Ready' string in command window
%% processing
current_value = 0; %something between 0 and 200
current_value =(current_value * 4096) / 293; %from the ECVFL datasheet
low = 0; high = 0; %variable definition
current_value_bin = dec2bin(current_value); %convertion to binary
size_number = length(current_value_bin);
while size_number <16 font="">
current_value_bin = strcat('0',current_value_bin);
size_number = length(current_value_bin);
end;
high_bin = current_value_bin(1:8);
low_bin = current_value_bin(9:end);
high = bin2dec(high_bin);
low = bin2dec(low_bin);
data_command = [hex2dec('41'), hex2dec('77'), high, low, 0, 0];
crc_value = crc16ibm(data_command, 4); %4=data length
% crc16ibm returns a 16 bits number. As before need to split it in 2 8 bit
% number
crc_value_bin = dec2bin(crc_value); %convertion to binary
size_number = length(crc_value_bin);
while size_number <16 font="">
crc_value_bin = strcat('0',crc_value_bin);
size_number = length(crc_value_bin);
end;
crc_value_high_bin = crc_value_bin(1:8); %upper part
crc_value_low_bin = crc_value_bin(9:end); %lower part
crc_value_high = bin2dec(crc_value_high_bin);
crc_value_low = bin2dec(crc_value_low_bin);
data_command = [hex2dec('41'), hex2dec('77') high low crc_value_low crc_value_high];
%% Send data throught the serial COM port communication
fwrite(s, data_command, 'uint8');
%test
%fprintf(s,'Start');
%out = fscanf(s)
%%
fclose(s); delete(s); clear s;
delete(instrfindall); % to make sure we really close the COM port