madyn 0 Posted October 23 Background first, if you please: RadStudio 12.2, in C++ on Windows 11. Monitors status information from up to 4 microprocessor nodes using TTL to USB converters. Each node is a separate board with its own interface. Ideally, I use a serial port package in C++ which (non-blocking) reads a package and updates a data panel on the display. Decoding the packet is no problem, getting it, is. Communication is in ASCII encoded packets to avoid premature terminating zeros, so string reads will work. Tried the APRO interface, but documentation seems to be lacking, with lots of features in the packages I don't need and no basic startup information. Tried the BOOST rabbit hole, which I somewhat got to work (gotta love the documentation (if any)). and then lost the solution. It seems to be blocking only, which I could tolerate if I could create a task. I could do this with a microprocessor, it would simply mirror the drivers in the hardware, using FreeRTOS tasks to read each port (one task = 1 port), and tasks can be blocking without a problem. Anybody know of a well documented serial package that can do non-blocking reads, C++ compatible? Then I need to do multiple threads, haven't looked at that yet in C++. I don't really have a problem with C++, but the add-ons are a problem. Got the UI (more or less customizable) up and running, custom buttons (made from panels) can be enabled/disabled with different text for pressed, different colors when active. so the C++ is not a problem. Thanks in advance Harvey Share this post Link to post
DelphiUdIT 176 Posted October 23 (edited) There are lot of packages for Delphi and C++, look at GETIT from IDE and search for: 1) asyncpro or 2) serial I have been using this component for a long time too: https://sourceforge.net/projects/comport/files/comport/4.11/comport411f.zip/download To read the Help you must use an old WinHelp executable. You can discharge it from Microsoft (I had ones for Windows 7 and is working in Win 11). Bye Edited October 23 by DelphiUdIT Share this post Link to post
madyn 0 Posted October 24 SERIAL give me a program that is both commercial and one that Norton (bless it's little heart) rejects because it tried to modify a protected file. I'm looking at asyncpro, because I know now how to find open ports (which async pro doesn't do, and I needed). If it knows how to actually read data I may do that. My basic scheme is to scan ports, then select which port is which (having retrieved the open ports); then allow selecting a port connecting to which board (you'd have to see the overall setup for it to make real sense); then assign that to a node panel which reports the results from a board assigned to a particular com port and thus a particular board. Harvey Share this post Link to post
Jirka52 2 Posted October 24 You can create trhread with TComport for communication with your device. Component is here, install it and use it in your code. Comport is Delphi component, but it works also in C++ Builder, I have been using it in C++ Builder more than 14 years. https://sourceforge.net/projects/comport/ Share this post Link to post
DelphiUdIT 176 Posted October 24 2 hours ago, Jirka52 said: You can create trhread with TComport for communication with your device. Component is here, install it and use it in your code. Comport is Delphi component, but it works also in C++ Builder, I have been using it in C++ Builder more than 14 years. https://sourceforge.net/projects/comport/ I suggested the same in my previous post 1 Share this post Link to post
Angus Robertson 574 Posted October 24 I've been using Async Pro for over 20 years, well documented, the original version was sold in a box with a book. Now I install it from GetIt. But I updated the TApdCustomComPort.InitializePort method so it can open COM ports by name instead of simple numbers, since many physical and virtual COM ports have more complex name than COM1 and COM2, like CNCA0. I have a free component that locates and lists COM ports, https://www.magsys.co.uk/delphi/maghardware.asp Angus 2 Share this post Link to post
madyn 0 Posted October 25 OK, spent some time getting things to (somewhat) work. Comport scanning works, and returns an ID of what the friendly name of the comport happens to be. I went with APRO since it was available and installed. Not sure exactly how to install a delphi package in C++ builder, but for now, that doesn't seem to be needed. Finally got the idea of how to specify packet start and stop, (documentation is for Delphi), and I was overcomplicating things. This is the data structure, and it is being sent (terminal program says so). struct SYSTEM_SUPERUSER_packet_data { char SOH; // start of header = begin packet char id[8]; // 32 bits of processor ID code hex char STX; // STX = beginning of block union SUPERUSER_BLOCK block; // block data in message (hex( char ETX; // ETX = end of block char checksum[4]; // checksum, should add to zero; char EOT; // end of transmission = end packet char CR; char LF; }; // super_packet.p.EOT = 0x04; // super_packet.p.ETX = 0x03; // super_packet.p.SOH = 0x01; // super_packet.p.STX = 0x02; // super_packet.p.CR = 0x0D; // super_packet.p.LF = 0x0A; // this is sent to the computer as a data packet union SYSTEM_SUPERUSER_packet_type { struct SYSTEM_SUPERUSER_packet_data p; uint8_t b[sizeof(struct SYSTEM_SUPERUSER_packet_data)]; }; Problem now is that the ApdDataPacket component doesn't work all the time. the ApdDataPacket1Packet code does not always get executed, things get ignored. Triggers are the SOH and the EOT. Any suggestions? Harvey Share this post Link to post
Angus Robertson 574 Posted October 25 I just use the OnTriggerAvail event to receive all data available, add it to a buffer, locate my packet, remove from buffer, repeat. More code that, but more reliable, particularly if the packet can contain random binary data, like your triggers. Angus Share this post Link to post
madyn 0 Posted October 25 OK, got this working. Thanks for the help here, I added a circular buffer so I always have room. Things I needed to know (and are apparently true) On trigger apparently fires once per character Packet decoding is not all that reliable for me the circular buffer uses std::optional, which is a whole another world to deal with until you understand it APro's documentation is lacking, it would be nice to have had C++ documentation it would be nice to have more details on how things work The code I ended up with follows, in case anyone has the same need: // client node panel[x] owns circular buffer void __fastcall TForm1::ApdComPort1TriggerAvail(TObject *CP, WORD Count) { uint8_t buffer[256] = {0}; int i; std::string data; ApdComPort1->GetBlock(buffer,Count); i = 0; while ((buffer[i] != 0) && (i < 250)) { // put chars in circular buffer ClientNodePanel[0]->NODE_buffer.put(buffer[i]); // packet ends with linefeed if (buffer[i] == 0x0A) { // end of packet, copy data into data structure int j = 0; while (!ClientNodePanel[0]->NODE_buffer.empty()) { // data as stored in circular buffer is in std::optional std::optional<uint8_t> gchar = ClientNodePanel[0]->NODE_buffer.get(); // actual value read, append to data string for memo display data.append(1,gchar.value()); // copy to binary overlay of data structure superuser_packet[0].b[j++] = gchar.value(); } // display Memo1->Lines->Add(data.c_str()); // update display with decoded data ClientNodePanel[0]->update(superuser_packet[0]); } i ++; } } Comments welcome: Harvey Share this post Link to post