Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DECLARE enigma with the Boolean type

Status
Not open for further replies.

dkean4

Programmer
Feb 15, 2015
282
US
I purchased a little controller board from Velleman K8055. It is designed to work with a DLL and here is an incomplete list of Declarations written in Visual Basic, to access the board.

Code:
Private Declare Function Version Lib "k8055d.dll" () As Long
Private Declare Function SearchDevices Lib "k8055d.dll" () As Long
Private Declare Function SetCurrentDevice Lib "k8055d.dll" (ByVal CardAddress As Long) As Long
Private Declare Function OpenDevice Lib "k8055d.dll" (ByVal CardAddress As Long) As Long

Private Declare Sub CloseDevice Lib "k8055d.dll" ()
Private Declare Function ReadAnalogChannel Lib "k8055d.dll" (ByVal Channel As Long) As Long
Private Declare Sub ReadAllAnalog Lib "k8055d.dll" (Data1 As Long, Data2 As Long)
Private Declare Sub OutputAnalogChannel Lib "k8055d.dll" (ByVal Channel As Long, ByVal Data As Long)
Private Declare Sub OutputAllAnalog Lib "k8055d.dll" (ByVal Data1 As Long, ByVal Data2 As Long)
Private Declare Sub ClearAnalogChannel Lib "k8055d.dll" (ByVal Channel As Long)
Private Declare Sub SetAllAnalog Lib "k8055d.dll" ()
Private Declare Sub ClearAllAnalog Lib "k8055d.dll" ()
Private Declare Sub SetAnalogChannel Lib "k8055d.dll" (ByVal Channel As Long)
Private Declare Sub WriteAllDigital Lib "k8055d.dll" (ByVal Data As Long)
Private Declare Sub ClearDigitalChannel Lib "k8055d.dll" (ByVal Channel As Long)
Private Declare Sub ClearAllDigital Lib "k8055d.dll" ()
Private Declare Sub SetDigitalChannel Lib "k8055d.dll" (ByVal Channel As Long)
Private Declare Sub SetAllDigital Lib "k8055d.dll" ()
Private Declare Function ReadDigitalChannel Lib "k8055d.dll" (ByVal Channel As Long) As Boolean
Private Declare Function ReadAllDigital Lib "k8055d.dll" () As Long
Private Declare Function ReadCounter Lib "k8055d.dll" (ByVal CounterNr As Long) As Long
Private Declare Sub ResetCounter Lib "k8055d.dll" (ByVal CounterNr As Long)
Private Declare Sub SetCounterDebounceTime Lib "k8055d.dll" (ByVal CounterNr As Long, ByVal DebounceTime As Long)
Private Declare Function SetTimer Lib "user32" ( _
    ByVal HWnd As Long, ByVal nIDEvent As Long, _
    ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" ( _
    ByVal HWnd As Long, ByVal nIDEvent As Long) As Long

I have successfully converted some and I cannot convert others to work properly in VFP. The lines in red are resisting me by not returning values.

