This project is a computerized multimeter which incorporates a volt meter, ohm meter, continuity meter, voltage drop meter, component tester, and graph. The program interfaces with a hardware microcontroller programmed with C++ code. The microcontroller knows how to perform various tests and communicate with a computer via serial over usb. The C# program can execute commands by sending them over serial and perform tasks based on the response given by the microcontroller. This functionality is run in a background thread so that the process won’t interfere with the user’s actions. The sending and receiving processes never directly communicate.
Serial Protocol (Evuino)
The serial protocol developed for this project uses a series of important characters, values, and separators to support multiple values.
Information is sent in the form of a command. A command begins with the character ‘#’, and ends with the ‘~’ character. The first integer to follow the ‘#’ character is the primary set of functions to be executed. The next int value (separated by a ‘/’ character) indicates the specific function. Numbers following that pass specific values into a function. The “measure capacitor” command would look like this: “#10/3/500/0/5/2/10000/4~”.
The way the commands are parsed allows for flexibility in what can be sent. For example, the command #12~ would execute the same as #12/0/0/0~. They would also be considered equal upon comparison.
Upon receiving a command, the microcontroller will immediately send the same command back, this time starting with the ‘@’ symbol. This indicates a handshake request. The computer then sends the confirm char ‘*’ or some other character to reject the command. This ensures that there are no transmission errors. Upon receiving a handshake command, the computer compares the value to the last sent command. If they match, it sends the confirm command.
Because the protocol only supports integer values, transmission of floating point values is difficult. If a floating point value needs to be transmitted, it is multiplied by a constant (typically 1,000,000) before transmission. This value is sent along with the multiplied value. When the computer receives the value, it divides the two values to restore the floating point format.
Window / Form Arrangement
- Main Measurement – The main measurement window contains multiple tabs which correspond to the various functions of the meter. The event handlers in this form call send command functions located in the EvuinoOverride object. Future versions could implement custom user controls for each multimeter function. This would clean up the code in the main measurement code. The tab structure is as follows:
- Volt Meter – Continually reads and displays voltage read by meter. Supports min/max tracking and reset functionality.
- Ohm Meter – Continually reads and displays resistance read by meter. Supports min/max tracking and reset functionality.
- Continuity Meter – Continually looks in both directions for a short circuit. If the measured voltage value exceeds the threshold (set in the GUI), display will update to indicate the direction of short and voltage value.
- Component Tester – Executes tests to find accuracy of a component. Runs multiple tests, and averages the results.
- *Component Meter – Runs several various tests and uses logic to determine what type of component is being measured. NOTE: This feature has not yet been implemented.
- Graph – Contains a performance graph element, which is updated with values in the same way as the volt and ohm meter. In addition to displaying the value numerically, the value gets appended to the chart.
- Settings – Upon loading, the settings dialog reads values from the prefVal object located in Program.cs. When a value is changed, the prefVal object is automatically updated. The next time the program performs a function, it will reference the new value.
Loading and Closing Logic
When the program is run, the serial object will attempt to connect with the hardware. If it is successful in establishing a serial port connection, it begins a background thread which starts to read data on that serial port. The program then sends a “hello” command (“&&&&&”). The thread waits for a response (*~) from the device. If it receives this response successfully, the program then loads the window and starts normal operation.
If any point in the initialization procedure above fails or throws an exception, the program will display a message box asking if the user would like to try to connect again. If so, the settings window will appear, providing the user with the opportunity to verify port name and baud rate. Once this window is closed, the program will restart and attempt to connect again. This same procedure is followed if the device is disconnected during operation.
If the user does not wish to attempt connection again, the program will throw a SelfDestructException, which will be caught by the Main() loop. The program will return and exit. This ensures destructor events still get called.
When the program is terminated for any reason, the background thread is stopped by calling the CancelAsync() function.