When trying to get the state ‘torque’ or ‘demo’, function only returns ‘false’.
The return value does not depend on the actual state of the flag - returns only ‘false’.
If you are programming in Delphi, you should be careful with boolean types. The DLL uses the Windows API BOOL type, which is different from Boolean. Both are boolean types, but their representation of true and false is different.
unit MotorDLL;
interface
uses
Windows, Messages, Motors;
const
mtrapi32 = 'mtrapi32.dll';
function SMCConnect(Port: PChar; Motors: DWORD): BOOL; stdcall;
procedure SMCDisconnect; stdcall;
function SMCConnected: BOOL; stdcall;
function SMCGetMotorCount: DWORD; stdcall;
function SMCGetInputCount: DWORD; stdcall;
function SMCGetOutputCount: DWORD; stdcall;
procedure SMCSetDemo(Enabled: BOOL); stdcall;
function SMCDemo: BOOL; stdcall;
procedure SMCMove(Motor, Steps: DWORD; Direction: DWORD; Speed: DWORD); stdcall;
procedure SMCStop(Motor: DWORD); stdcall;
function SMCGetMoving(Motor: DWORD): BOOL; stdcall;
function SMCGetDirection(Motor: DWORD): DWORD; stdcall;
procedure SMCSetTorque(Motor: DWORD; Enabled: BOOL); stdcall;
function SMCGetTorque(Motor: DWORD): BOOL; stdcall;
function SMCGetInput(Index: DWORD): BOOL; stdcall;
procedure SMCSetOutput(Active: BOOL); stdcall;
function SMCGetOutput: BOOL; stdcall;
implementation
function SMCConnect; external mtrapi32 name 'SMCConnect';
procedure SMCDisconnect; external mtrapi32 name 'SMCDisconnect';
function SMCConnected; external mtrapi32 name 'SMCConnected';
function SMCGetMotorCount; external mtrapi32 name 'SMCGetMotorCount';
function SMCGetInputCount; external mtrapi32 name 'SMCGetInputCount';
function SMCGetOutputCount; external mtrapi32 name 'SMCGetOutputCount';
procedure SMCSetDemo; external mtrapi32 name 'SMCSetDemo';
function SMCDemo: BOOL; external mtrapi32 name 'SMCDemo';
procedure SMCMove; external mtrapi32 name 'SMCMove';
procedure SMCStop; external mtrapi32 name 'SMCStop';
function SMCGetMoving; external mtrapi32 name 'SMCGetMoving';
function SMCGetDirection; external mtrapi32 name 'SMCGetDirection';
procedure SMCSetTorque; external mtrapi32 name 'SMCSetTorque';
function SMCGetTorque; external mtrapi32 name 'SMCGetTorque';
function SMCGetInput; external mtrapi32 name 'SMCGetInput';
procedure SMCSetOutput; external mtrapi32 name 'SMCSetOutput';
function SMCGetOutput; external mtrapi32 name 'SMCGetOutput';
end.
Pseudo code:
var
Value: BOOL;
begin
Value := SMCGetTorque(0);
if Value then
ToqueIsEnabled else TorqueIsDisabled;
end;
Adjust the header file to your needs. Experiment with the return value to see what is returned for true and what is returned for false; use integer types (of the same size) if necessary. You will probably get -1 for true and 0 for false.
The example is for Embarcadero Delphi, not Free Pascal, modify it until it works.
The BOOL type in Embarcadero Delphi means: zero is False and any nonzero value is True.
BOOL corresponds to LongBool which is a 32-bit integer (DWORD).
The DLL can be used from any programming language.
You have done a good job modifying the unit, but I see that you are developing a console application, which is completely different from a windowed application. Is the problem that you are not getting the correct status or that the motor is not responding to the commands? I am guessing that the motor is responding but the status is not correct?
If the motor is responding, but you are not getting the correct status, then the problem is due to timing. The communication between the DLL and the card is asynchronous, meaning that when you call SetTorque, the command is sent to the card but the reply may come in later. Once torque has been applied, a confirmation is sent back to the DLL, and the DLL updates its internal status. It is possible that you request the status before the card’s answer has been received and processed.
Illustration:
[size=85]In this picture, GetTorque is called before the updated status is received.[/size]
It is very difficult to combine a console application with something event driven.
//
Writeln ('SMCSetTorque & SMCGetTorque');
Result:= SMCGetTorque (0);
Writeln ('SMCGetTorque return: ', Result);
Writeln ('Set Torque to ON: SMCSetTorque (0, TRUE)');
SMCSetTorque (0,TRUE);
Sleep (100);
Result:= SMCGetTorque (0);
Writeln ('SMCGetTorque return: ', Result);
Writeln ('Press ENTER');
Readln;
//
I use timeouts 0.1s (Sleep(100) command).
Moreover, increasing of the timeout does not give any result.
Windows application written in Free Pascal behaves similarly bad.
Agree that it looks a little strange.
And this is the problem: either something wrong with the DLL, or the DLL is not fully documented.
So. I wrote a test application with the form.
In this form, the various API calls are handled by different event handlers (buttons).
All works Ok. But!
There is no documentation that could be about to guess in advance.
And it is looks strange.
Do you agree?
I would like to see the API, which allows the programmer to use different calls within the same procedure (function, handler) without using far not the easiest programming techniques.
If we use the description of API, then the code below (Free Pascal/Lazarus) should work fine:
SMCSetTorque(0,TRUE);
// Timeout 0.25s
Sleep(250);
// Checking
ChokeLI:= SMCGetTorque(0);
However, it did not work. Get-type call does not return the actual state.
We have to use the ‘pinch bar’:
SMCSetTorque(0,TRUE);
// Timeout 0.25s
Sleep(250);
// Use the 'pinch bar'
Application.ProcessMessages;
// Checking
ChokeLI:= SMCGetTorque(0);
As you can see, the problem here is not in the asynchronous operation.
The problem is badly written API.
[quote]If we use the description of API, then the code below (Free Pascal/Lazarus) should work fine: …Sleep(250)[/quote]That is if you don’t know what Sleep does. Sleep suspends the current thread, which simply means that it can not do anything.
[quote]We have to use the ‘pinch bar’: … Application.ProcessMessages;[/quote]The DLL uses the Windows message loop for thread synchronization, which is why Application.ProcessMessages appears to work and Sleep doesn’t.
This may be hard to understand, but the nature of the card requires that it works that way. Moving a motor for example may take 5 seconds, you can not put the application to sleep for that period.
[quote=“VEL417”]Please: Mind your language.
No need to insult the people that invest quite some time in trying to help you.[/quote]
I did not mean to offend anyone.
But do not strike a pose ‘Caesar’s wife is above suspicion’.
I repeat: Documenting API DLL is desirable to improve.
[quote]It may be worth your while to document (and write) API based on the fact that it will be used not only for demonstration and education programs?[/quote]We have to weigh carefully the fact that not everyone that will be using the card is a software programmer. We can not use more difficult constructs like callbacks.
[quote]And you are constantly trying to explain to me that I do not know how to write software.[/quote]If you know how to write software and want more than the current API can offer, you are free to write your own API. The K8096 uses the serial port which is easy to write to / read from. The communication is documented and we are here to explain it should it not be clear.