Code:
DECLARE Integer OpenDevice IN k8055d.dll Integer CardAddress
DECLARE SetDigitalChannel IN k8055d.dll Integer Channel
[COLOR=#CC0000]DECLARE Integer ReadDigitalChannel IN k8055d.dll integer Channel[/color]
DECLARE ClearDigitalChannel IN k8055d.dll integer Channel
[COLOR=#CC0000]DECLARE Integer [COLOR=#CC0000]ReadAllDigital[/color] IN k8055d.dll[/color][COLOR=#CC0000][/color]
DECLARE CloseDevice IN k8055d.dll
DECLARE ClearAllDigital IN k8055d.dll

The problem appears to be simple. In VB these Declarations are defined as Functions. Dennis however is using the "Integer" type. VFP does not have the Boolean option and after a million tests I was able to get a result for the OpenDevice Declaration to return a 0 to me, which indicates that the device was opened. That works great and reliably. The other Function declarations, however set the return value to Boolean and VFP does not have a Boolean option. What can I do there?

Some of you guys may have lots more experience with DLLs and Declarations than me. Any help is appreciated...



Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
The code for the USB Experimentation Board is not hard to implement.

To connect you do this:
Code:
Declare Integer OpenDevice in k8055d.dll integer CardAddress 

h = OpenDevice(0)
IF h >= 0
	--- code for success ---
ELSE
	--- code for failure ---
ENDIF

To turn on a channel (there are 8 i/o channels)
Code:
Declare Integer SetDigitalChannel in k8055d.dll integer Channel
SetDigitalChannel(1)

To turn off a channel
Code:
Declare Integer ClearDigitalChannel in k8055d.dll integer Channel
ClearDigitalChannel(1)


Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
I believe you, Griff, I only have read manuals and don't own such a board. From what I understand some dip switches or jumpers called SK5 and SK6 (already mentioned above) determine the boards ChannelAddress and as two switches or jumpers can be either 0 or 1 you may attach up to 4 similar boards and address them with address 0-3. If Dennis board was changed from default 0 you need to call OpenDevice with the correct address, obviously. It's good to know, though, that the OpenDevice Declaration itself should be okay.

And maybe it's also a less likely failing test to set a channel to a certain value than to read a channel. So that is a good idea to get away from the output value problem.
Are there any LEDs on the board to show the state of a channel?

Bye, Olaf.
 
I don't remember the DIP switches...

There were some niggles, I don't remember being able to read the status of the outputs, so I used a feedback loop
taking the output to a relay that had two poles, one to switch the fan and the other went back to one of the digital
inputs to confirm the status.

We are talking 2009 here. Great fun building the board, testing it all and setting it up, I could turn on a cooling fan either based on the temperature
in the garage - or via the net from anywhere with a connection.



Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
One more thing I just noticed: Right under the screenshot of your Controller form you have the code [tt]UU2 = ReadAllDigital(2)[/tt]. ReadAllDigital has no input parameter, it outputs all channels state in one value, don't you get an error if you call it with parameter? Your declaration [tt]DECLARE Integer ReadAllDigital IN k8055d.dll[/tt] correctly declares it as having an output function type integer and no input parameter.

Overall the impression I get is you fail on wrong usage and understanding of the functions more than on declares not working.

Bye, Olaf.
 
Hi

Just checked, the board has two jumpers for the address - two analogue inputs and 5 digital ones,
8 output channels.

One output was no use, because it 'flashed' during boot if I recall correctly.



Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
I think part of the fun was the flashing lights.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
Looking at the documentation I am right, you can't read the status of the digital outputs using the DLL, only the inputs.

But the docs do say the board supports 0-7 addresses.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
> But the docs do say the board supports 0-7 addresses.
Are you really talking about the CardAddress here, or the Channel numbers?
With OpenDevice you initialise the whole card, not one channel on it.

Bye, Olaf.
 
From the documentation for mine:
Docs said:
The K8061 interface board has 8 digital input channels and 8 digital output channels. In addition, there
are 8 analogue inputs, 8 analogue outputs and one PWM output. The number of inputs/outputs can
be further expanded by connecting more (up to a maximum of eight) cards to the PC's USB
connectors. Each card is given its own identification number by means of three jumpers, A1, A2 and
A3 (see table 1 below for card numbering).
Connection to the computer is optically isolated, so that damage to the computer from the card is not
possible.
All communication routines are contained in a Dynamic Link Library (DLL) K8061.DLL.
This document describes all functions and procedures of the DLL that are available for your
application programme. Calling the functions and procedures exported by the DLL, you may write
custom Windows (98SE, 2000, Me, XP) applications in Delphi, Visual Basic, C++ Builder or any other
32-bit Windows application development tool that supports calls to a DLL.
A complete overview of the procedures and functions that are exported by the K8061.DLL follows. At
the end of this document there are listings of example programmes in order to gain an insight as to
how to construct your own application programmes. The examples are written in Delphi, Visual Basic
and C++ Builder. In the listings there are full declarations for the DLL function and procedures.
Note that all the examples in the function and procedure description section are written for Delphi.

A1 A2 A3 CARD ADDRESS
ON ON ON 0
OFF ON ON 1
ON OFF ON 2
OFF OFF ON 3
ON ON OFF
4
OFF ON OFF
5
ON OFF OFF
6
OFF OFF OFF
7
TABLE 1: Jumper A1, A2, A3 Settings

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
Ah, I just spotted the documentation keeps quoting K8061 not B8055.



Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
Griff,

Thank you very much for the Zip file. I opened it installed the project and looked at your code. I see that you get 0s and 1s as returns and I copied your K8055D.dll. Yours is older than mine, but it works the same as my DLL in my machine. I see that you guys had fun on the forum while I was sleeping.

After reading all your posts and doing lots of experiments this morning, first let me thank both you Griff and Olaf for all the brain work offered. My biggest problem was that I did not understand the DECLARE command quite right. And I never tried. I simply blanked it out and used samples from existing and working code. And now that I got a good lashing from Olaf, I had to wake up to the reality of DECLARE. So, I DECLARE this.

The types (.F. and 0) which Olaf and I spoke about came from this:

? OpenDevice(0) && gives a "0", indicating the Device ID (I just happened to have an ID of 0)
? CloseDevice(0) && gives back a .T. or a .F. occasionally but it definitely sets the return as Boolean for some reason.

That actually makes sense because the device is turned off and some transient returns a random boolean. There is another obscure instance in which that takes place but not worth the time.

Setting and clearing the 8 OUTPUT ports works great, now.

Code:
DECLARE SetDigitalChannel IN k8055d.dll Integer PortNo
SetDigitalChannel (2)
SetDigitalChannel (7)

DECLARE ClearDigitalChannel IN k8055d.dll Integer PortNo
ClearDigitalChannel(2) 
ClearDigitalChannel(7)

Reading the 5 INPUT ports works great too.

Code:
DECLARE Integer ReadDigitalChannel Integer InputPort
PortStatus = ReadDigitalChannel(InputPort)
I have not tested the Analog Output ports, but feel confident that it will work great.

One rant I will offer is that removing direct access to devices in the NT OS's was a crime. The NT OSs require you to pray and plead for mercy. All this crap would not exist if direct access was existent. Arduino, Blackberry Pie etc could be replaced with a tiny controller geared at receiving specialized low level commands and not having to reprocess anything... just execute commands remotely with fixed delays. As things are, every arduino SP3 etc needs huge layers of wanna be OS to just turn a light on. And in the 8055 case there is a 1 second delay in processing. This $100 device is nothing more than a stupid and slow parallel 8 bit port ($0.73), a separate 5 bit port for input and 2 x 8 bit DACs multiplexed to save 6 cents in production costs.





Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Griff,

Had some time to look at your code this afternoon. Nice! Your help is very appreciated.


Olaf,

Thanks for the extra effort. I finally grasped the DECLARE command. Much appreciated.


You guys enjoy your weekend.



Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
First, congrats on getting things to work.

Griff, as you saw yourself you posted documentation of another board.

Just one more time: CloseDevice is one of the functions having no return value. In the VB declarations you have this is easily spotted as the difference of Sub (Subroutine) and Function. Whatever you get out, does not come from the DLL. You can really use such DLL functions without loking at their result, it has no information value.

As far as I see you had the expecation ReadDigitalChannel(n) returns what you set with SetDigitalChannel(n). I'm not sure, but at least if there are 8 outputs and only 5 inputs this can't work. If I compare this to serial port communication the output buffer only comes back as input, if there is an echo device or software at the other end. So maybe you expected ReadDigitalChannel to echo back what you set and that's not the way it works. Just speculation.

Bye, Olaf.
 
Yes Olaf, but that is actually the documentation that came with my board - which seems to be the same as the OP's

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
K8061 and K8055 may be same family, but not same board!?
You said yourself:
I just spotted the documentation keeps quoting K8061 not B8055

From what manuals I found for K8055 its card address is only determined by two jumpers or dip switches, not three.

Bye, Olaf.

 
Olaf,

The congratulations belongs to Griff and you, Olaf. I'm grateful. Concerning the two ports, this silly board of mine is probably an slightly inferior board to the K8061, which Griff is using. I had it on hand for many years. I believe this function was designed to read the values of the OUTPUT port. And it would come in as an integer from 0-255, one bit for each port.

Code:
[b]DECLARE Integer ReadAllDigital IN k8055d.dll [/b]

For the INPUT port, which on my card is 5 bits and 8 bits on Griff's card, the ports are read individually as follows.

Code:
[b]DECLARE Integer ReadDigitalChannel IN k8055d.dll Integer Channel[/b]
. So, separate funcs are used for the two ports.

For a time the "ReadAllDigital" function was giving me the right codes and in latter tests it was giving me the number 4 for all combinations. Not sure where I went wrong on that, I will work on that later. Right now I have to implement the OUTPUT ports to control some devices with "step up" relays to turn on/off my Compressor and a few other devices, which I too often leave running all night, because I am too lazy to go out, when programming... ha ha ha.



Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
No, as far as I understood manuals the ReadDigitalChannel will give you the current bit on that channel, just one bit! Therefore the Boolean function type.
And ReadAllDigital will combine all channel bits to one value, therefore an INTEGER or LONG function type. You could get each channels bit with BitTest() for example.

Both Read functions act on the input channels. You can of course easily prove me wrong, when you read in what you output there, but in my understanding any output port is just set, not readable, unless you connect output and input, which electronically may or may not be advisable.

Refer to your manual, if you still have one.

Bye, Olaf.


PS: This manual also describes it the way Griff and I see it - each channel being one bit only.
manual said:
Digital Input procedures and functions
ReadDigitalChannel(Channel) - Reads the status of the [highlight #FCE94F]input[/highlight] channel
ReadAllDigital(Buffer) - Reads the status of all the [highlight #FCE94F]input[/highlight] channels

The manual is not very descriptive about the nature of the digital channels...

manual said:
The K8055 interface board has 5 digital input channels and 8 digital output channels. In addition, there
are two analogue inputs, two analogue voltage outputs and two PWM (Pulse Width Modulation)
outputs with 8 bit resolution. The number of inputs/outputs can be further expanded by connecting
more (up to a maximum of four) cards to the PC's USB connectors. Each card is given its own
identification number by means of two jumpers, SK5 and SK6 (see table 1 below for card numbering).

The two PWM each have 8bit, the bitness of the formentioned 5 input channels is not specified, but the declarations you have point out these channels are only 1 bit each.

More concrete...

manual said:
FUNCTION ReadDigitalChannel(Channel: Longint): Boolean;
and
manual said:
Result
[tt]Boolean[/tt]: TRUE means that the channel has been set and FALSE means that it has been cleared.

You don't get more bits by declaring this as integer, you only declare this as integer, because though VFP has a boolean type (called logical) the DECLARE-DLL command has not. You still only get two values, likely 0 and 1 or 0 and -1 or perhaps 0 and any random non zero value, but the DLL only retuns one of two possible states of the channel, high or low. Not 8 bits. Welcome to the serial world, bytes are serialized to bits and then deserialized...

I guess you get the correct VFP logical value of you take the int and convert it to [tt]llChannelStatus = NOT (ReadDigitalChannel(nChannel)=0)[/tt]. That'll give .F. for return value 0 and .T. for any other value and is the typical way to convert an integer coming from a DLL function really returning a boolean type to a VFP logical value.

Bye, Olaf.
 
Hi

I am not 100% convinced that ReadAllDigital() reads the controllable outputs, just all the readable digital inputs in one byte (sic)

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
Yes, Griff,

manual said:
ReadAllDigital
Syntax
[tt]FUNCTION ReadAllDigital: Longint;[/tt]

Result
[tt]Longint:[/tt] The 5 LSB correspond to the status of the input channels. A high (1) means that the
channel is HIGH, a low (0) means that the channel is LOW.

Description
The function returns the status of the digital [highlight #FCE94F]inputs[/highlight]

Clear as mud. Now all you need to know is LSB means least significant bits. Since you have 5 input channels/bits the lowest 5 bits of the Longint - In VFP just a normal int mean a value range of 0 to 31. Hex 0x00000000 to 0x0000001f. The uppper bits (MSB) all stay 0, therefore it also doesn't harm VFP has no Longint 64bit integrer type, just 32bit integer, only 5 bits are used anyway. [tt]BitTest(ReadAllDigital(),nChannel-1)[/tt] with nChannel from 1 to 5 will give you that channel state as a VFP logical .T. or .F., too. Bits are numbered from 0 to 31 and thus nChannel-1 here, when nChannel still goes from 1 to 5.

So even if ReadDigitalChannel doesn't work out for you for any reason, ReadAllDigital should, as its declaration has no totally different function type in VFP (int instead of longint is not so far away as int instead of boolean, though in the end a vbBoolean also is an int or byte). But you read inputs, never outputs. You set or clear outputs only and a verification, whether that works can only be done by reaction of whatever you control via the output or receive in a same or similar card on the other end of your wiring. Therefore I also asked, whether the board has LEDs signaling the state of channels, the DLL functions don't help you for that output validation check.

Bye, Olaf.
 
Griff and Olaf.

Thanks guys. Good to know. I tested the INPUT ports and thought that I was reading the OUTPUT ports. That's why it stopped working after a while. I knew that it was giving me the correct settings on the test of the 3 LSBs. The number 4 I was reading was coming from the pull up resistor left on the 3rd bit input port. Not paying close attention, I guess.

The more important function to me at this time is the output ports and they work fine. My tools like the compressor are in the area of 3HP apiece and 3 days of charging up the tank every 15 minutes has turned costly, when I forget to turn it off. So, VFP to the rescue... I told you... VFP rocks!

Merci mes amis!


Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top