Physical devices and systems are usually composed of many blocks working in synergy to form a single system. The integration of various blocks is unfortunately is often overlooked or assumed to be much simpler then it proves to be. In order to create a reliably working system every single block whether it is software or hardware should be carefully integrated. Efcom dealt with countless software and hardware blocks, we developed multiple tools to aid us in creating intermediate layers to integrate various types of blocks. System integration is our main expertise and we are eager for new exciting journeys.
As anyone who has allowed their car to parallel park for them knows, computers are everywhere and they control everything. We’re seemingly living in a technologically complex world that many will reap the benefits of but never truly understand.
However, as developers know, at their core all of these incredible devices, apps and abilities boil down to one main thing: communication. From simple IOT devices to large medical systems, every one of these technological developments contain hardware talking to software in some capacity. Whether it’s a BLE channel sending a beacon signal to a mobile phone or a super complicated grid of cameras, motion controller and sensors running a full body procedure in an operating room, there is software-hardware integration everywhere.
The people behind the machines are turning ideas into realities by successfully integrating hardware with software, enabling the communication that makes so much of technology possible. At Efcom, we’ve been completing a full range of low-level to high-level hardware integration among other programming for over 10 years, and learned a few things along the way that we’d like to share.
THE FACTORS THAT GO INTO SELECTING AN INTEGRATION STRATEGY
There are several layers to each integration, and selecting the right integration strategy will significantly influence the robustness and quality of the solution.
The right system integration strategy for each individual solution will depend on many factors, including:
- The device functionality and operation modes – for example response times, synchronous/a synchronous operation, etc.
- The communication protocol used by the device. It can be one of the standards or explicitly defined by the vendor. Examples for standard protocols are MODBUS, GigE, JSON, etc.
- The hardware layer for the protocol – Serial link such as RS232 or RS485, Ethernet, USB other
- The device documentation quality
- The support level provided by the vendor
- System level constraints and specifications
AVOIDING COMMON COMMUNICATION PROBLEMS
Writing software that communicates with hardware is challenging in many ways. It requires the programmer to understand what really happens on the other side and what can be expected of it. It also requires dealing with a module that has its own will, requirements and behavior. And despite all that, very often it lacks proper documentation.
Every piece of hardware has its own communication protocol (both physical and SW), and being able to work with it at a high level requires the understanding that there is something alive on the other side of the line.
The problems that emerge due to lack of such understanding or experience usually are:
- Faulty communication with the device, either not stable or not optimized
- Reduction of system productivity due to misuse of hardware capabilities
- Limited set of features provided to the user
- “Dirty” solutions and workarounds that influence the whole system
- Long and exhausting integration process, both costly and time consuming
OUR DEVELOPMENT METHODOLOGY
Over the last 10 years our team at Efcom has been focused on developing software for multidisciplinary systems. Such systems usually involve one or more types of hardware – cameras, motion and automation units or laboratory equipment, for example.
The methodology we use in our developments is built upon three key points: development flow, the software architecture and the system integration process.
- Development flow
To begin with, we want to evaluate the communication with the device and its functionality in a sterile environment. This can mean seeing how it works with the software provided by the vendor, if applicable. Doing this can either eliminate or detect the possibility that the device is faulty. Once we’ve seen it working with the original tools we know what to expect from it in the future.
The next step would be searching for examples, as it is always better to start from something rather than a blank page. With that, it’s time to start writing code. (Just make sure the device is connected, forgetting this simple step is a common mistake responsible for roughly 30% of integration errors.)
To begin the coding process we create a standalone tester application. The tester is programmed preferably in the same language and platform as the main application. The main purpose of this tool is to let us start working with the new hardware with no interruptions from other items, and also so we can learn how to “talk” to it. We implement all or most of the functionality required by the main software, try it, profile and evaluate the behavior and make decisions for the future software development process based on what we see during testing.
If there are several hardware devices, it’s good to have “tabs” for each one in the tester. This allows us to see how they work together both in terms of performance, such as USB bandwidth limitations, and in terms of functionality, such as turning on the illumination and imaging in parallel.
This phase also helps us understand the requirement from the software in general. For example, if the device to be integrated came with an API it might support only x86, which is obviously good to know that before writing the whole software in x64 just to find out it will not work.
In addition to common good practices, there are some specifics that we’re always careful to keep in mind when working with hardware. For instance, we never let the logical role of the device be mixed up with its protocol/API limitations and constraints. The interface that describes the device should be defined. For example, if it’s a camera it would contain methods like: Init, Close, GetImage, SetExposureTime and perhaps some event like Connected, Disconnected, NewFrame etc. This will be also most helpful in unit testing.
It’s also essential we have an error reporting and detection strategy that assigns severity and defines the appropriate response. For instance, device malfunction or disconnection might be a severe problem that justifies some technician level operations.
It’s also important for us to log, log, log – it’s critical for future steps and the whole system lifecycle, so the logs must be detailed and informative. At times the attention to detail may seem unnecessary, such as when hardware using polling creates 100 lines per second, but when something goes wrong it might be the only source of information.
For every operation it’s also necessary for us to understand what the nature of it is – is it synchronous? What are the errors that can happen by calling that operation? Depending on the software behavior in most cases a singleton pattern can be used to handle all hardware devices.
- System Integration
So we’ve made a working tester, defined an interface and implemented it, and everything looks good. Now it’s time for the most critical step – the integration. This is the time to be prepared, because during the integration anything and everything can happen. In most projects this is the riskiest and most time consuming component. However, in many of those projects, the risks and frustration could have been avoided.
We’ve found that the best way to keep our heads during integration is by sticking to the divide and conquer strategy. After all, most of the problems origins are local; only in a handful of cases will the problem be cross system. Our best friends here are common sense and logs. Don’t allow yourself to be tempted by voodoo rituals. All problems have a scientific explanation. The explanations may not be obvious, but they exist.
RUNNING INTO TROUBLE, AND CLIMBING OUT OF IT
No matter how careful your integration strategy is, you could very well run into issues. To trace back a problem, you might need to go back to the tester phase and recheck it, and you might want to enhance the tester with more functionality to imitate the fault conditions. You might even be forced to go back further, using the vendor provided tools.
It’s also possible that during the development process you could have overwritten some inner memory and made the device nonfunctional. Completely nonfunctional is also your best case scenario, as a device that is faulty only in a specific scenario is much more difficult to detect.
A reliable way to detect a problem that happens only when someone with a coffee crosses the imaginary line between you and the window, so to speak, is stressing the communication channel. If you’re working in 1 Hz polling try to increase to 1Kh, the problem will happen 1000 times faster. As a bonus this might help you see additional issues.
As a final note, you’ll want to remember not to blame the “hardware” right away. As anyone who’s been in the game long enough knows, the hardware usually isn’t the problem.
Planning ahead and understanding and anticipating the challenges you may face during the integration process will significantly improve your chances of finishing the integration on time. If you’re facing issues with integration or are looking for the firm that will handle it all for you like consummate pros, get in touch with us through our website, by calling +972 8 6710671 or sending us an email at firstname.lastname@example.org.