One of my new assignments was to develop a controller to SCN6 actuators to be implemented in a simulator.
After hours of work disassembling a Tmbscom.DLL to be used in a C++ test program, i finally got it working.
Converting this code to C#, was a bit trick, but fortunately someone else did the hard work of writing the functions of DLL in C#.
This code is related to a repository (“EC Hardware”) that was located at assembla.com. The author had this project as opensource. But unfortunately, the repository was deleted. But Google Cache help-me and i could retrieved it.
using UnityEngine; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Threading; namespace Driver_SCN5 { public class SCN5: MonoBehaviour { #region &&&&&&&&&&&&&&&&& IMPORT TMBSCOM &&&&&&&&&&&&&&&&& #region ############ COMUNICACIONES ############ [DllImport("Tmbscom", EntryPoint = "_init_tmbs_config@24")] public static unsafe extern int init_tmbs_config( string port, // Port Name ( "COM1","COM2"etc. ) int baud, // Baudrate( 4,5,6,7,11H,12H,13H,14H ) int nrt, // Retry bool reset, // bool automatic, // ref int axes_info // ); [DllImport("TMBSCOM.dll", EntryPoint = "_close_tmbs@0")] public static unsafe extern int close_tmbs(); [DllImport("TMBSCOM.dll", EntryPoint = "_get_current_baud@0")] public static unsafe extern int get_current_baud(); [DllImport("TMBSCOM.dll", EntryPoint = "_init_tmbs@0")] public static unsafe extern int init_tmbs(); #endregion #region ############ ESTADO ############ [DllImport("TMBSCOM.dll", EntryPoint = "_get_tmbs_state@0")] public static unsafe extern int get_tmbs_state(); [DllImport("TMBSCOM.dll", EntryPoint = "_get_sio_error@0")] public static unsafe extern int get_sio_error(); [DllImport("TMBSCOM.dll", EntryPoint = "_check_pfin@4")] public static unsafe extern int check_pfin(int axis); [DllImport("TMBSCOM.dll", EntryPoint = "_check_status@4")] public static unsafe extern int check_status(int axis); [DllImport("TMBSCOM.dll", EntryPoint = "_check_alrm@4")] public static unsafe extern int check_alrm(int axis); [DllImport("TMBSCOM.dll", EntryPoint = "_reset_alarm@4")] public static unsafe extern int reset_alarm(int axis); [DllImport("TMBSCOM.dll")] public static unsafe extern int read_param(int axis, ref COMPACK dst); [DllImport("TMBSCOM.dll", EntryPoint = "_set_son@4")] public static unsafe extern int set_son(int axis); [DllImport("TMBSCOM.dll", EntryPoint = "_set_soff@4")] public static unsafe extern int set_soff(int axis); #endregion #region ############ MOVIMIENTO ############ [DllImport("TMBSCOM.dll", CallingConvention = CallingConvention.Winapi, EntryPoint = "_move_point@8")] public static unsafe extern int move_point(int axis, int point); [DllImport("TMBSCOM.dll", EntryPoint = "_move_org@8")] public static unsafe extern int move_org(int axis, int position); [DllImport("TMBSCOM.dll")] public static unsafe extern int move_abs(int axis, int position); [DllImport("TMBSCOM.dll")] public static unsafe extern int move_jog(int axis, int distance); [DllImport("TMBSCOM.dll", EntryPoint = "_move_inc@8")] public static unsafe extern int move_inc(int axis, int distance); [DllImport("TMBSCOM.dll", EntryPoint = "_move_rotate@16")] public static unsafe extern int move_rotate(int axis, int dir, int velocidad, int aceleracion); #endregion #region ############ PARAMETROS ############ [DllImport("TMBSCOM.dll", EntryPoint = "_write_velocity@12")] public static unsafe extern int write_velocity(int axis, int vcmd, int acmd); [DllImport("TMBSCOM.dll", EntryPoint = "_select_svparm@12")] public static unsafe extern int select_svparm(int axis, int gain_sel, int svparm); [DllImport("TMBSCOM.dll", EntryPoint = "_write_trqlim@12")] public static unsafe extern int write_trqlim(int axis, int atstop, int atmovement); [DllImport("TMBSCOM.dll", EntryPoint = "_write_inpos@8")] public static unsafe extern int write_inpos(int axis, int width); [DllImport("TMBSCOM.dll", EntryPoint = "_write_point@12")] public static unsafe extern int write_point(int axis, int point, ref COMPACK src); [DllImport("TMBSCOM.dll", EntryPoint = "_read_point@12")] public extern unsafe static int read_point(int axis, int point, ref COMPACK dst); [DllImport("TMBSCOM.dll")] public static unsafe extern int load_param(int axis); [DllImport("TMBSCOM.dll")] public static unsafe extern int write_param(int axis, ref COMPACK src); [DllImport("TMBSCOM.dll")] public static unsafe extern int read_svmem(int axis, int address, ref int dst); [DllImport("TMBSCOM.dll")] public static unsafe extern int write_svmem(int axis, int address, ref int dst); public struct COMPACK { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public long[] address; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public long[] data; public void initialize() { address = new long[31]; data = new long[31]; for (int i = 0; i < address.Length; i++) address[i] = i; } } public const int TMBS_NO_EXIST = 0; public const int TMBS_INITIAL = 1; public const int TMBS_INIT_ERROR = 2; public const int TMBS_OPENING = 3; public const int TMBS_RUNNING = 4; public const int SIO_DONE = 1; public const int SIO_ERROR = 0; public static COMPACK newPacket; public int[] axes_info; #endregion #endregion #region &&&&&&&&&&&&&&&&& CONSTRUCTOR &&&&&&&&&&&&&&&&& public SCN5() { axes_info = new int[16]; newPacket.initialize(); } #endregion #region &&&&&&&&&&&&&&&&& METODOS PUBLICOS &&&&&&&&&&&&&&&&& #region ############ COMUNICACIONES ############ public int Start_Comunnication(String port, int repeat) { int i = 0; int j = repeat; for (i = 0; i < 16; i++) axes_info[i] = -1; axes_info[0] = 0; // Axis#0 is used axes_info[1] = 0; /*while (init_tmbs_config(port, Convert.ToInt16("14", 16), 3, false, true, ref axes_info[0]) != 1 && j != 0) { if (get_tmbs_state() == TMBS_INIT_ERROR) return get_tmbs_state(); j--; } j = repeat; while (get_tmbs_state() <= TMBS_OPENING && j != 0) { Thread.Sleep(500); j--; }*/ while (init_tmbs() != 1 && j != 0) { Thread.Sleep(5); if (get_tmbs_state() == 2) { break; } j--; } return get_tmbs_state(); } public int Close_Communications() { return close_tmbs(); } public int Get_CurrentBaud() { return get_current_baud(); } public int Init_Calibration(int axis) { int status = SIO_ERROR; if (get_tmbs_state() == TMBS_RUNNING) { status = move_point(axis, -1000); Thread.Sleep(1000); move_abs(axis, -10000); } return status; } #endregion #region ############ ESTADO ############ public int Get_State() { return get_tmbs_state(); } public int Get_SIO_Error() { return get_sio_error(); } public int Check_Pfin(int axis) { return check_pfin(axis); } public int Check_Status(int axis) { return check_status(axis); } public int Check_Alarm(int axis) { return check_alrm(axis); } public int Reset_Alarm(int axis) { return reset_alarm(axis); } public int Servo_On(int axis) { return set_son(axis); } public int Servo_Off(int axis) { return set_soff(axis); } #endregion #region ############ MOVIMIENTO ############ public int Move_Point(int axis, int point) { return move_point(axis, point); } public int Move_Abs(int axis, int position) { return move_abs(axis, position); } public int Move_Inc(int axis, int distance) { return move_inc(axis, distance); } public int Move_ORG(int axis, int mode) { return move_org(axis, mode); } public int Move_Rotate(int axis, int dir, int velocidad, int aceleracion) { return move_rotate(axis, dir, velocidad, aceleracion); } public int Move_JOG(int axis, int distance) { return move_jog(axis, distance); } #endregion #region ############ PARAMETROS ############ public int Write_Velocity(int axis, int velocidad, int aceleracion) { return write_velocity(axis, velocidad, aceleracion); } public int Write_GainServo(int axis, int gain_sel, int svparm) { return select_svparm(axis, gain_sel, svparm); } public int Write_TrqLim(int axis, int atstop, int atmovement) { return write_trqlim(axis, atstop, atmovement); } public int Write_Tolerance(int axis, int width) { return write_inpos(axis, width); } public int Read_Position(int axis) { int bank1 = Convert.ToInt16("29", 16); int bank2 = Convert.ToInt16("29", 16); int dataLoc = Convert.ToInt16("7400", 16); read_svmem(axis, dataLoc, ref bank1); int retVal = bank1; return retVal; } public int Read_Code_RZONE(int axis) { int bank1 = Convert.ToInt16("29", 16); int bank2 = Convert.ToInt16("12", 16); int dataLoc = Convert.ToInt16("5", 16); read_svmem(axis, dataLoc, ref bank1); int retVal = bank1; //write_svmem(axis, dataLoc, ref bank2); return retVal; } public int Read_Code_FZONE(int axis) { int bank1 = Convert.ToInt16("29", 16); int bank2 = Convert.ToInt16("12", 16); int dataLoc = Convert.ToInt16("4", 16); read_svmem(axis, dataLoc, ref bank1); int retVal = bank1; //write_svmem(axis, dataLoc, ref bank2); return retVal; } #endregion #endregion #region &&&&&&&&&&&&&&&&& METODOS PRIVADOS &&&&&&&&&&&&&&&&& private long getLongValue(string positionStr) { bool isNegative; string hexRep; long longRep; long position = Convert.ToInt64(positionStr, 10); if (position < 0) isNegative = true; else isNegative = false; if (isNegative) { //Convert to hex to view in word format hexRep = Convert.ToString(position, 16); //Get least significant double word hexRep = hexRep.Substring(hexRep.Length - 8, 8); //swap double words hexRep = hexRep.PadRight(16, '0'); //convert to number longRep = Convert.ToInt64(hexRep, 16); return longRep; } else { //converts integer to a hex value hexRep = Convert.ToString(position, 16); //pad the value to ensure correct offset //since the positive numbers have leading 0's we do not need to fill the full 64 bits hexRep = hexRep + "00000000"; longRep = Convert.ToInt64(hexRep, 16); return longRep; } } private int getIntValue(long position) { string binaryRep; string hexRep; int intRep; bool isNegative; string onesComp; long onesCompInt; binaryRep = Convert.ToString(position, 2); //Check to see that the length is 64 bits, and check the sign bit(msb) to see if its negative //In the event that the number is positive, the msb=0 and will normally be left out when //converted to an integer if (binaryRep.Length == 64 && binaryRep.Substring(0, 1) == "1") isNegative = true; else { //Check to see if the position is 0 if (binaryRep.Length == 1) return 0; isNegative = false; } if (isNegative) { //To get actual decimal value, we must convert from the one's compliment representation //To ones compliment switch 0's to 1's and 1's to zeros, then add 1 onesComp = binaryRep.Replace("0", "2"); onesComp = onesComp.Replace("1", "0"); onesComp = onesComp.Replace("2", "1"); onesCompInt = Convert.ToInt64(onesComp, 2); onesCompInt = onesCompInt + 1; //This is now the unsigned value hexRep = Convert.ToString(onesCompInt, 16); //There is an extra word (8 bits) that we must remove hexRep = hexRep.Remove(hexRep.Length - 8, 8); intRep = Convert.ToInt16(hexRep, 16); //Add the sign back on intRep = (intRep * -1); return intRep; } else { //Convert the binary representation to HEX hexRep = Convert.ToString(Convert.ToInt64(binaryRep, 2), 16); //Remove the extra word (8 Bits) hexRep = hexRep.Remove(hexRep.Length - 8, 8); //Convert back to a decimal intRep = Convert.ToInt32(hexRep, 16); return intRep; } } #endregion } }
The problem: Using this code in a Unity3D project created a known and old problem. You could do only one access. The second attempt result in IDE lock.
Reading about a similar problem in this post.
I could find an excellent way to dinamically invoke a C++ DLL using C#.
For thoses who program in MFC Win32 using C++, should known the LoadLibrary, FreeLibrary. Essential to solve this problem with Tmbscom.DLL.
As a result, there are two DLLs, one that will be accessed from Unity3D (Driver_SCN5.DLL) to wrap the Tmbscom.DLL.
A converted source in C# used as a plugin for Unity3D:
using UnityEngine; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Threading; namespace Driver_SCN5 { public class SCN5: MonoBehaviour { int hModule; [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")] static extern int LoadLibrary( [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName); [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")] static extern IntPtr GetProcAddress( int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")] static extern bool FreeLibrary(int hModule); #region &&&&&&&&&&&&&&&&& IMPORT TMBSCOM &&&&&&&&&&&&&&&&& #region ############ COMUNICACIONES ############ public delegate int DLL_INIT_TMBS_CONFIG( string port, // Port Name ( "COM1","COM2"etc. ) int baud, // Baudrate( 4,5,6,7,11H,12H,13H,14H ) int nrt, // Retry bool reset, // bool automatic, // ref int axes_info // ); DLL_INIT_TMBS_CONFIG init_tmbs_config; public delegate int DLL_CLOSE_TMBS(); DLL_CLOSE_TMBS close_tmbs; public delegate int DLL_GET_CURRENT_BAUD(); DLL_GET_CURRENT_BAUD get_current_baud; public delegate int DLL_INIT_TMBS(); DLL_INIT_TMBS init_tmbs; #endregion #region ############ ESTADO ############ public delegate int DLL_GET_TMBS_STATE(); DLL_GET_TMBS_STATE get_tmbs_state; public delegate int DLL_GET_SIO_ERROR(); DLL_GET_SIO_ERROR get_sio_error; public delegate int DLL_CHECK_PFIN(int axis); DLL_CHECK_PFIN check_pfin; public delegate int DLL_CHECK_STATUS(int axis); DLL_CHECK_STATUS check_status; public delegate int DLL_CHECK_ALRM(int axis); DLL_CHECK_ALRM check_alrm; public delegate int DLL_RESET_ALARM(int axis); DLL_RESET_ALARM reset_alarm; /*NAO ESTAVA COMPLETA VER CODIGO ORIGINAL*/ public delegate int DLL_READ_PARAM(int axis, ref COMPACK dst); DLL_READ_PARAM read_param; public delegate int DLL_SET_SON(int axis); DLL_SET_SON set_son; public delegate int DLL_SET_SOFF(int axis); DLL_SET_SOFF set_soff; #endregion #region ############ MOVIMIENTO ############ [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate int DLL_MOVE_POINT(int axis, int point); DLL_MOVE_POINT move_point; public delegate int DLL_MOVE_ORG(int axis, int position); DLL_MOVE_ORG move_org; public delegate int DLL_MOVE_ABS(int axis, int position); DLL_MOVE_ABS move_abs; public delegate int DLL_MOVE_JOG(int axis, int distance); DLL_MOVE_JOG move_jog; public delegate int DLL_MOVE_INC(int axis, int distance); DLL_MOVE_INC move_inc; public delegate int DLL_MOVE_ROTATE(int axis, int dir, int speed, int accel); DLL_MOVE_ROTATE move_rotate; #endregion #region ############ PARAMETROS ############ public delegate int DLL_WRITE_VELOCITY(int axis, int vcmd, int acmd); DLL_WRITE_VELOCITY write_velocity; public delegate int DLL_SELECT_SVPARM(int axis, int gain_sel, int svparm); DLL_SELECT_SVPARM select_svparm; public delegate int DLL_WRITE_TRQLIM(int axis, int atstop, int atmovement); DLL_WRITE_TRQLIM write_trqlim; public delegate int DLL_WRITE_INPOS(int axis, int width); DLL_WRITE_INPOS write_inpos; public delegate int DLL_WRITE_POINT(int axis, int point, ref COMPACK src); DLL_WRITE_POINT write_point; public delegate int DLL_READ_POINT(int axis, int point, ref COMPACK dst); DLL_READ_POINT read_point; public delegate int DLL_LOAD_PARAM(int axis); DLL_LOAD_PARAM load_param; public delegate int DLL_WRITE_PARAM(int axis, ref COMPACK src); DLL_WRITE_PARAM write_param; public delegate int DLL_READ_SVMEM(int axis, int address, ref int dst); DLL_READ_SVMEM read_svmem; public delegate int DLL_WRITE_SVMEM(int axis, int address, ref int dst); DLL_WRITE_SVMEM write_svmem; public struct COMPACK { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public long[] address; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public long[] data; public void initialize() { address = new long[31]; data = new long[31]; for (int i = 0; i < address.Length; i++) address[i] = i; } } public const int TMBS_NO_EXIST = 0; public const int TMBS_INITIAL = 1; public const int TMBS_INIT_ERROR = 2; public const int TMBS_OPENING = 3; public const int TMBS_RUNNING = 4; public const int SIO_DONE = 1; public const int SIO_ERROR = 0; public static COMPACK newPacket; public int[] axes_info; #endregion #endregion #region &&&&&&&&&&&&&&&&& CONSTRUCTOR &&&&&&&&&&&&&&&&& public SCN5() { hModule = LoadLibrary("Tmbscom.DLL"); init_tmbs = (DLL_INIT_TMBS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_init_tmbs@0"), typeof(DLL_INIT_TMBS)); close_tmbs = (DLL_CLOSE_TMBS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_close_tmbs@0"), typeof(DLL_CLOSE_TMBS)); move_point = (DLL_MOVE_POINT) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_point@8"), typeof(DLL_MOVE_POINT)); get_tmbs_state = (DLL_GET_TMBS_STATE) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_get_tmbs_state@0"), typeof(DLL_GET_TMBS_STATE)); init_tmbs_config = (DLL_INIT_TMBS_CONFIG) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_init_tmbs_config@24"), typeof(DLL_INIT_TMBS_CONFIG)); set_son = (DLL_SET_SON) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_set_son@4"), typeof(DLL_SET_SON)); set_soff = (DLL_SET_SOFF) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_set_soff@4"), typeof(DLL_SET_SOFF)); move_org = (DLL_MOVE_ORG) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_org@8"), typeof(DLL_MOVE_ORG)); move_abs = (DLL_MOVE_ABS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_abs@8"), typeof(DLL_MOVE_ABS)); move_jog = (DLL_MOVE_JOG) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_jog@8"), typeof(DLL_MOVE_JOG)); move_inc = (DLL_MOVE_INC) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_inc@8"), typeof(DLL_MOVE_INC)); move_rotate = (DLL_MOVE_ROTATE) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_rotate@16"), typeof(DLL_MOVE_ROTATE)); write_velocity = (DLL_WRITE_VELOCITY) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_velocity@12"), typeof(DLL_WRITE_VELOCITY)); select_svparm = (DLL_SELECT_SVPARM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_select_svparm@12"), typeof(DLL_SELECT_SVPARM)); write_trqlim = (DLL_WRITE_TRQLIM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_trqlim@12"), typeof(DLL_WRITE_TRQLIM)); write_inpos = (DLL_WRITE_INPOS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_inpos@8"), typeof(DLL_WRITE_INPOS)); write_point = (DLL_WRITE_POINT) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_point@12"), typeof(DLL_WRITE_POINT)); read_point = (DLL_READ_POINT) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_read_point@12"), typeof(DLL_READ_POINT)); load_param = (DLL_LOAD_PARAM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_load_param@4"), typeof(DLL_LOAD_PARAM)); write_param = (DLL_WRITE_PARAM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_param@8"), typeof(DLL_WRITE_PARAM)); read_svmem = (DLL_READ_SVMEM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_read_svmem@12"), typeof(DLL_READ_SVMEM)); write_svmem = (DLL_WRITE_SVMEM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_svmem@12"), typeof(DLL_WRITE_SVMEM)); get_current_baud = (DLL_GET_CURRENT_BAUD) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_get_current_baud@0"), typeof(DLL_GET_CURRENT_BAUD)); get_sio_error = (DLL_GET_SIO_ERROR) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_get_sio_error@0"), typeof(DLL_GET_SIO_ERROR)); check_pfin = (DLL_CHECK_PFIN) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_check_pfin@4"), typeof(DLL_CHECK_PFIN)); check_status = (DLL_CHECK_STATUS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_check_status@4"), typeof(DLL_CHECK_STATUS)); check_alrm = (DLL_CHECK_ALRM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_check_alrm@4"), typeof(DLL_CHECK_ALRM)); reset_alarm = (DLL_RESET_ALARM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_reset_alarm@4"), typeof(DLL_RESET_ALARM)); read_param = (DLL_READ_PARAM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_read_param@8"), typeof(DLL_READ_PARAM)); axes_info = new int[16]; newPacket.initialize(); } #endregion #region &&&&&&&&&&&&&&&&& METODOS PUBLICOS &&&&&&&&&&&&&&&&& #region ############ COMUNICACIONES ############ public int Start_Comunnication(String port, int repeat) { int i = 0; int j = repeat; for (i = 0; i < 16; i++) axes_info[i] = -1; axes_info[0] = 0; // Axis#0 is used axes_info[1] = 0; while (init_tmbs_config(port, Convert.ToInt16("14", 16), 3, false, true, ref axes_info[0]) != 1 && j != 0) { if (get_tmbs_state() == TMBS_INIT_ERROR) return get_tmbs_state(); j--; } j = repeat; while (get_tmbs_state() <= TMBS_OPENING && j != 0) { Thread.Sleep(500); j--; } return get_tmbs_state(); } public int Close_Communications() { int result = close_tmbs(); FreeLibrary(hModule); return result; } public int Get_CurrentBaud() { return get_current_baud(); } public int Init_Calibration(int axis) { int status = SIO_ERROR; if (get_tmbs_state() == TMBS_RUNNING) { status = move_point(axis, -1000); Thread.Sleep(1000); move_abs(axis, -10000); } return status; } #endregion #region ############ ESTADO ############ public int Get_State() { return get_tmbs_state(); } public int Get_SIO_Error() { return get_sio_error(); } public int Check_Pfin(int axis) { return check_pfin(axis); } public int Check_Status(int axis) { return check_status(axis); } public int Check_Alarm(int axis) { return check_alrm(axis); } public int Reset_Alarm(int axis) { return reset_alarm(axis); } public int Servo_On(int axis) { return set_son(axis); } public int Servo_Off(int axis) { return set_soff(axis); } #endregion #region ############ MOVIMIENTO ############ public int Move_Point(int axis, int point) { return move_point(axis, point); } public int Move_Abs(int axis, int position) { return move_abs(axis, position); } public int Move_Inc(int axis, int distance) { return move_inc(axis, distance); } public int Move_ORG(int axis, int mode) { return move_org(axis, mode); } public int Move_Rotate(int axis, int dir, int velocidad, int aceleracion) { return move_rotate(axis, dir, velocidad, aceleracion); } public int Move_JOG(int axis, int distance) { return move_jog(axis, distance); } #endregion #region ############ PARAMETROS ############ public int Write_Velocity(int axis, int velocidad, int aceleracion) { return write_velocity(axis, velocidad, aceleracion); } public int Write_GainServo(int axis, int gain_sel, int svparm) { return select_svparm(axis, gain_sel, svparm); } public int Write_TrqLim(int axis, int atstop, int atmovement) { return write_trqlim(axis, atstop, atmovement); } public int Write_Tolerance(int axis, int width) { return write_inpos(axis, width); } public int Read_Position(int axis) { int bank1 = Convert.ToInt16("29", 16); int bank2 = Convert.ToInt16("29", 16); int dataLoc = Convert.ToInt16("7400", 16); read_svmem(axis, dataLoc, ref bank1); int retVal = bank1; return retVal; } public int Read_Code_RZONE(int axis) { int bank1 = Convert.ToInt16("29", 16); int bank2 = Convert.ToInt16("12", 16); int dataLoc = Convert.ToInt16("5", 16); read_svmem(axis, dataLoc, ref bank1); int retVal = bank1; //write_svmem(axis, dataLoc, ref bank2); return retVal; } public int Read_Code_FZONE(int axis) { int bank1 = Convert.ToInt16("29", 16); int bank2 = Convert.ToInt16("12", 16); int dataLoc = Convert.ToInt16("4", 16); read_svmem(axis, dataLoc, ref bank1); int retVal = bank1; //write_svmem(axis, dataLoc, ref bank2); return retVal; } #endregion #endregion #region &&&&&&&&&&&&&&&&& METODOS PRIVADOS &&&&&&&&&&&&&&&&& private long getLongValue(string positionStr) { bool isNegative; string hexRep; long longRep; long position = Convert.ToInt64(positionStr, 10); if (position < 0) isNegative = true; else isNegative = false; if (isNegative) { //Convert to hex to view in word format hexRep = Convert.ToString(position, 16); //Get least significant double word hexRep = hexRep.Substring(hexRep.Length - 8, 8); //swap double words hexRep = hexRep.PadRight(16, '0'); //convert to number longRep = Convert.ToInt64(hexRep, 16); return longRep; } else { //converts integer to a hex value hexRep = Convert.ToString(position, 16); //pad the value to ensure correct offset //since the positive numbers have leading 0's we do not need to fill the full 64 bits hexRep = hexRep + "00000000"; longRep = Convert.ToInt64(hexRep, 16); return longRep; } } private int getIntValue(long position) { string binaryRep; string hexRep; int intRep; bool isNegative; string onesComp; long onesCompInt; binaryRep = Convert.ToString(position, 2); //Check to see that the length is 64 bits, and check the sign bit(msb) to see if its negative //In the event that the number is positive, the msb=0 and will normally be left out when //converted to an integer if (binaryRep.Length == 64 && binaryRep.Substring(0, 1) == "1") isNegative = true; else { //Check to see if the position is 0 if (binaryRep.Length == 1) return 0; isNegative = false; } if (isNegative) { //To get actual decimal value, we must convert from the one's compliment representation //To ones compliment switch 0's to 1's and 1's to zeros, then add 1 onesComp = binaryRep.Replace("0", "2"); onesComp = onesComp.Replace("1", "0"); onesComp = onesComp.Replace("2", "1"); onesCompInt = Convert.ToInt64(onesComp, 2); onesCompInt = onesCompInt + 1; //This is now the unsigned value hexRep = Convert.ToString(onesCompInt, 16); //There is an extra word (8 bits) that we must remove hexRep = hexRep.Remove(hexRep.Length - 8, 8); intRep = Convert.ToInt16(hexRep, 16); //Add the sign back on intRep = (intRep * -1); return intRep; } else { //Convert the binary representation to HEX hexRep = Convert.ToString(Convert.ToInt64(binaryRep, 2), 16); //Remove the extra word (8 Bits) hexRep = hexRep.Remove(hexRep.Length - 8, 8); //Convert back to a decimal intRep = Convert.ToInt32(hexRep, 16); return intRep; } } #endregion } }
With this approuch the Unity3D Editor is working fine, to load and unload the Actuators DLL.
Hello, I’m the source author… I will test your modification 🙂
Hope it still working 😉
By the way, I would like to thank you. Your source code give me a good start in how to wrap the SCN6 driver.
Hi
I’m unable to find this tmbscom.dll, please could you tell me how to get it ?
Thank you
Hi. I used the DLL from the mirai intertech’s software. All the programs to operate and configure the SCNs Cylinders make use of this DLL. You can find the manual here (PDF). Inside this document you will see the reference to the softwares.
thank you very much