Hello,
For a school project, I bought a PCS10 some time ago. And for my project having my own software is essential. So I went out and looked, and I found “K8047D.dll” and it seemed to be right.
After having put this in my system32 directory, I used the [DllImport(“K8047D.dll”)] directive to create a .net wrapper. However, although it correctly finds the DLL and doesn’t give any kind of error, the module doesn’t do anything.
If I call StartDevice and then LEDon, the LED remains off.
And the int array from ReadData remains all 0 although ~4.8V was applied to one of the inputs and PClab correctly recognized it.
So, where’s my mistake?
Yours sincerely,
Ernst Haagsman
VEL436
November 12, 2007, 11:42am
2
Please copy all the files FASTTIME32.DLL, K8047D.DLL and K8047E.EXE to the system32 folder.
You may also put those files to your application folder.
Thank You Very Much, it was the K8047E.exe. I never read that it should be included in the System32 folder (perhaps an idea to put that in the documentation PDF?)
Now I’m going to try to get the cast from ReadData correct, but that should succeed anytime now. (long[]?).
But thanks again!
VEL436
November 12, 2007, 3:54pm
4
Yes, ReadData returns long integers (int32) to the buffer. In the document this is not clear. In the Delphi example the buffer is defined as integer. (Integer in Delphi it is 32 bits.)
In the example code it is more clear: DataBuffer: ARRAY[0…7] OF LongInt;
Also in Visual Basic example: Dim DataBuffer(0 To 7) As Long
Well… In fact… It actually returns an int[] in C#
I’ve got it working now. And all values will be casted to an int in C#
So it’s:
[DllImport("K8047D.dll")]
public static extern void LEDoff();
[DllImport("K8047D.dll")]
public static extern void ReadData(
[MarshalAs(UnmanagedType.LPArray)]int[] Volts
);
[DllImport("K8047D.dll")]
public static extern void SetGain
(int Channel_no,
int Gain);
And:
// Define
int[] VoltArray = new int[8];
// Get Vals
ReadData(VoltArray);
And now: VoltArray[2] = the Channel 1 Voltage.
VEL436
November 12, 2007, 5:33pm
6
Nice that it is working now!
Indeed, the int type represents signed 32-bit integers in MS Visual C#.
msdn2.microsoft.com/en-us/library/aa691145(VS.71 .aspx
At the moment there are no other examples in Visual C# for the PCS10. This your code will be good example for those who like to make some programming with the PCS10 in Visual C#. Could you please copy it here if possible…
To keep the code formatting unchanged please select the code text and then click the ”Code” button just above the edit window.
Thank you.
Well, here is my ADC class, which controls the hardware communication:
static class ADC
{
static bool LEDstatus = false;
public static bool LED
{
get
{
return LEDstatus;
}
set
{
LEDstatus = value;
if (LEDstatus)
{
LEDon();
}
else
{
LEDoff();
}
}
}
public static void Gain(int Channel, int Gain)
{
// Check Bounds
if (!(Channel > 0 && Channel <= 4))
{
throw new Exception("Channel Out Of Bounds");
}
if (!(Gain == 3 || Gain == 6 || Gain == 15 || Gain == 30))
{
throw new Exception("Gain Not Supported");
}
// Translate Gain
if (Gain == 3)
Gain = 10;
if (Gain == 6)
Gain = 5;
if (Gain == 15)
Gain = 2;
if (Gain == 30)
Gain = 1;
// Cast and run through DLL
SetGain(Channel, Gain);
}
public static void Start()
{
StartDevice();
LEDon();
}
public static void Stop()
{
StopDevice();
LEDoff();
}
public static decimal[] Volts()
{
// Returns Channel Voltages in Array
// [0] Channel 1 Voltage
// [1] Channel 2 Voltage
// etc etc
// Define
int[] VoltArray = new int[8];
// Get Vals
ReadData(VoltArray);
// Get into int array
int[] RawArray = new int[4];
RawArray[0] = VoltArray[2];
RawArray[1] = VoltArray[3];
RawArray[2] = VoltArray[4];
RawArray[3] = VoltArray[5];
// REPLACE WITH ACTUAL GAINS!!!
// ReturnArray[x] = (RawArray[x] / 255) * GAIN!!
decimal[] ReturnArray = new decimal[4];
ReturnArray[0] = Math.Round(((decimal)RawArray[0] / 255) * 3, 2);
ReturnArray[1] = Math.Round(((decimal)RawArray[1] / 255) * 3, 2);
ReturnArray[2] = Math.Round(((decimal)RawArray[2] / 255) * 3, 2);
ReturnArray[3] = Math.Round(((decimal)RawArray[3] / 255) * 3, 2);
// Return Vals
return ReturnArray;
}
public static int[] Time()
{
// Returns the Time in an array,
// [0] Time Most Significant Byte
// [1] Time Least Significant Byte
// Define
int[] VoltArray = new int[8];
// Get Vals
ReadData(VoltArray);
// Copy Juicy Bits
int[] ReturnArray = new int[2];
ReturnArray[0] = VoltArray[0];
ReturnArray[1] = VoltArray[1];
// Return
return ReturnArray;
}
public static void Exit()
{
LEDoff();
}
// DLL Calls
#region DLL Calls
[DllImport("K8047D.dll")]
private static extern void StartDevice();
[DllImport("K8047D.dll")]
public static extern void StopDevice();
[DllImport("K8047D.dll")]
public static extern void LEDon();
[DllImport("K8047D.dll")]
public static extern void LEDoff();
[DllImport("K8047D.dll")]
public static extern void ReadData(
[MarshalAs(UnmanagedType.LPArray)]int[] Volts
);
[DllImport("K8047D.dll")]
public static extern void SetGain
(int Channel_no,
int Gain);
#endregion
}
And to all others who try to use the K8047 with C#: Good Luck!
VEL436
November 12, 2007, 5:54pm
8
Thanks!
For me this is nice reading for studying Visual C#.
VEL448
November 13, 2007, 9:48am
9
A more general-purpose class for the K8047.dll
using System;
using System.Runtime.InteropServices;
namespace Velleman.Kits
{
internal static class K8047Native
{
[DllImport("K8047D.dll")]
internal static extern void StartDevice();
[DllImport("K8047D.dll")]
internal static extern void StopDevice();
[DllImport("K8047D.dll", EntryPoint = "LEDon")]
internal static extern void LedOn();
[DllImport("K8047D.dll", EntryPoint = "LEDoff")]
internal static extern void LedOff();
[DllImport("K8047D.dll")]
internal static extern void ReadData(
[MarshalAs(UnmanagedType.LPArray)]int[] Volts);
[DllImport("K8047D.dll")]
internal static extern void SetGain(int ChannelNo, int Gain);
}
sealed class K8047
{
public enum GainLevel
{
One = 1,
Two = 2,
Five = 5,
Ten = 10
}
private K8047() { }
public static readonly K8047
TheInstance = new K8047(); // Singleton
public Boolean LedOn
{
set
{
if (value) K8047Native.LedOn();
else K8047Native.LedOff();
}
}
public void Start()
{
K8047Native.StartDevice();
}
public void SetChannelGain(int ChannelNo, GainLevel Gain)
{
K8047Native.SetGain(ChannelNo, (int)Gain);
}
public void ReadData(int[] Volts)
{
K8047Native.ReadData(Volts);
}
public void Stop()
{
K8047Native.StopDevice();
}
}
}
K8047 myDevice = K8047.TheInstance;
myDevice.Start();
myDevice.LedOn = false;
myDevice.SetChannelGain(1, K8047.GainLevel.Five);
myDevice.Stop();