Skip to content

Commit

Permalink
show optional note value (+-cent) for audio frequencies, readme update
Browse files Browse the repository at this point in the history
implement changes from PR #275, thx @radiantly
add a code of conduct to the project
  • Loading branch information
Ho-Ro committed Mar 7, 2022
1 parent ff6492f commit ee8798c
Show file tree
Hide file tree
Showing 23 changed files with 508 additions and 1,017 deletions.
5 changes: 5 additions & 0 deletions CODE_OF_CONDUCT
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
This is a private, non-profit project.
There is one simple rule for our cooperation:
Be kind - please treat your counterpart as you would like to be treated yourself!
And if you are looking for help, please help us to help you:
Be accurate in the information you give.
674 changes: 0 additions & 674 deletions COPYING

This file was deleted.

27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ OpenHantek6022 is a free software for **Hantek DSO6022** USB digital signal osci
* [Building OpenHantek6022 from source](#building-openhantek6022-from-source)
* [Install prebuilt binary packages](#install-prebuilt-binary-packages)
* [Run OpenHantek6022](#run-openhantek6022)
+ [Windows USB access](#windows-usb-access)
* [Important!](#important-)
* [Specifications, features, limitations and developer documentation](#specifications--features--limitations-and-developer-documentation)
+ [USB access](#usb-access)
* [Important!](#important)
* [Specifications, features, limitations and developer documentation](#specifications-features-limitations-and-developer-documentation)
* [Contribute](#contribute)
* [Donate](#donate)
* [Other DSO open source software](#other-dso-open-source-software)
Expand Down Expand Up @@ -52,13 +52,14 @@ OpenHantek6022 is a free software for **Hantek DSO6022** USB digital signal osci
* Settable probe attenuation factor 1..1000 to accommodate a variety of different probes.
* Measure and display Vpp, DC (average), AC, RMS and dB (of RMS) values as well as frequency of active channels.
* Display the power dissipation for a load resistance of 1..1000 Ω (optional, can be set in Oscilloscope/Settings/Analysis).
* Display the THD of the signal (optional, can be set in Oscilloscope/Settings/Analysis).
* Math channel modes: CH1+CH2, CH1-CH2, CH2-CH1, CH1*CH2 and AC part of CH1 or CH2.
* Display the THD of the signal (optional, can be enabled in Oscilloscope/Settings/Analysis).
* Show the note values and deviation in cent (*twelve equal*, A = 440 Hz) for audio frequencies (optional, can be enabled in Oscilloscope/Settings/Analysis). Useful to tune e.g. your electrical guitar.
* Math channel modes: CH1+CH2, CH1-CH2, CH2-CH1, CH1*CH2 and square, abs, sign, AC and DC part of CH1 or CH2.
* Time base 10 ns/div .. 10 s/div.
* Sample rates 100, 200, 500 S/s, 1, 2, 5, 10, 20, 50, 100, 200, 500 kS/s, 1, 2, 5, 10, 12, 15, 24, 30 MS/s (24 & 30 MS/s in CH1-only mode).
* 48 MS/s not supported due to unstable USB data streaming.
* Downsampling (up to 200x) increases resolution and SNR.
* Calibration output square wave signal frequency can be selected between 32 Hz .. 100 kHz in small steps (poor man's signal generator).
* Calibration output square wave signal frequency can be selected between 32 Hz .. 100 kHz in small steps (poor person's signal generator).
* Trigger modes: *Normal*, *Auto* and *Single* with green/red status display (top left).
* Untriggered *Roll* mode can be selected for slow time bases of 200 ms/div .. 10 s/div.
* Trigger filter *HF* (trigger also on glitches), *Normal* and *LF* (for noisy signals).
Expand All @@ -75,7 +76,7 @@ OpenHantek6022 is a free software for **Hantek DSO6022** USB digital signal osci
* The dock views on the main window can be [customized](https://github.com/OpenHantek/OpenHantek6022/issues/161#issuecomment-799597664) by dragging them around and stacking them.
This allows a minimum window size of 800*300 for old laptops or workstation computers.
* All settings can be saved to a configuration file and loaded again.
* Chinese, French, German, Polish, Russian and Spanish localisation complete, Italian and Portuguese translation ongoing - [volunteers welcome](openhantek/translations/Translation_HowTo.md)!
* Chinese, French, German, Polish, Russian, Spanish and Swedish localisation complete, Italian and Portuguese translation ongoing - [volunteers welcome](openhantek/translations/Translation_HowTo.md)!

## AC coupling
A [little HW modification](docs/HANTEK6022_AC_Modification.pdf) adds AC coupling. OpenHantek6022 supports this feature since v2.17-rc5 / FW0204.
Expand Down Expand Up @@ -133,6 +134,8 @@ On a Linux system start the program via the menu entry *OpenHantek (Digital Stor

You can explore the look and feel of OpenHantek6022 without the need for real scope hardware by running it from the command line as: `OpenHantek --demoMode`.

Note: To use the 6022BL in scope mode, make sure the "H/P" button is pressed before plugging in.

### OpenGL support
OpenHantek6022 uses the *OpenGL* graphics library to display the data. It requires a graphics card that supports
3D rendering and runs on legacy HW/SW that supports at least *OpenGL* 2.1+ or *OpenGL ES* 1.2+.
Expand All @@ -158,19 +161,19 @@ You have to assign the correct WinUSB driver with _one_ of these three _alternat
2. Install the signed `.inf` file `Hantek_6022B.inf` for all devices [provided by VictorEEV](https://www.eevblog.com/forum/testgear/hantek-6022be-20mhz-usb-dso/msg3218116/#msg3218116). It's also part of the `openhantek_xxx_win_x64.zip` [binary distribution](https://github.com/OpenHantek/OpenHantek6022/releases). Right-click on `Hantek_6022B.inf` and select "install" from the pull-down menu.
3. Run the [**Zadig**](docs/build.md#microsoft-windows-usb-driver-install-with-zadig) tool and follow the good [step-by-step tutorial](docs/OpenHantek6022_zadig_Win10.pdf) provided by [DaPa](https://github.com/DaPa).

Note:
With alternative *i*, the Device Manager will show (under "Universal Serial Bus devices") the name and state according to the firmware loaded (e.g. `Hantek 6022BE loader`, `Hantek 6022BL openht`).
The [PulseView/sigrok-cli](https://sigrok.org/) firmware is also recognized (e.g. `Hantek 6022BE sigrok`).
Note:
With alternative *i*, the Device Manager will show (under "Universal Serial Bus devices") the name and state according to the firmware loaded (e.g. `Hantek 6022BE loader`, `Hantek 6022BL openht`).
The [PulseView/sigrok-cli](https://sigrok.org/) firmware is also recognized (e.g. `Hantek 6022BE sigrok`).

## Important!
The scope doesn't store the firmware permanently in flash or eeprom, it must be uploaded after each power-up and is kept in ram 'til power-down.
If the scope was used with a different software (old openhantek, sigrok or the windows software) the scope must be unplugged and replugged one-time before using it with OpenHantek6022 to enable the automatic loading of the correct firmware.
The top line of the program must display the correct firmware version (FW0209).
The top line of the program must display the correct firmware version (FW0210).

## Specifications, features, limitations and developer documentation
I use this project mainly to explore how DSP software can improve and extend the [limitations](docs/limitations.md)
of this kind of low level hardware. It would have been easy to spend a few bucks more to buy a powerful scope - but it would be much less fun :)
Please refer also to the [developer info](openhantek/developer_info.md).
Please refer also to the [developer info](docs/developer_info.md).

## Contribute
We welcome any reported GitHub issue if you have a problem with this software. Send us a pull request for enhancements and fixes. Some random notes:
Expand Down
14 changes: 7 additions & 7 deletions cmake/CPackInfos.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,14 @@ set(CPACK_DEBIAN_PACKAGE_SECTION "electronics")
# do not detect depencencies and versions automatically
# set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
# use deb stable packages without version explicitely to support also legacy installations
# local build uses Debian stable (currently buster)
# CI build (github actions or appveyor) uses Ubuntu 18.04 LTS until Debian "bullseye" becomes "stable"
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libfftw3-double3, libglu1-mesa, libglx0, libopengl0, libqt5opengl5, libqt5printsupport5, libusb-1.0-0")
# local build uses Debian stable (currently bullseye)
# CI build (github actions or appveyor) uses Ubuntu 20.04 LTS as long as Debian "bullseye" is "stable"
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libfftw3-double3, libglu1-mesa, libglx0, libopengl0, libqt5opengl5, libqt5printsupport5, libusb-1.0-0")
message( "-- Depends: ${CPACK_DEBIAN_PACKAGE_DEPENDS}" )
# Debian buster Depends: "libc6 (>= 2.14), libfftw3-double3 (>= 3.3.5), libgcc1 (>= 1:3.0), libglu1-mesa | libglu1, libglx0, libopengl0, libqt5core5a (>= 5.11.0~rc1), libqt5gui5 (>= 5.8.0), libqt5opengl5 (>= 5.0.2), libqt5printsupport5 (>= 5.10.0), libqt5widgets5 (>= 5.4.0), libstdc++6 (>= 5), libusb-1.0-0 (>= 2:1.0.16)"
# Debian bullseye Depends: tbd
# Ubuntu 18.04 Depends: "libc6 (>= 2.14), libfftw3-double3 (>= 3.3.5), libgcc1 (>= 1:3.0), libqt5core5a (>= 5.9.0~beta), libqt5gui5 (>= 5.8.0), libqt5printsupport5 (>= 5.2.0), libqt5widgets5 (>= 5.4.0), libstdc++6 (>= 5), libusb-1.0-0 (>= 2:1.0.16)"
# Ubuntu 20.04 Depends: "libc6 (>= 2.29), libfftw3-double3 (>= 3.3.5), libgcc-s1 (>= 3.0), libqt5core5a (>= 5.12.2), libqt5gui5 (>= 5.8.0) | libqt5gui5-gles (>= 5.8.0), libqt5printsupport5 (>= 5.10.0), libqt5widgets5 (>= 5.4.0), libstdc++6 (>= 5), libusb-1.0-0 (>= 2:1.0.16)
# Debian buster Depends: "libc6 (>= 2.14), libfftw3-double3 (>= 3.3.5), libgcc1 (>= 1:3.0), libglu1-mesa | libglu1, libglx0, libopengl0, libqt5core5a (>= 5.11.0~rc1), libqt5gui5 (>= 5.8.0), libqt5opengl5 (>= 5.0.2), libqt5printsupport5 (>= 5.10.0), libqt5widgets5 (>= 5.4.0), libstdc++6 (>= 5), libusb-1.0-0 (>= 2:1.0.16)"
# Debian bullseye Depends: "libc6 (>= 2.29), libfftw3-double3 (>= 3.3.5), libgcc-s1 (>= 3.0), libqt5core5a (>= 5.15.1), libqt5gui5 (>= 5.14.1) | libqt5gui5-gles (>= 5.14.1), libqt5printsupport5 (>= 5.10.0), libqt5widgets5 (>= 5.15.1), libstdc++6 (>= 5), libusb-1.0-0 (>= 2:1.0.16)
# Ubuntu 18.04 Depends: "libc6 (>= 2.14), libfftw3-double3 (>= 3.3.5), libgcc1 (>= 1:3.0), libqt5core5a (>= 5.9.0~beta), libqt5gui5 (>= 5.8.0), libqt5printsupport5 (>= 5.2.0), libqt5widgets5 (>= 5.4.0), libstdc++6 (>= 5), libusb-1.0-0 (>= 2:1.0.16)"
# Ubuntu 20.04 Depends: "libc6 (>= 2.29), libfftw3-double3 (>= 3.3.5), libgcc-s1 (>= 3.0), libqt5core5a (>= 5.12.2), libqt5gui5 (>= 5.8.0) | libqt5gui5-gles (>= 5.8.0), libqt5printsupport5 (>= 5.10.0), libqt5widgets5 (>= 5.4.0), libstdc++6 (>= 5), libusb-1.0-0 (>= 2:1.0.16)

set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")

Expand Down
2 changes: 1 addition & 1 deletion openhantek/src/OH_BUILD.h
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Do not edit, will be re-created at each commit!
#define OH_BUILD "20220307 - commit 962"
#define OH_BUILD "20220307 - commit 963"
31 changes: 21 additions & 10 deletions openhantek/src/configdialog/DsoConfigAnalysisPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,15 @@ DsoConfigAnalysisPage::DsoConfigAnalysisPage( DsoSettings *settings, QWidget *pa
spectrumGroup = new QGroupBox( tr( "Spectrum" ) );
spectrumGroup->setLayout( spectrumLayout );

dummyLoadLabel = new QLabel( tr( "Calculate power dissipation for load resistance<br/>(0 = off)" ) );
dummyLoadCheckbox = new QCheckBox( tr( "Calculate power dissipation for load resistance" ) );
dummyLoadSpinBox = new QSpinBox();
dummyLoadSpinBox->setMinimum( 0 ); // 0 = off
dummyLoadSpinBox->setMaximum( 1000 ); // range: audio (4/8 Ω), RF (50 Ω) and telco (600 Ω)
dummyLoadSpinBox->setMinimum( 1 );
dummyLoadSpinBox->setMaximum( 1000 ); // range: audio (4/8 Ω), RF (50 Ω) and telco (600 Ω)
if ( 0 == settings->scope.analysis.dummyLoad ) { // 0 was off in earlier setups
settings->scope.analysis.calculateDummyLoad = false; // do not analyse
settings->scope.analysis.dummyLoad = 50; // set default
}
dummyLoadCheckbox->setChecked( settings->scope.analysis.calculateDummyLoad );
dummyLoadSpinBox->setValue( int( settings->scope.analysis.dummyLoad ) );
dummyLoadUnitLabel = new QLabel( tr( "<p>&Omega;</p>" ) );
dummyLoadLayout = new QHBoxLayout();
Expand All @@ -69,17 +74,21 @@ DsoConfigAnalysisPage::DsoConfigAnalysisPage( DsoSettings *settings, QWidget *pa
thdCheckBox = new QCheckBox( tr( "Calculate total harmonic distortion (THD)" ) );
thdCheckBox->setChecked( settings->scope.analysis.calculateTHD );

powerLayout = new QGridLayout();
powerLayout->addWidget( dummyLoadLabel, 0, 0 );
powerLayout->addLayout( dummyLoadLayout, 0, 1 );
powerLayout->addWidget( thdCheckBox, 1, 0 );
showNoteCheckBox = new QCheckBox( tr( "Show note values for audio frequencies" ) );
showNoteCheckBox->setChecked( settings->scope.analysis.showNoteValue );

powerGroup = new QGroupBox( tr( "Power" ) );
powerGroup->setLayout( powerLayout );
analysisLayout = new QGridLayout();
analysisLayout->addWidget( dummyLoadCheckbox, 0, 0 );
analysisLayout->addLayout( dummyLoadLayout, 0, 1 );
analysisLayout->addWidget( thdCheckBox, 1, 0 );
analysisLayout->addWidget( showNoteCheckBox, 2, 0 );

analysisGroup = new QGroupBox( tr( "Analysis" ) );
analysisGroup->setLayout( analysisLayout );

mainLayout = new QVBoxLayout();
mainLayout->addWidget( spectrumGroup );
mainLayout->addWidget( powerGroup );
mainLayout->addWidget( analysisGroup );
mainLayout->addStretch( 1 );

setLayout( mainLayout );
Expand All @@ -91,7 +100,9 @@ void DsoConfigAnalysisPage::saveSettings() {
settings->post.spectrumWindow = Dso::WindowFunction( windowFunctionComboBox->currentIndex() );
settings->post.spectrumReference = referenceLevelSpinBox->value();
settings->post.spectrumLimit = minimumMagnitudeSpinBox->value();
settings->scope.analysis.calculateDummyLoad = dummyLoadCheckbox->isChecked();
settings->scope.analysis.dummyLoad = unsigned( dummyLoadSpinBox->value() );
settings->scope.analysis.calculateTHD = thdCheckBox->isChecked();
settings->post.reuseFftPlan = reuseFftPlanCheckBox->isChecked();
settings->scope.analysis.showNoteValue = showNoteCheckBox->isChecked();
}
7 changes: 4 additions & 3 deletions openhantek/src/configdialog/DsoConfigAnalysisPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ class DsoConfigAnalysisPage : public QWidget {
QHBoxLayout *minimumMagnitudeLayout;

QCheckBox *reuseFftPlanCheckBox;
QCheckBox *showNoteCheckBox;

QGroupBox *powerGroup;
QGridLayout *powerLayout;
QGroupBox *analysisGroup;
QGridLayout *analysisLayout;

QLabel *dummyLoadLabel;
QCheckBox *dummyLoadCheckbox;
QSpinBox *dummyLoadSpinBox;
QLabel *dummyLoadUnitLabel;
QHBoxLayout *dummyLoadLayout;
Expand Down
6 changes: 6 additions & 0 deletions openhantek/src/dsosettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,16 @@ void DsoSettings::load() {
}
// Analysis
storeSettings->beginGroup( "analysis" );
if ( storeSettings->contains( "calculateDummyLoad" ) )
scope.analysis.calculateDummyLoad = storeSettings->value( "calculateDummyLoad" ).toBool();
if ( storeSettings->contains( "dummyLoad" ) )
scope.analysis.dummyLoad = storeSettings->value( "dummyLoad" ).toUInt();
if ( storeSettings->contains( "calculateTHD" ) )
scope.analysis.calculateTHD = storeSettings->value( "calculateTHD" ).toBool();
if ( storeSettings->contains( "reuseFftPlan" ) )
post.reuseFftPlan = storeSettings->value( "reuseFftPlan" ).toBool();
if ( storeSettings->contains( "showNoteValue" ) )
scope.analysis.showNoteValue = storeSettings->value( "showNoteValue" ).toBool();
storeSettings->endGroup(); // analysis
storeSettings->endGroup(); // scope

Expand Down Expand Up @@ -392,9 +396,11 @@ void DsoSettings::save() {

// Analysis
storeSettings->beginGroup( "analysis" );
storeSettings->setValue( "calculateDummyLoad", scope.analysis.calculateDummyLoad );
storeSettings->setValue( "dummyLoad", scope.analysis.dummyLoad );
storeSettings->setValue( "calculateTHD", scope.analysis.calculateTHD );
storeSettings->setValue( "reuseFftPlan", post.reuseFftPlan );
storeSettings->setValue( "showNoteValue", scope.analysis.showNoteValue );
storeSettings->endGroup(); // analysis
storeSettings->endGroup(); // scope

Expand Down
19 changes: 17 additions & 2 deletions openhantek/src/dsowidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ DsoWidget::DsoWidget( DsoSettingsScope *scope, DsoSettingsView *view, const Dso:
measurementLayout->setColumnStretch( 9, 3 ); // Power
measurementLayout->setColumnStretch( 10, 2 ); // THD
measurementLayout->setColumnStretch( 11, 3 ); // f
measurementLayout->setColumnStretch( 12, 3 ); // note, cent
for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
QPalette voltagePalette = palette;
QPalette spectrumPalette = palette;
Expand Down Expand Up @@ -167,6 +168,9 @@ DsoWidget::DsoWidget( DsoSettingsScope *scope, DsoSettingsView *view, const Dso:
measurementFrequencyLabel.push_back( new QLabel() );
measurementFrequencyLabel[ channel ]->setAlignment( Qt::AlignRight );
measurementFrequencyLabel[ channel ]->setPalette( voltagePalette );
measurementNoteLabel.push_back( new QLabel() );
measurementNoteLabel[ channel ]->setAlignment( Qt::AlignCenter );
measurementNoteLabel[ channel ]->setPalette( voltagePalette );
setMeasurementVisible( channel );
int iii = 0;
measurementLayout->addWidget( measurementNameLabel[ channel ], int( channel ), iii++ );
Expand All @@ -181,6 +185,7 @@ DsoWidget::DsoWidget( DsoSettingsScope *scope, DsoSettingsView *view, const Dso:
measurementLayout->addWidget( measurementRMSPowerLabel[ channel ], int( channel ), iii++ );
measurementLayout->addWidget( measurementTHDLabel[ channel ], int( channel ), iii++ );
measurementLayout->addWidget( measurementFrequencyLabel[ channel ], int( channel ), iii++ );
measurementLayout->addWidget( measurementNoteLabel[ channel ], int( channel ), iii++ );
if ( channel < spec->channels )
updateVoltageCoupling( channel );
else
Expand Down Expand Up @@ -378,6 +383,7 @@ void DsoWidget::setColors() {
measurementRMSPowerLabel[ channel ]->setPalette( tablePalette );
measurementTHDLabel[ channel ]->setPalette( tablePalette );
measurementFrequencyLabel[ channel ]->setPalette( tablePalette );
measurementNoteLabel[ channel ]->setPalette( tablePalette );
}

tablePalette = palette();
Expand Down Expand Up @@ -504,6 +510,7 @@ void DsoWidget::setMeasurementVisible( ChannelID channel ) {
measurementACLabel[ channel ]->setVisible( visible );
measurementdBLabel[ channel ]->setVisible( visible );
measurementFrequencyLabel[ channel ]->setVisible( visible );
measurementNoteLabel[ channel ]->setVisible( visible );
measurementRMSPowerLabel[ channel ]->setVisible( visible );
if ( !visible ) {
measurementGainLabel[ channel ]->setText( QString() );
Expand All @@ -515,6 +522,7 @@ void DsoWidget::setMeasurementVisible( ChannelID channel ) {
measurementRMSPowerLabel[ channel ]->setText( QString() );
measurementTHDLabel[ channel ]->setText( QString() );
measurementFrequencyLabel[ channel ]->setText( QString() );
measurementNoteLabel[ channel ]->setText( QString() );
}

measurementGainLabel[ channel ]->setVisible( scope->voltage[ channel ].used );
Expand Down Expand Up @@ -867,7 +875,6 @@ void DsoWidget::updateZoom( bool enabled ) {
repaint();
}


/// \brief Prints analyzed data.
void DsoWidget::showNew( std::shared_ptr< PPresult > analysedData ) {
if ( scope->verboseLevel > 4 )
Expand Down Expand Up @@ -910,8 +917,16 @@ void DsoWidget::showNew( std::shared_ptr< PPresult > analysedData ) {
// Frequency string representation (3 significant digits)
measurementFrequencyLabel[ channel ]->setText(
valueToString( analysedData.get()->data( channel )->frequency, UNIT_HERTZ, 4 ) );
// Frequency note representation
if ( scope->analysis.showNoteValue ) {
measurementLayout->setColumnStretch( 12, 3 );
measurementNoteLabel[ channel ]->setText( analysedData.get()->data( channel )->note );
} else { // do not show this label
measurementNoteLabel[ channel ]->setText( "" );
measurementLayout->setColumnStretch( 12, 0 ); // Note
}
// RMS Amplitude string representation (3 significant digits)
if ( scope->analysis.dummyLoad ) { // != 0 -> show
if ( scope->analysis.calculateDummyLoad && scope->analysis.dummyLoad > 0 ) {
measurementLayout->setColumnStretch( 9, 3 );
measurementRMSPowerLabel[ channel ]->setText(
valueToString( ( analysedData.get()->data( channel )->rms * analysedData.get()->data( channel )->rms ) /
Expand Down
Loading

0 comments on commit ee8798c

Please sign in to comment.