Study of the BlackBox Component Builder

Usage of the framework, compiler and tools
User avatar
Marcel Kollenaar
Posts: 16
Joined: Mon Jul 26, 2021 1:33 pm
Location: Enschede, The Netherlands

Study of the BlackBox Component Builder

Post by Marcel Kollenaar »

Hello,

To study something new you must have a goal. Studying without a goal is difficult. So after a while reading, reading and reading I came up with 2 ideas.
  • 1 Building a Question and Answer application.
    2 Building a tool to read the data of my TFA temperature/hygrometer
Ad 1
This is a little too complex project but I'll see how far I will come. A simple description: There are 2 stages. An edit stage by the question builder and an fill stage by a user. Someone can start with a text with a question and formulates answers. There must be minimal 2 answers, a standard and actual answer. However the list can contain e.g. 10 answers. The answer can be an answer on its own but the answers can also be used for a next answer. For example: Question 1 is a question about the size. There are 3 possible answers: "standard", "small", "large". The second questions depends on question 1. If question 1 is answered with "standard" the next answers are possible: "left" or "right". If the answer on question 1 was "large" the answers on question 2 are "up" or "down". These are just examples.

The interesting possibility I read is that BB us using RTF documents and therefore a lot is possible. I was thinking building text views with active position in the text. You write the question and when you come to the point of the answer you can insert a dropdown list of answers. In runtime a user can select a question at that point by a click on the listobject. The answers are depending on already answered question. So the question builder can select a previous question and answer and list the answers for that question and answer. You can also exclude previous answers from the answer list of the next question. Pretty simple. I also want to add dependent pictures to the text. Picture A is shown when the question is answered with "1" and picture B is shown when the question is answered with "2". Other options must be "tables".

Ad 2
I have a 16 year old datalogger and it is still working perfect with 5 external stations. I used it once for trimming the floor heating valves in my house. However it has a "serial" port. My new computer has no serial port anymore, only USB and the software of the logger was XP level. I asked 16 years ago TFA Dostmann for the communication protocol but they refused to reveal it. Now there are several hacks created by other tinkers. At that time I discovered that it used the serial COM RS-232/V24 and just only the handshake lines DTR/DSR (SPI-SCL), RTS/CTS (SPI-SDA) were used to read the device. There is logic inside the TFA that split/join the SCL/SDA signals of an AT24C256 memory. It was a bit banged SPI imitation and I wrote a tool in PureBasic (great language). Due to the fact that I have only USB now I have to use another option. Using an Arduino to read the memory chip with SPI and send it serial to my PC using BlackBox V24 at the receiver side. 1000 values from 5 sensors, temp, humidity and date.
Temperature and hygrometer
Temperature and hygrometer
Another project still on breadboard:
  • Dust sensor
    CO2 sensor
    Hygrometer sensor
    Pressure sensor
Breadbord overview
Breadbord overview
TFT
TFT
I hope this gives you an idea of my interests.

[Edit: some textual changes: I2C > SPI]
User avatar
Ivan Denisov
Posts: 362
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

Re: Study of the BlackBox Component Builder

Post by Ivan Denisov »

Very interesting.
All can be done with BlackBox.
Please, ask questions if there are any troubles.
User avatar
Marcel Kollenaar
Posts: 16
Joined: Mon Jul 26, 2021 1:33 pm
Location: Enschede, The Netherlands

Re: Study of the BlackBox Component Builder

Post by Marcel Kollenaar »

From the Ad 2 above, the serial comm part is done. It was a nice journey, albeit that I had an archaïc feeling.

I did a kind of copycat from https://learn.sparkfun.com/tutorials/co ... essing/all and instead of using Processing I used BlackBox. The Arduino code looks like this:

Code: Select all

// Source: https://learn.sparkfun.com/tutorials/connecting-arduino-to-processing/all
int count = 0;
void setup() 
{
  //initialize serial communications at a 9600 baud rate
  Serial.begin(115200);
}

void loop()
{
  //send 'The quick brown fox jumps over the lazy dog.' over the serial port
  Serial.println("The quick brown fox jumps over the lazy dog.");
  //wait 100 milliseconds so we don't drive ourselves crazy
  delay(100);
}
The BB-code is:

Code: Select all

(* 
   Date: 22-8-2021
   Uses: Original Arduino UNO attached to COMM port 5. In this case it is an virtual port via USB.
   The Arduino is sending the string "The quick brown fox [...]" via the serial port.
   BlackBox is reading the COMM port and prints the characters in the log. 
   At a certain point BlackBox is getting unresponsive when log screen has to scroll. In the end all lines are
   written in the log. *)

