/// <summary> /// Establish a connection to the DMM. /// </summary> /// <param name="portName">The name of the serial port to use.</param> private void Connect(string portName) { // Validate the port name if (string.IsNullOrWhiteSpace(portName)) { return; } // Initialize the multimeter object meter = new Multimeter(portName); // Set the alive flag and clear the blank counter isAlive = true; blankCount = 0; // Try to establish the connection Exception error = meter.Connect(); if (error != null) { // If there was any error, exit, as there is no recovery from this MessageBox.Show(string.Format(Language.ConnectionErrorText, portName, error.Message), Language.ConnectionErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); ChangeUI(false); return; } // Change the UI ChangeUI(true); // Start the timer acquisitionTimer.Start(); }
private void acquisitionTimer_Tick(object sender, EventArgs e) { // Make sure that the state and meter objects are valid if (!isConnected || meter == null || !meter.IsConnected) { // Disconnect and return, if not Disconnect(); return; } // Stop the timer acquisitionTimer.Stop(); // Handle pause mode if (isPaused) { // Discard the samples, start the timer again and continue meter.Flush(); acquisitionTimer.Start(); return; } // Check, if the maximum duration of missed screen updates has been exceeded if ((blankCount - 1) * acquisitionTimer.Interval >= 1000) { // Clear the readout, bargraph and alive flag after a certain number of missed updates isAlive = false; UpdateStatusLabels(); ClearReadout(); ClearBargraph(); } // Always update the blank count (it will be reset if there was a successful update) blankCount++; // Handle pending timer updates if (isTimerUpdatePending) { UpdateTimer(); } // Read all available packets Packet sample = new Packet(); bool success = false; while (meter.IsAvailable) { if (!meter.Receive(out sample)) { // Update the blank screen count blankCount++; // And turn the sampling on again acquisitionTimer.Start(); return; } // Skip invalid packets if (!sample.ChecksumValid) { continue; } // Set the success flag success = true; } // Check, if the reception was successful if (!success) { // Start the timer again acquisitionTimer.Start(); return; } // Clear the blank screen count and set the alive flag after a successful reception blankCount = 0; if (!isAlive) { isAlive = true; UpdateStatusLabels(); } // Handle regular display // Set the mode label accordingly first bool validMode = true; bool valueMode = true; switch (sample.Mode) { case Mode.Ampere: modeLabel.Text = Language.ModeCurrent; break; case Mode.AmpereMicro: modeLabel.Text = Language.ModeCurrent; break; case Mode.AmpereMilli: modeLabel.Text = Language.ModeCurrent; break; case Mode.ContinuityOhm: modeLabel.Text = Language.ModeContinuity; break; case Mode.DiodeVolt: modeLabel.Text = Language.ModeDiode; break; case Mode.ResistanceOhm: modeLabel.Text = Language.ModeResistance; break; case Mode.VoltAC: modeLabel.Text = Language.ModeVoltageAC; break; case Mode.VoltDC: modeLabel.Text = Language.ModeVoltageDC; break; case Mode.Squarewave: modeLabel.Text = Language.ModeSquarewave; valueMode = false; break; default: modeLabel.Text = Language.ModeUnknown; valueMode = false; validMode = false; break; } // Compare the last range with the current one if (lastMode != sample.Mode) { ClearStatistics(); lastMode = sample.Mode; } // Allocate variables for the number parsing bool negative = false; int integer = 0, fractional = 0, exponent = 0, precision = 0; char unit = '\0', unitPrefix = '\0'; // Attempt to parse the number if (validMode && valueMode) { validMode = Multimeter.Parse(sample, out negative, out integer, out fractional, out exponent, out precision, out unit, out unitPrefix); } // Check, if the mode is invalid or that the number is OL bool overloaded = Multimeter.IsOverloaded(sample); if (overloaded && valueMode) // Overload { // Update the value and unit labels valueLabel.Text = "OL"; unitLabel.Text = unit.ToString(); // Fill the bargraph FillBargraph(); } else if (!validMode || !valueMode) { // No valid mode valueLabel.Text = ""; unitLabel.Text = ""; // Clear the bargraph ClearBargraph(); // Cancel and skip the rest acquisitionTimer.Start(); return; } else { // Just format the value according to the precision valueLabel.Text = precision < 1 ? integer.ToString() : string.Format("{0}{1}.{2:D" + precision.ToString() + "}", negative ? "-" : "", integer, fractional); // Also update the unit label unitLabel.Text = unitPrefix == '\0' ? unit.ToString() : string.Format("{0}{1}", unitPrefix, unit); } // Update the UI if (!overloaded) { // Update the bargraph bargraphBar.Minimum = 0; bargraphBar.Maximum = sample.Value < 0 ? Math.Abs(Multimeter.RangeMin(sample.Mode, sample.Range)) : Multimeter.RangeMax(sample.Mode, sample.Range); bargraphBar.Value = Math.Abs(sample.Value); // Calculate the double value double currentValue = Math.Pow(10, exponent) * (integer + (fractional * Math.Pow(10, -precision))); if (negative) { currentValue = -currentValue; } // Update the min statistics if (resetStatistics || minValue > currentValue) { minValue = currentValue; minValueLabel.Text = valueLabel.Text + unitLabel.Text; } // Update the max statistics if (resetStatistics || maxValue < currentValue) { maxValue = currentValue; maxValueLabel.Text = valueLabel.Text + unitLabel.Text; } // Unset the statistics flag if (resetStatistics) { resetStatistics = false; } } // Handle record mode only for valid value modes if (isRecording) { // Calculate the offset in seconds TimeSpan delta = sample.ReceptionTime - recordingStart; // Assemble the line, e.g.: 2022/04/29 10:25:03,4.32,12.34E-3,V // Start with date and time recordingBuffer.AppendFormat("{0} {1}", sample.ReceptionTime.ToLongDateString(), sample.ReceptionTime.ToLongTimeString()); // Followed by the delimiter recordingBuffer.Append(GetCSVDelimiter()); // Continue with the time offset recordingBuffer.AppendFormat(new NumberFormatInfo() { NumberDecimalSeparator = GetCSVFractionalSeparator().ToString(), NumberDecimalDigits = 2 }, "{0:E}", delta.TotalSeconds); // Followed by the delimiter recordingBuffer.Append(GetCSVDelimiter()); // Followed by the value if (overloaded) // Overload { recordingBuffer.Append("OL"); } else if (precision < 1) // Integer value { recordingBuffer.AppendFormat("{0}E{1}", integer, exponent); } else // Fixed point value { recordingBuffer.AppendFormat("{0}{1}{2}{3:D" + precision.ToString() + "}E{4}", negative ? "-" : "", integer, GetCSVFractionalSeparator(), fractional, exponent); } // Followed by the delimiter recordingBuffer.Append(GetCSVDelimiter()); // Followed by the unit recordingBuffer.Append(unit); // And a final line break recordingBuffer.AppendLine(); // Update the running for label and increment the sample counter recordingCount++; UpdateStatusLabels(); } // Start the timer again acquisitionTimer.Start(); }