• Analyze serial port activity

    Serial Port Monitor can connect to a COM port, even if it is already open by some application, and immediately start monitoring it. All data passing through the monitored COM port will be displayed in our monitoring program. Since everything is recorded in real time, you will be able to spot problems instantly. To compare data, there is a function of synchronized selection of the same IRPs in different views.

    In addition, you can redirect all monitoring data to a specified file or copy all recorded data to the clipboard. Serial Port Monitor gives you the ability to intercept and record all serial port input/output control codes (IOCTLs), monitor all their data and parameters. You can save any monitoring session and load it next time if necessary.

  • Monitor multiple ports within the same session

    The Serial Port Monitor has a unique functionality monitoring multiple COM ports at the same time. Now you can collect data on how applications interact with two or more ports and in parallel with multiple devices within the same session. The received and sent monitoring data will be presented (recorded) in a separate log in the order in which they are received, which greatly simplifies the analysis.

  • Different options for viewing received data

    You can view monitoring data in 4 modes at once: table, row, dump or terminal, each of which offers a different way of presenting recorded serial data. Serial Port Monitor allows you to select monitoring filters, thus saving you time and allowing you to monitor only the events of interest. In the settings, you can select the data to display: binary, ASCII, configure the port. Any display settings can be applied directly in the current monitoring process.

  • Emulate data transfer to a serial device

    You can send data to various formats(string, binary, octal, decimal, hexadecimal, mixed) to the monitored serial port as if they were sent directly by the controlled application using the Serial Port Monitor Terminal Mode feature. In this way, you can monitor the response of the controlled serial device to some special commands and data.

  • Full support for Modbus data protocol (RTU and ASCII)

    With the help of new Serial Port Monitor filters you will be able to decrypt and analyze Modbus data. The program will help not only establish a connection between RS485/422/232 devices, but also conduct an effective analysis of passing data.

  • Replay and compare monitoring sessions

    Serial Port Monitor provides the unique ability to replay a session from an application to a port for best analysis ongoing processes. You will be able to observe the reaction of the serial port to the passage of the same data, thereby increasing the monitoring efficiency. You also have the option to compare multiple monitoring sessions and automatically track the difference between them.

Today computer viruses literally flooded the world and roam freely on the Internet, so when it comes to ports, most users often think of logical ports, which in network technologies such as TCP / IP or UDP, are used to organize communication channels, and forget about physical ports for connecting external devices. However, even to connect printers, mice and keyboards are increasingly used high speed USB ports and less and less often - the good old COM and LPT (serial and parallel ports). However, the latter are available even in the most modern computers, and, perhaps, the time has come to use them for some other purpose (say, to control one or another specialized device).

In order to track the exchange between a computer and some device, port analyzer programs are just what is needed.

Of course, there are also special devices (probes) on sale for monitoring analog and digital signals (including USB, LPT and COM analyzers), however, like any professional equipment they are quite expensive.

Computer Serial Port Control (COM)