MODULE Hw00ReadArduino;

	IMPORT StdLog, CommV24;

	PROCEDURE ReadV24*;

	VAR serialbyte: BYTE;       (* byte received by CommV24 port *)
			c: CommV24.Connection;  (* Comm connection *)
			avail, i: INTEGER;      (* Contains buffer data? *)

	BEGIN
		CommV24.Open("COM5", 115200, {}, c);                   (* 8N1 default *)
		CommV24.SetBuffers(c, 1024, 1024);
		ASSERT( c # NIL);											                (* If connection is empty then fail *)
		avail := CommV24.Available(c);                         (* Check if there are any bytes in the receive buffer *)
		StdLog.String("Avail: ");StdLog.Int(avail);StdLog.Ln;	(* Show the amount *)
		i := 0;
		LOOP
			IF (avail > 0) THEN
				CommV24.ReceiveByte(c, serialbyte);
				IF (serialbyte > 31) & (serialbyte < 127) THEN     (* Show only printable characters *)
					StdLog.Char(CHR(serialbyte));
				ELSIF (serialbyte = 10)  THEN
					StdLog.String(" - ");StdLog.Int(i);StdLog.Ln;    (* Line number and new line *)
					INC(i); IF i = 1000 THEN EXIT END;
				END;
			END;
			avail := CommV24.Available(c); (* Check again if there are any bytes in the receive buffer *)
		END;
		StdLog.String("---------------------- DONE 1000 lines --------------"); StdLog.Ln;	(* The end *)	
		CommV24.Close(c)
	END ReadV24;
END Hw00ReadArduino.

"Hw00ReadArduino.ReadV24"
At a baud rate of 9600 it was a little "unstable" but at a baud rate of 115200 it ran smooth. At some times BB was not responding and if I clicked on the screen it became gray/white. At first I thought BB crashed but at the end all the data was shown after a flash/refresh when the code exits. Maybe that background processes were responsible for this because it appeared most of the time when the Log screen has to scroll.

The only strange thing is that if the device is not attached to the USB-port BB exits with a TRAP 0. It should be possible to show the user a message that no device is attached and not a TRAP message. I found no solution for it, does anybody have an idea to catch the TRAP when the CommV24.Open() fails?
luowy
Posts: 87
Joined: Thu Dec 17, 2015 1:32 pm

Re: Study of the BlackBox Component Builder

Post by luowy »

Marcel Kollenaar wrote:The only strange thing is that if the device is not attached to the USB-port BB exits with a TRAP 0.
after "CommV24.Open" you should check

Code: Select all

IF c # NIL THEN 

please refer to https://forum.oberoncore.ru/viewtopic.p ... ort#p21199 for more info about V24
At first I thought BB crashed but at the end all the data was shown after a flash/refresh when the code exits. Maybe that background processes were responsible for this because it appeared most of the time when the Log screen has to scroll.
use StdLog.OpenBuffer and StdLog.CloseBuffer to collect some Log message in once , use Service.Action if the task need a long time to run
User avatar
Marcel Kollenaar
Posts: 16
Joined: Mon Jul 26, 2021 1:33 pm
Location: Enschede, The Netherlands

Re: Study of the BlackBox Component Builder

Post by Marcel Kollenaar »

Hello luowy,

Thanks for all the information. Great source of WinAPI information too from Ivan Denisov.

The test for NIL works like a charm and the next code in the TestLink.odc for conversion from string to byte helped me also. I was hitting a wall there when I tried to use the stringreader, got error after error at the array of bytes and array of chars.

Code: Select all

WHILE (i < c) & (str[i] # 0X) DO
    bytes[i] := SHORT(SHORT(ORD(str[i])));
    INC(i)
END;
The Service.Action is something I have to study. I saw it yesterday in a post related to another problem. 12 years ago I used a serial comm OVERLAPPED construction to read the TFA to overcome long freezing of the application. BB is new to me and I have to find my way in it.

I read a question in the Russian forum about accessing virtuals port with BB. Maybe it is already answered because it is an old post but nevertheless, yes virtual ports do work in BB. The Arduino I use has an virtual COMM5 port.
User avatar
Ivan Denisov
Posts: 362
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

Re: Study of the BlackBox Component Builder

Post by Ivan Denisov »

Please take a look at this example of using Services.Action for reading data

Code: Select all

MODULE NovaUartMonitor;

	IMPORT Log := StdLog, CommV24, Services;
	
	TYPE
		Action = POINTER TO RECORD (Services.Action) END;
		
	VAR
		p: CommV24.Connection;
	
	PROCEDURE Open* (port: ARRAY OF CHAR; speed: INTEGER);
	VAR a: Action;
	BEGIN
		IF p = NIL THEN
			CommV24.Open(port, speed, {}, p);
			IF p = NIL THEN
				Log.String("failed"); Log.Ln;
			ELSE
				Log.String("connected"); Log.Ln;
				NEW(a);
				Services.DoLater(a, Services.now)
			END
		ELSE
			Log.String("already connected"); Log.Ln;
		END
	END Open;

	PROCEDURE Close*;
	BEGIN
		IF p # NIL THEN
			CommV24.Close(p);
			p := NIL;
		ELSE
			Log.String("there is no connection"); Log.Ln;
		END
	END Close;

	PROCEDURE Check;
	VAR len, i: INTEGER; data: ARRAY 1024 OF BYTE;
	BEGIN
		IF p # NIL THEN
			len := CommV24.Available(p);
			IF len > 0 THEN
				CommV24.ReceiveBytes(p, data, 0, len);
				FOR i:= 0 TO len - 1 DO
					IF (data[i] = ORD(0AX)) OR (data[i] = ORD(0X)) THEN
						Log.Ln
					ELSE
						Log.Char(CHR(data[i]))
					END
				END
			END
		ELSE
			Log.String("no connection"); Log.Ln;
		END
	END Check;

	PROCEDURE (a: Action) Do;
	BEGIN
		IF p # NIL THEN
			Check;
			Services.DoLater(a, Services.Ticks() + 100)
		END
	END Do;

	PROCEDURE Send* (str: ARRAY OF CHAR);
	VAR bytes: POINTER TO ARRAY OF BYTE; i: INTEGER;
	BEGIN
		NEW(bytes, LEN(str$) + 1);
		FOR i:=0 TO LEN(str$) DO
			bytes[i] := SHORT(SHORT(ORD(str[i])))
		END;
		CommV24.SendBytes(p, bytes, 0, LEN(bytes));
	END Send;

END NovaUartMonitor.

^Q "NovaUartMonitor.Open('COM5', 19200)"

^Q "NovaUartMonitor.Close"
User avatar
Marcel Kollenaar
Posts: 16
Joined: Mon Jul 26, 2021 1:33 pm
Location: Enschede, The Netherlands

Re: Study of the BlackBox Component Builder

Post by Marcel Kollenaar »

Thanks Ivan. I'm on it. Looks promising.
luowy
Posts: 87
Joined: Thu Dec 17, 2015 1:32 pm

Re: Study of the BlackBox Component Builder

Post by luowy »

Marcel Kollenaar wrote:I was hitting a wall there when I tried to use the stringreader, got error after error at the array of bytes and array of chars.
in the CP language, the CHAR is 16bit(unsigned short), SHORTCHAR is 8bit(unsigned char), the BYTE is 8bit (signed char) , the conversion between them use builtin function: ORD() , CHR(), SHORT():

ch := CHR(b);
ch :=sch;
sch := SHORT(ch);
sch := SHORT(CHR(b));
b := SHORT(ORD(sch));
b := SHORT(SHORT(ORD(ch)));

press the F1 get "Language Report" for more

for embeded project, use SHORTCHAR instead BYTE is good choice;
use ORD() to convert to BYTE, also you can use SYSTEM.VAL() to cast:

Code: Select all

	PROCEDURE Test;
		TYPE A=ARRAY 256 OF BYTE;
		VAR str:ARRAY 256 OF SHORTCHAR;
		
		TYPE D=ARRAY OF BYTE;
		ss:POINTER TO ARRAY OF SHORTCHAR;
		i,c:INTEGER;
		conn:CommV24.Connection;
	BEGIN
		CommV24.SendBytes(conn, SYSTEM.VAL(A, str), 0, i);
		CommV24.ReceiveBytes(conn, SYSTEM.VAL(A,str), 0, c);
		CommV24.SendBytes(conn, SYSTEM.VAL(D, ss^), 0, i);
		CommV24.ReceiveBytes(conn, SYSTEM.VAL(D,ss^), 0, c);
	END Test;
User avatar
Marcel Kollenaar
Posts: 16
Joined: Mon Jul 26, 2021 1:33 pm
Location: Enschede, The Netherlands

Re: Study of the BlackBox Component Builder

Post by Marcel Kollenaar »

Thanks luowy,

I'm a bit spoiled with Visual Basic for Application :D. A lot is done "automatically" under the hood when it comes to string conversion or using functions like VAL() or Cstr().

Your help is appreciated.
User avatar
Marcel Kollenaar
Posts: 16
Joined: Mon Jul 26, 2021 1:33 pm
Location: Enschede, The Netherlands

Re: Study of the BlackBox Component Builder

Post by Marcel Kollenaar »

Ivan Denisov wrote:Please take a look at this example of using Services.Action for reading data
I had only to change the baud rate and it ran flawlessly. Now I'm extending my code with this Services.DoLater concept to understand it.
Post Reply