Programming

Interfacing the real-world with a Velleman K8055N / P8055N

I don't do a whole lot of programming, but when I do, its now in QB64! For more information on our K8055 / P8055N projects, take a look at our Electronics pages.

The Velleman K8055N is a USB I/O hobby board: it comes with 5 digital inputs, 2 analogue inputs, 8 digital 'open-collector' outputs, 2 analogue DAC output (and 2 associated PWM's clocked at 23.43kHz). Maybe not sufficient for demanding I/O applications, but certainly sufficient for the interfacing of many home-brew hobby applications.

Rather than messing around with Windows graphical programming environments, if you simply want control of board, I highly recommend QB64. In QB64, you can make calls to procedures stored in external dll's in a native, and fairly easy to understand way. This is most convenient since the procedural calls to control the K8055N are all neatly stored in a single dll, which as of the time of writing, is version 5.0.0.0 'k8055d.dll'. You can download the file here, or direct from Velleman - naturally, the file also comes bundled with the K8055N product.

To load the dll in QB64, we use the following declarations, and then we can access the procedures as functions as one would native QB functions.

DECLARE DYNAMIC LIBRARY "K8055D"
	FUNCTION Version&
	FUNCTION SearchDevices&
	FUNCTION SetCurrentDevice& (BYVAL CardAddress AS LONG)
	FUNCTION OpenDevice& (BYVAL CardAddress AS LONG)
	FUNCTION CloseDevice&
	FUNCTION ReadAnalogChannel& (BYVAL Channel AS LONG)
	FUNCTION ReadAllAnalog& (Data1 AS LONG, Data2 AS LONG)
	FUNCTION OutputAnalogChannel& (BYVAL Channel AS LONG, BYVAL Data1 AS LONG)
	FUNCTION OutputAllAnalog& (BYVAL Data1 AS LONG, BYVAL Data2 AS LONG)
	FUNCTION ClearAnalogChannel& (BYVAL Channel AS LONG)
	FUNCTION SetAllAnalog&
	FUNCTION ClearAllAnalog&
	FUNCTION SetAnalogChannel& (BYVAL Channel AS LONG)
	FUNCTION WriteAllDigital& (BYVAL Data1 AS LONG)
	FUNCTION ClearDigitalChannel& (BYVAL Channel AS LONG)
	FUNCTION ClearAllDigital&
	FUNCTION SetDigitalChannel& (BYVAL Channel AS LONG)
	FUNCTION SetAllDigital&
	FUNCTION ReadDigitalChannel& (BYVAL Channel AS LONG)
	FUNCTION ReadAllDigital&
	FUNCTION ReadCounter& (BYVAL CounterNr AS LONG)
	FUNCTION ResetCounter& (BYVAL CounterNr AS LONG)
	FUNCTION SetCounterDebounceTime& (BYVAL CounterNr AS LONG, BYVAL DebounceTime AS LONG)
END DECLARE

Bits of Programming used on this Website

Equations

Equations produced using the MathJAX and written in AsciiMath.

The equations are written inline surrounded by the grave accent, within the normal html paragraph tags. For example, ` int_0^(x=oo) exp(x)x^2dx ` is rendered as `int_0^(x=oo) exp(x)x^2dx`. There are many references available on the internet for the math symbols supported by AsciiMath and its syntax. When you don't want MathJAX to parse the grave accent, enclose the quote in <code></code> tags. To utilise the MathJAX package, you must reference the package in the <head> of your html files,

<script type="text/javascript"
src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=AM_CHTML">
</script>

You can also specify additional config files (the above code loads a file called AM_CHTML from the mathjax server). To load an additional config file, simply append it to the end of the config with a comma delimiter. Why use an external file? Because it contains additional macros and symbols which are not in the base config package. Two important things to note when using a config file which is hosted on a different server to the MathJAX installation (like I do: installation on CDN server, but config file on my server):

  1. When specifying the config file on a different server, you must specify full URL including protocol
  2. ...and perhaps more importantly, in your config file (on the different server), you must include a line at the end of your config file instructing MathJax to stop waiting, and carry on - otherwise, mathJax will stop and wait for 15seconds before rendering the maths. This line is: MathJax.Ajax.loadComplete("http://resospace.nz/mjax_conf.js");

For example, my external config file ("http://resospace.nz/mjax_conf.js") contains two such loadComplete calls. Like the code says, the config will either be on my localhost or on the resospace server - these two lines instruct mathJAX to continue having loaded either, or...

MathJax.Hub.Register.StartupHook("AsciiMath Jax Config",function () {
	var AM = MathJax.InputJax.AsciiMath.AM;
	AM.symbols.push(
		{input:"hbar", tag:"mi", output:"\u210F", tex:null, ttype:AM.TOKEN.CONST}
	);
	AM.symbols.push(
		{input:"mathbi", tag:"mstyle", atname:"mathvariant", atval:"bold-italic",
		output:"mathbi", tex:null, ttype:AM.TOKEN.UNARY}
	);
});
MathJax.Ajax.loadComplete("http://resospace.nz/mjax_conf.js");
MathJax.Ajax.loadComplete("http://127.0.0.1/mjax_conf.js"); //well its going to be one of them !
For those those who are interested, my external config file species a style for bold, italics, for use with vectors, called by mathbi(xxx), and hbar is the symbol for the reduced Planck constant - naturally!

Custom JScript Functions

To generate some of the graphs (those illustrating the chemical kinetics for example), we needed to use some mathematical special functions. For example, The Lerch Transcendent, and the Exponential Integral. Javascript doesn't include these special functions as part of the generic language, and so we've implemented them here using their series expansions. Someone, somewhere, might find them useful - who knows...?

function sFact(num)
//The Factorial Function
{
	var rval=1;
	for (var i = 2; i <= num; i++)
		rval = rval * i;
	return rval;
}

function LPhi(z,s,a)
//The Lerch Transcendent Function
{
	var rval=0;
	for (var n = 0; n <= 5; n++){
		rval=rval+Math.pow(z,n)/Math.pow((a+n),s);
	}
	return rval;
}

//The Euler-Mascheroni constant, gamma
var eumnum=0.577215664901532860606512090082;

function Eix(x) {
//The Exponential Integral
	var tval;
	var n;
	var sum1=0;
	for (n = 1; n < 25; n += 1) {
		sum1=sum1+Math.pow(-1,n)*Math.pow(x,n)/n/sFact(n); //
	}
	tval=-eumnum-Math.log(x)-sum1;
	return tval;
}

Graphing

Graphs produced using flotr2 by humble software.

Sometimes I've noticed that graphs don't always display when I refresh a page, but then if I hold the Ctrl key whilst refreshing, it works. Maybe to do with caching the JS files?

To place the graph in the html, you put the container div anywhere, with the code <div id="graphcontainer"></div>

To utilise the flotr2 package, you must load the javascript file. I place the references to this at the end of the file, just before the closing </body> tag. The code below is used to produce a graph with two datasets.

<!--[if IE]>
<script type="text/javascript" src="examples/path/to/flashcanvas.js"></script>
<![endif]-->
<script type="text/javascript" src="../flotr2.min.js"></script>
<script type="text/javascript">
(function () {
var container = document.getElementById('graphcontainer'),
d1 = [], d2 = [], data, graph, t;

// Produce the two datasets, d1 and d2
for (t = 0; t < 5e5; t += 1000) {
	d1.push([t, Math.exp(-k1*t)]);
	d2.push([t, 1-Math.exp(-k1*t)]);
}

data = [{
	data: d1, label: 'A(t)'
	}, {
	data: d2, label: 'B(t)'
}];

// Draw Graph
graph = Flotr.draw(container, data, {
legend: { position: 'se', backgroundColor: '#D2E8FF'},
yaxis : { max : 1, min : 0 }
});
})();

</script>