One of the serial port analysis programs was written by Valery Kovtun (http://valery-us4leh.narod.ru/). Thanks for a great tool!

The program is called Com Port Visual Control (http://valery-us4leh.narod.ru/ComVC.html), is distributed free of charge and is intended for visual control, documenting data exchange and studying the processes occurring in the UART transceiver during the operation of applications using COM -port personal computer. This program operates in Windows environment 9x/Me/NT/2000/XP and performs continuous viewing (monitoring) of all registers of the UART chip. The controller has an 8x8 format (eight registers of eight bits) and for each register it independently displays: the current state (simultaneously in decimal and hexadecimal format), as well as the logical state. In addition, the program can write values ​​to registers (also in both decimal and hexadecimal formats) and manage the logic state accordingly. In addition, it monitors changes in registers and maintains a protocol (LOG) according to the commands of the transceiver of the UART chip, and also keeps a protocol of received and transmitted data at the level of machine codes. After work, the program views and saves LOG-files and can search them for the necessary information.

Com Port Visual Control has a built-in transceiver for standard setting port modes: data bits, stop bits, speed, parity, error control, the ability to receive and transmit text data and modem commands, as well as an indicator for monitoring the active state of UART commands (17 basic commands are supported). In addition, computer ports are monitored with simultaneous display of a group of registers and status bits, and a protocol is maintained for changing data in the base register.

Among such programs are free utility ComLite32 by Realtime Communications (RTCOMM, http://www.rtcomm.com/), written for Windows 95, and its premium paid version, ComLab32 (http://www.rtcard.com/comlab32.html).

These programs are powerful real-time communication analyzers that allow you to explore the exchange over a COM port and understand how a particular device works, even if there is no documentation for it. The program has a convenient and intuitive clear interface, facilitating the monitoring of the exchange, the management of I / O ports and the provision of detailed online documentation.

ComLite32 and ComLab32 programs work with RS-232, RS-422, RS-485 and RTX485 ports (with the last port being read-only) and allow you to communicate with these ports in both directions. System requirements ComLite32 programs are minimal: only 8 MB RAM, 6 MB disk space and at least one device that works with a serial port (including laptop PCMCIA modems).

And finally, I would like to note the Advanced Serial Port Monitor and Advanced Serial Data Logger programs from AGG Software (http://www.aggsoft.ru). Advanced Serial Data Logger processes data received via RS-232 and transmits it to excel file, Access, or some other Windows application. The program provides the ability to collect data from any device in real time, as well as receive and transmit data via the RS-232 interface or via the RS-485 interface if a hardware converter is available. Advanced Serial Data Logger collects data from the serial port, processes it according to the needs of the user, extracts blocks of data from the general stream, and then transfers the data to any Windows or DOS application - by pressing the appropriate keys in the application window. Data is transferred via DDE (Dynamic Data Exchange), ODBC, OLE, etc. This solution can be used in automated data collection systems or PBX call analysis systems.

Advanced Serial Data Logger can also send requests and commands via serial port to directly control devices via ASCII (default) or MODBUS protocol. Thus, the Advanced Serial Data Logger program becomes an I/O server. As for the management and settings, they are very simple and intuitive. Additional programming for data acquisition is not required.

In addition, Advanced Serial Data Logger can work as a service under Windows NT/2000/XP/2003, which will start at system boot and write data from the serial port to a file on disk or to other specified locations even before the user logs in to the system (and will continue to function after the end of the user session).

The program has the ability to run multiple copies on the same computer, so that multiple ports can be logged at the same time.

As for the Advanced Serial Port Monitor program, it can be useful for both novice users and professionals.

Advanced Serial Port Monitor can be used both to monitor data transmission by other applications, and to send and receive data through the computer's serial port (RS-232). The program provides various ways saving data to a file or visualizing them on the monitor screen.

Thus, you can work with any devices that work via the RS-232 or RS-485 (RS-422) interface with the appropriate converter. You will observe the exchange of data between any Windows application and external devices connected to the serial port. This could be either a measuring device, or a home radio, or another computer connected via a z-modem or null modem cable.

Advanced Serial Port Monitor supports full duplex operation, that is, you can monitor the exchange in both directions without using other programs and without interrupting other applications. All information passing through the serial port is displayed on the screen in a special window and can be written to a file. All displayed parameters can be changed during operation. At the same time, the program supports two modes - automatic and manual, that is, you can send data by pressing the "Send" button or they will be sent automatically at a certain interval (from 10 to 10,000 ms).

With the help of additional modules, you can not only receive data or send commands, but also emulate the work of some specific devices, and in the observer (interceptor) mode - just monitor the data exchange between an external device connected to the serial port and some Windows application. And finally, Advanced Serial Port Monitor has its own built-in scripting language, with which you can run the program with preset options and actions, as well as execute commands from modules.

Computer Parallel Port Control (LPT)

Valery Kovtun has another useful communication program - LPT 3D Hard Analyzer. The program is a graphical storage analyzer-oscilloscope designed to capture digital signals and protocols of devices connected to the parallel port of a computer in Windows 95/98/Me/NT/2000/XP.

LPT 3D Hard Analyzer works through the LPT port and allows you to analyze five input lines (channels) and 12 output channels (that is, control digital signals from computer) in SPP mode or manipulate four outputs and 14 input parameters in EPP mode. Bidirectional EPP parallel port mode is available on almost all computers released after 1993. Sometimes, however, it is not enabled by default in the BIOS (this must be checked and, if possible, enabled).

When working in the oscilloscope mode, the program remembers all 17 graphs (lines), the depth (displayed length of the graph in time) is limited only by the free memory of the computer (and taking into account the paging file in OC Windows, this will be several hundred megabytes). There is also an option to automatically save each new page in graphic format.

Analyzer-oscilloscope LPT 3D Hard Analyzer plots data changes in two-dimensional and three-dimensional form, and also shows two independent diagrams: a 17-channel oscilloscope (bit per channel) and a graph of port registers (input, output, control). There is an adjustment of the analysis speed, and the total number of cycles for the entire period of progress of the graph is displayed. You can also program the number of cycles with the ability to copy graphs to memory (the plotting depth is limited only by the available RAM computer). The program has tools for saving system resources while reading data from high-speed devices connected to the LPT port and synchronized with it by this program (that is, it can be used on relatively weak computers). When you turn off the graphical display mode, graphics are copied only to the computer's memory - as a result, the speed of the program increases tenfold. At the end of the analysis, the graph is viewed in the same way as if it were switched to the graphical display mode. Scrolling of graphs is carried out smoothly and page by page ( right click mice). There is a flexible setting of the speed and scrolling step, as well as the ability to automatically compress the entire chart within one page. Snapshots of the state of the selected graph page can be stored in BMP formats and WMF (Windows metafile) or set automatic saving to a separate file for each new page. To view the package has a built-in browser graphic files.

The port control module is based on the core code of another program by Valery Kovtun - XP LPT, which uses the LPT WDMIO I/O driver.

The XP LPT program is designed to control the parallel ports of a computer from Windows 9x/2000/XP and has the following features:

  • performs automatic registration of the driver in Windows XP as a system administrator;
  • leads automatic check established ports;
  • performs simultaneous reading of data, control and status registers of the selected LPT port;
  • displays the contents of the registers simultaneously in different formats (decimal and hexadecimal), which eliminates the need for recalculation.

This program has available source, description, as well as examples of creating programs to control external devices through a parallel port based on this solution.

As we have already mentioned, the program functions through the LPT WDMIO I / O driver and is designed specifically for training and debugging self-produced programs for controlling external devices via a parallel port in a Windows environment.

Valery Kovtun also created the PortControl program, which is used to control a parallel port with a 17-bit analyzer of the communication protocol for devices using the computer's LPT port. The program is written for the Windows OS family and has the following features:

  • there are three independent channels that can be used to enter the port address (register), automatically read data from the port, write data to the port in decimal and hexadecimal format, and display data in bite, word and Dword formats;
  • the status of each of the 17 bits of the LPT port is displayed and the output bits are controlled;
  • nine programmable port/data memory banks available;
  • there is a 17-channel analyzer-oscilloscope of the logical state of each bit with the ability to set the speed of analysis (in time), synchronization by any of the 17 bits - as per high level(1), and low (0), as well as a counter of transmitted data for each bit and many other functions for easy checking and tuning digital devices connected to a computer.

This program can be used both as a digital multichannel oscilloscope and to control external devices via a computer.

Port analysis and management programs may have various applications. First, they can be used to detailed check and testing the performance of the parallel port of the computer, for example, to check the performance of the LPT port and the system as a whole using the Test out mode. Moreover, it is convenient to observe all operations in time using the built-in 17-channel analyzer-oscilloscope with the possibility of flexible adjustment for a certain type of measurement.

To analyze high-speed digital data transmission buses connected to a computer of various radio-electronic devices and microcircuits, a computer with a processor frequency of at least 300 MHz is recommended. But for low-speed devices, more than weak computers under Windows control 95.

Secondly, analyzer programs can be used to control, analyze, configure, develop, test and repair digital radio electronic circuits ( individual modules, blocks, control buses, frequency synthesizer control protocols, control elements digital indicators, ROM programmers, etc.), that is, where widely used digital microcircuits, which form control signals and somehow react to them.

Thirdly, port analyzer programs can simply be used to read exchange protocols. And by synchronizing the data bus and the control signals of information storage and identification devices, you can even read service signals and / or access passwords encoded in sequences of zeros and ones. In general, these programs are designed to empower the radio amateur, electronics engineer, or design engineer. A visual study of the operation protocols of radio electronic devices can also be useful when developing your own software controlled by different controllers.

Fourthly, analyzer programs will be very useful for repairing office equipment that somehow uses the computer's parallel port - various printers, scanners, cash registers and other devices.

Fifthly, the listed programs will be useful for novice programmers. For example, if you decide to write small program to control certain external devices through a parallel port, it will be very convenient for you to visually observe the algorithm of your program in the PortControl multifunctional interface. As a result, you will be able to detect and eliminate the mistakes made in time without using measuring instruments at the output of the port and without interfering with the circuitry of the controlled device.

And finally, for the parallel port, Valery Kovtun suggests useful program PinRegistrator, designed to monitor and register the logical state of the LPT port bits. The program was written under Windows 95/98/Me and logs the state of the parallel port automatically or manually.

Computer USB port control

The aforementioned company AGG Software has programs designed to analyze and monitor USB ports, buses, controllers and devices. For example, Advanced USB Monitor (http://www.aggsoft.ru/usb-monitor/index.htm) allows you to capture, analyze, view and process USB traffic for efficient debugging and testing of USB devices. Devices that meet all specifications are supported: UHCI- (old USB devices 1.x devices operating at speeds up to 1.5 Mbps), OHCI- (next generation USB 1.x devices operating at speeds up to 12 Mbps) and finally USB 2.0 EHCI devices (operating at speeds up to 480 Mbps). Advanced USB Monitor allows you to expand the laboratory toolkit for both USB device developers and advanced users.

Advanced USB Monitor can display transmitted data packets in a readable way, decode descriptors, detect packet errors, and measure device performance. During capture, data packets can be displayed in real time, allowing you to monitor the status of devices. Data packets are saved in chronological order and contain full information about addresses and endpoints. This makes it very easy to identify, filter and search for packets. The program provides several levels of detail when displaying data. Fast decoding of USB traffic makes it possible to work even with such high-speed devices like USB drives or USB cameras. Moreover, the capture, monitoring and recording of captured data occur in real time. With Advanced USB Monitor, you can view traffic as it occurs, and simultaneously for a range of USB devices, with multiple monitoring windows open at the same time.

Using a capture kernel driver with support for WDM, WMI, Power Management and PNP allows you to achieve full compatibility with operating system and USB devices for maximum performance.

The program also gives you the ability to measure the performance of any USB device. Advanced USB Monitor easily navigates the topology of USB devices and gets a detailed technical information about devices such as USB drives (interfaces, endpoints, registry information, class information, and more). At the end of the study, you can get a ready-made report on connected devices and USB traffic, and at the end of the study, print it out on a printer. In addition, the program has advanced functions for exporting data to PDF formats, XML or Microsoft Word, which allows not to limit the data post-processing process to only this one program.

USB oscilloscopes (http://www.usb-osc.narod.ru/) work on the same principle as the above-described analyzers-oscilloscopes for the parallel port. The USB oscilloscope is primarily intended for radio amateurs who, by the nature of their work, are faced with the need to analyze low-frequency analog signals, register long-term slowly changing processes, and also examine binary signals from various devices. In addition, the USB oscilloscope can be used as a simple two-channel voltmeter for voltages in the +/-20 V range, a frequency counter for signal frequencies up to 50 kHz, or a probe with an audible alert.

So, the USB oscilloscope provides the following modes of operation:

  • two-channel oscilloscope (marker measurements, synchronization, signal voltage and frequency measurements, filtering, etc.);
  • two-channel spectrum analyzer (marker measurements, various window functions, filtering, etc.);
  • two-channel recorder (marker measurements, signal recording for several tens of hours, etc.);
  • 8/16-channel logic analyzer (marker measurements, synchronization, skipping a given number of pulses, searching for a given logical combination, decoding interfaces UART, SPI, I2C, 1-Wire, etc.);
  • 8-channel logic generator (signal table setting or direct construction of timing diagrams with the mouse, etc.).

In addition, the USB oscilloscope allows you to save the results of all measurements in the form of a vector or raster drawing for later import into other programs or for saving in a file for later analysis. The results of all measurements can be printed, copied to the clipboard, as well as set events and accompany them with a sound commentary. Various digital filters can be calculated and analog filtering and oscilloscope timing smoothing can be performed. The device allows you to display statistics for all channels of the logic analyzer and generator.

However, USB oscilloscopes are no longer just programs, but devices made in the form of external units with a USB interface and accompanied by service providers. software modules. That is, it is a whole universal measuring complex, consisting of a switching attachment and a computer. By the way, you can update the firmware of such a device via a USB bus, which allows you to supplement the capabilities of the device with any custom functions.

Such devices are produced by the Ukrainian company Da-Labs (http://www.da-labs.com/) and Russian company"Trade-M" (http://motor-master.ru/index.htm/). The price of a set of a Russian company is 1850 rubles. excluding delivery.

So, armed with the necessary tools, we now have the opportunity to independently write control programs for various external devices using any ports of our computer.

Serial ports are loved by developers for their ease of maintenance and use.

And of course, writing to the console of the terminal program is all good, but I want my own application, which, by pressing a key on the screen, performs the actions you need;)

In this article I will describe how to work with com port in C++ language.

The solution is simple, but for some reason a working example was not found immediately. For sim I save it here.

Of course, you can use cross-platform solutions like QSerial - a library in Qt, I probably will, but in the future. Now we are talking about "pure" Windows C++. We will write to visual studio. I have 2010, although this does not play any role ...

Create a new console Win32 project.

Include header files:

#include #include using namespace std;

We declare a com port handler:

HANDLE hSerial;

I do it globally so I don't have to worry about pointers when passing it to functions.

int _tmain(int argc, _TCHAR* argv) (

I can't stand the Windows style of programming. They called everything in their own way and sit rejoicing ...

Now the magic of declaring a string with the port name. The matter is that it is not able to transform char itself.

LPCTSTR sPortName = L"COM1";

Working with serial ports in Windows works like with a file. Opening the first com port for writing/reading:

HSerial = ::CreateFile(sPortName,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

Checking the functionality:

If(hSerial==INVALID_HANDLE_VALUE) ( if(GetLastError()==ERROR_FILE_NOT_FOUND) ( cout<< "serial port does not exist.\n"; } cout << "some other error occurred.\n"; }

Now you need to configure the connection parameters:

DCB dcbSerialParams = (0); dcbSerialParams.DCBlength=sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) ( cout<< "getting state error\n"; } dcbSerialParams.BaudRate=CBR_9600; dcbSerialParams.ByteSize=8; dcbSerialParams.StopBits=ONESTOPBIT; dcbSerialParams.Parity=NOPARITY; if(!SetCommState(hSerial, &dcbSerialParams)) { cout << "error setting serial port state\n"; }

On msdn, it is advised to first get the parameters, and then change them. We are still learning, so we do as requested.

Now let's declare the string that we will pass and the variables necessary for this:

Char data = "Hello from C++"; // string to pass DWORD dwSize = sizeof(data); // size of this string DWORD dwBytesWritten; // here will be the number of bytes actually transferred

Sending a string. Let me remind you that the example is the simplest, so I don’t do any special checks:

BOOL iRet = WriteFile(hSerial,data,dwSize,&dwBytesWritten,NULL);

I also decided to display the string size and the number of bytes sent to control:

Cout<< dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;

At the end of the program, we make an infinite loop of reading data:

While(1) ( ReadCOM(); ) return 0; )

Now the read function:

Void ReadCOM() ( DWORD iSize; char sReceivedChar; while (true) ( ​​ReadFile(hSerial, &sReceivedChar, 1, &iSize, 0); // get 1 byte if (iSize > 0) // print cout if something is received<< sReceivedChar; } }

That's actually the whole example.

About how to beautifully represent the data sent by Arduin to Serial. In my opinion, the guys offered a very beautiful solution, which on the one hand looks quite simple, and on the other hand, allows you to get an excellent result with a minimum of effort.

In the comments to the article, it was regretted that such a solution would not work under Firefox, and the idea was expressed that "you can still write a simple web server with html output based on this thing." This idea “hooked” me, a quick search on google did not give out a ready-made solution, and I decided to implement the idea myself. And here's what came out of it.

Warning! The proposed solution should by no means be considered complete. Unlike Amperka's Serial Projector, this is a concept, a demonstration of a possible approach, a working prototype and nothing more.

Some time ago I did a project in which I used the built-in accelerometers in an Android smartphone to control servos connected to an Arduino. Then for these purposes I used the Scripting Layer for Android (SL4A) and RemoteSensors projects. It turns out that the python standard library includes the BaseHTTPServer package, with which to raise a web service in python is a task in a couple of lines of code.

There were no sensors for the Arduino at hand, so I used the internal thermometer built into the Arduino Uno as the source of the displayed information. As far as I understand, it is not very accurate and is not at all intended for measuring ambient temperature, but it will do for prototyping.

After a short googling, here is a sketch for an arduino:

// source: https://code.google.com/p/tinkerit/wiki/SecretThermometer long readTemp() ( long result; // Read temperature sensor against 1.1V reference ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3); delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = (result - 125) * 1075; return result; } void setup() { Serial.begin(115200); } int count = 0; void loop() { String s = String(count++, DEC) + ": " + String(readTemp(), DEC); Serial.println(s) delay(1000); }
This sketch opens a COM port, sets it to 115200 baud, and then writes the current value of the built-in thermometer to it every second. (Do not ask me in what units the temperature is given - for the described task it is not important). Since the value does not change very actively, for better visibility of data changes, the line number is displayed before the temperature.

To check that the web server will give out only whole lines, and not parts of them, as it reads from the COM port, the line
Serial.println(s)
has been replaced by
for(int i=0; i< s.length(); i++){ Serial.print(s.charAt(i)); delay(200); } Serial.println("");
those. the formed string is not output to the serial port in its entirety, but character by character, with pauses of 200 ms.

To begin with, a very simple prototype of a web server was written (below it is disassembled in parts):
# -*- coding: utf-8 -*- #-- based on: https://raw.githubusercontent.com/Jonty/RemoteSensors/master/remoteSensors.py SERIAL_PORT_NAME = "COM6" SERIAL_PORT_SPEED = 115200 WEB_SERVER_PORT = 8000 import time , BaseHTTPServer, urlparse import serial ser = None def main(): global ser httpd = BaseHTTPServer.HTTPServer(("", WEB_SERVER_PORT), Handler) #-- workaround for getting IP address at which serving import socket s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM) s.connect(("google.co.uk", 80)) sData = s.getsockname() print "Serving at "%s:%s"" % (sData, WEB_SERVER_PORT) ser = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_SPEED, timeout=0) httpd.serve_forever() class Handler(BaseHTTPServer.BaseHTTPRequestHandler): # Disable logging DNS lookups def address_string(self): return str(self.client_address) def do_GET(self): self.send_response(200) self.send_header("Content-type", "application/x-javascript; charset=utf-8") self.end_headers() try: while True: new_serial_line = get_full_line_from_serial() if new_serial_line is not None: self.wfile.write(new_serial_line) self.wfile.write("\n") self.wfile.flush() except socket.error, e: print "Client disconnected.\n" captured = "" def get_full_line_from_serial(): """ returns full line from serial or None Uses global variables "ser" and "captured" """ global captured part = ser.readline() if part: captured += part parts = captured.split("\n", 1); if len(parts) == 2: captured = parts return parts return None if __name__ == "__main__": main()
Let's break down the script piece by piece.

Since this is a prototype, all the main operation parameters (the name of the COM port, its speed, as well as the number of the TCP port on which the web server will run) are indicated directly in the source text:
SERIAL_PORT_NAME="COM6" SERIAL_PORT_SPEED=115200 WEB_SERVER_PORT=8000
Of course, you can arrange to read these parameters from the command line. For example, with the help of the argparse module, this is done very quickly, simply and flexibly.

In this case, Windows users need to find out in the device manager the name of the COM port to which the Arduin is connected. For me it was "COM6". Users of other operating systems need to use the tools of their OS. I have no experience with MacOS at all and I didn't work with COM ports on Linux either, but there, most likely, it will be something like "/dev/ttySn".

Next comes the definition of a global variable to which an instance of the Serial class, which in python is responsible for working with the COM port, will be bound:
ser = None
In line
httpd = BaseHTTPServer.HTTPServer(("", WEB_SERVER_PORT), Handler)
a web server is created that will listen for requests on the specified port WEB_SERVER_PORT. And these requests will be handled by an instance of the Handler class, described below.

The following lines are a little "hack" to display the IP address on which the running web server is actually running:
#-- workaround for getting IP address at which serving import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("google.co.uk", 80)) sData = s.getsockname() print "Serving at "%s:%s"" % (sData, WEB_SERVER_PORT)
As far as I understand, there is no other way to find out this IP. And without this knowledge, how will we access our server from the browser?

Therefore, you have to open a socket and connect to the Google site in order to extract information about your own IP address from the attributes of this socket.

A little lower, the COM port is opened and the web server is actually launched:
ser = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_SPEED, timeout=0) httpd.serve_forever()
This is followed by a description of the class that is responsible for processing requests received by the running web server:
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
This is an inheritor of the class built into the BaseHTTPServer module, in which it is enough to override only the do_GET method

Since this is still a prototype, the server will be “happy” with any request - no matter what URL is requested from it, it will give the client all the data read from the COM port. Therefore, in Handler.do_GET, it immediately responds with a success code and the necessary headers:
self.send_response(200) self.send_header("Content-type", "application/x-javascript; charset=utf-8") self.end_headers()
after which an infinite loop is launched, in which an attempt is made to read a whole line from the COM port and, if this attempt was successful, transfer it to the web client:
while True: new_serial_line = get_full_line_from_serial() if new_serial_line is not None: self.wfile.write(new_serial_line) self.wfile.write("\n") self.wfile.flush()
In the project that was taken as a basis, this infinite loop was “wrapped” in a try ... except block, with the help of which it was supposed to carefully handle the connection break. Perhaps, in Android (the base project was developed for it), this works fine, but it didn’t work out for me under Windows XP - when the connection was broken, some other exception occurred, which I never learned how to intercept. But, fortunately, this did not prevent the web server from working normally and accepting the following requests.

The function of getting an entire string from a COM port works on the same principle as the creators of Serial Projector:

  • there is some global buffer that stores everything that is read from the COM port
  • every time the function is called, it tries to read something from the COM port
  • if she succeeds, then
    • it adds what has just been read to the specified global buffer
    • tries to divide the global buffer into at most two parts by the end-of-line character
    • if it succeeds, then it returns the first part to the calling procedure, and uses the second part as the new value of the global buffer
  • if there is no new data in the COM port or the end-of-line character is not found, then the function returns None:
captured = "" def get_full_line_from_serial(): """ returns full line from serial or None Uses global variables "ser" and "captured" """ global captured part = ser.readline() if part: captured += part parts = captured.split("\n", 1); if len(parts) == 2: captured = parts return parts return None
As a result, it turned out like this:

It can be seen that lines appear in the browser that are read from the COM port. I don't understand anything about the web frontend: JavaScript, Ajax, CSS and DOM are a dark forest for me. But it seems to me that for programmers creating web interfaces, this should be quite enough to convert this output into the same beautiful picture that Amperka's Serial Projector produces. In my opinion, the task is to create a javascript script that accesses the web server, reads a stream from it, and outputs the last line read to the right place on the web page.

Just in case, I decided to play it safe and tried to make the first approximation on my own. A not very deep Google search suggested that, in fact, for such purposes, at least, WebSockets or Server-Sent Events used to be used. I found what seemed to me a good use of Server-Sent Events and decided to use this technology.

Note! This does not seem to be the best solution, because this technology did not work in Internet Explorer 8, nor in the browser built into Android 2.3.5. But it worked at least in Firefox 39.0, so I didn't "dig" further.

From the point of view of the python script, the changes under Server-Sent Events are completely minor:

  • it is necessary to replace the type of data given to the client:
    line
    self.send_header("Content-type", "application/x-javascript; charset=utf-8")
    replaced by
    self.send_header("Content-type", "text/event-stream")
  • and also before the line read from the COM port, insert the prefix "data:" and add one more newline character:
    lines
    self.wfile.write(new_serial_line) self.wfile.write("\n")
    replaced by
    self.wfile.write("data: " + new_serial_line) self.wfile.write("\n\n")

Everything else could probably remain unchanged, but ...

First, I created an index.html file with the following content:

header


The most interesting in it is the line
which forms a place to output the next line from the COM port, and a javascript script

which actually reads the stream from the web server and outputs the read information to the specified location.

I intended to open this file in a browser, for example, from disk or from some other web server, but this did not work: when opening a page from disk, the javascript script once accessed the running Python web server and immediately disconnected. I did not understand why this was happening, and suggested that this might be some kind of browser protection against various attacks. He probably does not like that the page itself is opened from one source, and the script reads data from another source.

Therefore, it was decided to change the Python web server so that it would also serve this html page. Then it would turn out that both the page and the stream are read from the same source. I don’t know if my assumption about security turned out to be correct, or something else, but with this implementation, everything worked as it should.

Of course, you only need to change the Handler request handler class:
class Handler(BaseHTTPServer.BaseHTTPRequestHandler): # Disable logging DNS lookups def address_string(self): return str(self.client_address) def do_GET(self): if self.path == "/" or self.path == "/index .html": self.process_index() elif self.path == "/get_serial": self.process_get_serial() else: self.process_unknown() def process_index(self): self.send_response(200) self.send_header("Content -type", "text/html; charset=utf-8") self.end_headers() self.wfile.write(open("index.html").read()) self.wfile.write("\n\ n") self.wfile.flush() def process_get_serial(self): self.send_response(200) self.send_header("Content-type", "text/event-stream") self.end_headers() try: while True: new_serial_line = get_full_line_from_serial() if new_serial_line is not None: self.wfile.write("data: " + new_serial_line) self.wfile.write("\n\n") self.wfile.flush() except socket.error, e : print "Client disconnected.\n" def process_unknown(self): self.send_response(404)
This option assumes that the web server will only respond to two requests: "/index.html" (giving the page's html code) and "/get_serial" (giving an endless stream of strings read from the COM port). All other requests will be answered with a 404 code.

Since index.html is served by the Python web server, it can be slightly modified by specifying a relative instead of the absolute address of the string stream from the COM port:
string
var source = new EventSource("http://192.168.1.207:8000/")
replaced by
var source = new EventSource("/get_serial")
As a result, it turned out like this:

This is where I decided to stop. It seems to me that designing a page beautifully should already be quite simple. But I'm not proficient in HTML or CSS, so let someone else do it. I saw my task in showing that making a web service that sends data from a COM port, it seems, is not at all difficult.

I repeat once again: the presented code is not a complete solution that can be “put into production”. This is only a prototype, which shows a fundamental approach to solving the problem.

What else can be worked on:

  • firstly, reading data from the COM port in the python script is done very "clumsily" - in fact, there is a constant polling "is there something fresh?". This approach, of course, loads the processor and one core on my computer is 100% occupied.
    A blocking read with a timeout can be used as a solution. To do this, it is enough to specify a non-zero value (in seconds) as a timeout when opening a COM port, for example:
    ser = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_SPEED, timeout=0.03)
    In addition, in the description of the pySerial module, there are three examples of creating a bridge: "TCP/IP - serial bridge", "Single-port TCP/IP - serial bridge (RFC 2217)" and "Multi-port TCP/IP - serial bridge (RFC 2217)" - you can see how professionals solve such problems.
  • secondly, only one client can receive data. Until the page is closed on the first client, you cannot connect to that server and get values ​​on the second computer. On the one hand, this is probably correct: there is only one COM port, and there are several consumers - which of them should give the read line? If you think the answer to this question should be "everyone", then here are my thoughts on the matter. It seems to me that the issue cannot be solved only by using an "honest" multi-threaded web server (for example, some Tornado or Flask), which can serve requests from several web clients at the same time. Because you cannot open a COM port from each thread and read from it - in this case, data from the COM port will go to only one thread / process. Therefore, in my opinion, it is necessary to split the server part into two parts:
    • zmq server that works with a COM port, reads lines from it and sends them via PUB socket to all interested consumers
    • python web server instead of connecting to COM port connects to zmq server and receives data from it
    If you are not familiar with the ZMQ (ZeroMQ) library, then you can use regular TCP / IP or UDP sockets instead, but I would strongly recommend getting acquainted with ZMQ, because this library makes it very easy to solve such problems. It seems to me that with the help of ZMQ, the solution will fit in a maximum of 20 lines. (I can't help but write: even if you do not plan to solve the described task, but your work is related to multi-threaded / multi-process programming with data exchange between threads / processes, take a closer look at this library - perhaps this is what you have been talking about for so long dreamed)
  • the data flow is still unidirectional - from the COM port to the web browser. You cannot yet send data from the browser to the Arduino. It seems to me that this task is also not very difficult and, unlike the previous one, it can be solved only
    • using a multi-threaded server
    • refinement of the Handler.do_GET method so that it accepts GET requests with parameters and sends the values ​​of certain of them to the COM port
    In my opinion, if you want to write a full-fledged analog of the web-based serial port monitor built into the Arduino IDE, it’s not so difficult. Personally, for myself, I see the difficulty only in creating a normal frontend.
  • it is not yet possible to set the name of the COM port and the parameters of its operation through the browser. On the one hand, this seems logical: how can a user on the other side of our planet know which COM port and at what speed the arduino is connected to? But the Python web server running on the same computer knows for sure. But if it is still desirable to give the user the opportunity to change the name of the COM port or the parameters of its operation, then again this can be easily solved by refining the Handler.do_GET method
  • python is required to run the server. This is generally not difficult, but if for some reason this cannot be done or you do not want to, then pyInstaller can come to the rescue. With it, the Python script can be compiled into one executable file (in the case of Windows - in .exe), which is easy to copy to the computer to which the arduino is connected.
    Perhaps the best solution would be to use the Go language in this case. As far as I know, it solves the problem of creating a file for "distribution" better.
In conclusion: the question may arise: “isn’t it easier to solve this problem through some ready-made cloud?”. Why not publish data readable from a COM port in the cloud, and on clients simply access the corresponding service in the cloud? Probably, such a solution also has the right to exist, but before applying such a solution, the following questions must be answered:
  • Are there ready-made web services that allow me to publish data at the speed / frequency I need? Are there free ones among them or are you ready to pay the corresponding money?
  • are you ready for the fact that in the event of a fall of the cloud or a connection to it, you will be left without data
  • Doesn't it bother you that in order to transfer data from one room to another, they will cross the ocean or half a continent twice?

So we got to the COM port. But with it, everything is not as simple as with LPT, and its full use will require much more effort. The main snag is its main advantage - data transfer in serial form. If in LPT a data byte is transmitted over 8 lines, one bit per line, and the state of each line could be easily viewed, then in a COM port, data bytes are transmitted bit by bit along one line (relative to ground, of course) and see what is transmitted there from LEDs alone will not work. To do this, you need a special device - a converter of the serial data stream into parallel, the so-called. USART (Universal Synchronous/Asynchronous Receiver Transmitter). For example, it is included in the motherboard of a computer equipped with a COM port, in any more serious microcontroller.


I hope you are still discouraged in mastering the COM port. Everything is not so gloomy. Some results can be obtained without USART. Let's formulate the task that we implement at the initial stage of working with the COM port:


"I want an LED to be connected to the computer via the COM port. I launch the program. I do some action in this program, the LED lights up, I do something else - the LED goes out."


The task is quite specific (given that USART is not used) and is pure "self-made", but it is quite feasible and workable. Let's start implementing it.


1.COM port

Again, we take the system unit of your PC and look at the rear. We note there a 9-pin connector - this is the COM port. In reality, there may be several (up to 4). My PC has two COM ports (see photo).


2. COM port extension


3. Hardware

We will also have to "tinker" with the hardware part, in the sense that it will be more difficult than with the first device for the LPT port. The fact is that the RS-232 protocol, through which data is exchanged in the COM port, has a somewhat different ratio of logical state - voltage. If usually it is logical 0 0 V, logical 1 +5 V, then in RS-232 this ratio is as follows: logical 0 +12 V, logical 1 -12 V.

And for example, having received -12 V, it is not immediately clear what to do with this voltage. Usually, RS-232 levels are converted to TTL (0.5 V). The easiest option is zener diodes. But I propose to make this converter on a special microcircuit. It is called MAX232.

Now let's see, what signals from the COM port can we see on the LEDs? In fact, there are as many as 6 independent lines in the COM port that are of interest to the developer of interface devices. Two of them are not yet available to us - serial data lines. But the remaining 4 are designed to control and indicate the process of data transfer, and we will be able to "transfer" them to suit our needs. Two of them are designed to be controlled by an external device and we will not touch them for now, but we will use the last two remaining lines now. They're called:

  • RTS- Transfer request. An interaction line that indicates that the computer is ready to receive data.
  • DTR- The computer is ready. Interaction line, which indicates that the computer is on and ready to communicate.

Now we pass their purpose a little, and the LEDs connected to them will either go out or light up, depending on the actions in our own program.

So, let's assemble a scheme that will allow us to carry out the intended actions.

And here is its practical implementation. I think you'll forgive me that I made it in such a dumb breadboard version, because I don't want to make a board for such a "highly productive" circuit.


4. Software part

Everything is faster here. Let's create a Windows application in Microsoft Visual C++ 6.0 based on MFC to manage two communication lines of a COM port. To do this, create a new MFC project and give it a name, for example, TestCOM. Next, we choose the option of building on the basis of the dialogue.

Give the appearance of the dialog box of our program, as in fig. below, namely add four buttons, two for each of the lines. One of them, respectively, is necessary in order to "pay off" the line, the other in order to "set" it to one.

Class CTestCOMDlg: public CDialog ( // Construction public: CTestCOMDlg(CWnd* pParent = NULL); // standard constructor HANDLE hFile;

In order for our program to manage the lines of the COM port, it must first be opened. Let's write the code responsible for opening the port when the program is loaded.

HFile = CreateFile("COM2", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0,NULL); if(hFile==INVALID_HANDLE_VALUE) ( MessageBox("Failed to open port!", "Error", MB_ICONERROR); ) else ( MessageBox("Port opened successfully", "Ok", MB_OK); )

Using the standard Win API function CreateFile() open COM port COM2. Next, we check the success of the opening with the output of an informational message. Here it is necessary to make an important remark: COM2 is in my computer, and on your computer you could connect it to another COM port. Accordingly, its name must be changed to what port you are using. To see which port numbers are present on your computer, you can do this: Start -> Settings -> Control Panel -> System -> Hardware -> Device Manager -> Ports (COM and LPT).

Finally, the function CTestCOMDlg::OnInitDialog() located in the file TestCOMDlg.cpp, our dialog class should take the form:

BOOL CTestCOMDlg::OnInitDialog() ( CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); ) ) // Set the icon for this dialog. The framework does this automatically // when the application"s main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here hFile = CreateFile("COM2", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0,NULL); if(hFile==INVALID_HANDLE_VALUE) ( MessageBox("Failed to open port!", "Error", MB_ICONERROR); ) else ( MessageBox("Port opened successfully", "Ok", MB_OK); ) return TRUE; // return TRUE unless you set the focus to a control )

Now let's add line control button handlers. I gave them the appropriate names: the function that sets the DTR line to 1 is OnDTR1(), 0 is OnDTR0(). For the RTS line, respectively, in a similar way. Let me remind you that the handler is created when you double-click on the button. As a result, these four functions should take the form:

Void CTestCOMDlg::OnDTR1() ( // TODO: Add your control notification handler code here EscapeCommFunction(hFile, 6); ) void CTestCOMDlg::OnDTR0() ( // TODO: Add your control notification handler code here EscapeCommFunction(hFile, 5); ) void CTestCOMDlg::OnRTS1() ( // TODO: Add your control notification handler code here EscapeCommFunction(hFile, 4); ) void CTestCOMDlg::OnRTS0() ( // TODO: Add your control notification handler code here EscapeCommFunction(hFile, 3); )

Let me explain a little how they work. As you can see, inside they contain a call to the same Win API function EscapeCommFunction() with two options. The first of them is a handle (HANDLE) to an open port, the second is a special action code corresponding to the required state of the line.

Everything, compile, run. If everything is fine, you should see a message about the successful opening of the port. Further, by pressing the corresponding buttons, we blink the LEDs connected to the COM port.

© Ivanov Dmitry
December 2006