Turn a simple Arduino Uno (and some Python code) into a crude oscilloscope for viewing waveforms and voltage levels.
Oscilloscopes are extremely useful, but usually come with a hefty price tag. Luckily, there are some alternatives to dedicated oscilloscopes, so in this project we'll turn a simple Arduino Uno (and some Python code) into a crude oscilloscope that you can use to view waveforms and voltage levels!
How it works: Arduino
The hardware/firmware side of the oscilloscope is very simple and makes use of a module built into the Arduino, the ADC. ADC stands for Analog to Digital Converter and is a module that can take an analog voltage (between 0V and 5V) and convert it into a binary number. The Arduino has a 10-bit ADC, which means that the maximum voltage, 5V, is represented as 1023 (11111111111) and the minimum voltage, 0V, is represented as 0 (0000000000). However, since the Arduino is an 8-bit machine and an unsigned char is 8 bits in size (you'll see why later), we only use the first 8 bits from the ADC result. This means that 5V is now represented as 255 and 0V is represented as 0V. Since there are 256 possible values, each bit represents 5/256 volts or 0.02V (approximately). Therefore, a value of 0x0F represents 0.3V, a value of 0x80 represents 2.56V, and a value of 0x3E represents 1.22V.
Although the Arduino enables the ADC by default, so no setup code is required, we will still configure the analog pins as inputs. The pin we will use to take readings is A0, which is pin number 14. In addition to the pin configuration, we will also configure the UART module for a fast baud rate (115200 baud) for PC communication, and initialize some variables.
The code in the main loop starts by taking 100 readings from the ADC module. Reading analog data from the ADC is very simple and can be done using the function analogRead(pin number) which returns an integer with the 10-bit ADC result from the pin specified by the pin number. In our case, input0 refers to pin 14, which is A0. Once the readings have been taken, the next piece of code to be executed is the delay. The size of the delay (in microseconds) is defined by timeBase, which defaults to 100. Despite being a 100us delay, the true spacing between readings is the size of the delay plus the ADC conversion time (100us), which gives a 200us interval between readings. For simplicity in this project this will be ignored.
Once all 100 readings are complete, this data can be sent to the PC for plotting. To ensure that the receiver can correctly distinguish the data transaction, the Arduino will only send data after the Arduino sends a request "R?" followed by the receiver sending the letter "K".
Once the Arduino and PC have successfully talked to each other, all the data is streaming out. However, the UART works at 8 bits, and trying to send integers over the UART will require complex conversions that will make things rather difficult. Therefore, we just send the analog reading as a single byte, which we do using the function highByte ( ). The size of integers in the Arduino is 16 bits, which means that we need to take the 10 bits of the result and shift them to the left until the top 8 bits contain our data. To do this, we shift the data to the left six times, which means that we lose the lowest 2 bits of the ADC reading, but for our basic oscilloscope that doesn't matter.
With the 8-bit result sent, the last task is to wait for a response from the computer to notify the Arduino that the result has been read correctly. The Arduino simply stays in a loop, waiting for the character "K" on the serial port. Once it has been read, the whole loop repeats itself!
How it works: Python code
The Python code along with some additional libraries is what turns a simple Arduino data logger into a basic oscilloscope. However, Python cannot perform certain tasks on its own, like graphing routines and serial communication, so we need to get a few libraries first. Luckily, if you have pip installed , installing these libraries is a breeze. If you don't, get pip first by following this tutorial here. Once pip is installed, open a command prompt and enter the following commands in order (one at a time):
pip install pyserial
pip install PyGame
Once both packages are successfully installed, we can jump right into our graphical application! While the serial package is pretty easy to understand, the pygame package is a bit more complex, so only the basics will be covered here. The first task for our Python program is to import the required libraries, which are pygame (for generating the graphical interface), serial (for Arduino communication), and time (for time delays). The next code block is for variable declaration and initialization, which includes booleans, strings, and colors for pygame. The colors used in pygame are of type RGB, where three bytes (0-255) represent the amount of red, green, and/or blue.
With the variable definitions complete, the next task is to initialize pygame, which is done by calling pygame.init(). Since we plan on printing text to our windowed application, we also need to initialize the font engine, which is done by calling pygame.font.init(). In addition to initializing the font engine, we will also create a font object that we will use as the rendering font (which will be a monospaced font). The last bit of pygame initialization code will be to create a window (of size 700×500) and set the title of the window to “PyScopeUno”.
The next task involves configuring the serial port to use a baud rate that matches the Arduino (in this case, 115200). It is also necessary to select the correct port (in my case "COM8") and specify a timeout so that the program does not hang during the serial port loop. After configuring the serial port, the last step is to open the port!
After completing all the initialization codes, the main program loops, that is, in the form of a while loop, waiting until the Boolean variable applicationClose is equal to true. When the close button is clicked on the window, this value is set to true. After clicking, the serial port is closed normally and pygame is closed.
The first task in displaying the data we logged is to get the serial data from the Arduino. To do this, we wait until there is data present in the serial port. If this data is equal to "R?", we send the Arduino the character "K", which causes the Arduino to stream 100 bytes to the PC. The program waits until all 100 bytes are received, and once complete, transfers those bytes to the data buffer. The next lines of code involve some useful basic operations, including calculating averages and finding min/max values.
The final block of code involves plotting data, plotting text, and plotting lines, but due to the self-explanatory nature of the code, this will not be discussed in depth. The data in our oscilloscope program is not plotted as individual points, but as an interpolated line between two data points, because rapidly changing signals will appear as a scatter plot, which is difficult to visualize. To do this, a line is plotted where the first point is the first voltage level and the end point is the next data value. Since we are taking 100 readings but our graph is 400 pixels wide, we multiply the x-coordinate by 4 to stretch the graph. This makes it easier to see the individual readings.
The complete graphical program is shown below.
It should be easy and doable to get this project up and running in less than 15 minutes. The step that will probably cause the most headaches is installing and running the Python library, as the command line installation method has a habit of throwing errors, not being able to find required files, or missing permissions. Once the Arduino has loaded the code it will start automatically. Assuming the Python program works (make sure the COM port is correct), then the project should work fine.
Previous article:Differences and analysis between oscilloscope frequency response analyzer option and Bode plot test
Next article:The difference between oscilloscope and spectrum analyzer
- Popular Resources
- Popular amplifiers
- Keysight Technologies Helps Samsung Electronics Successfully Validate FiRa® 2.0 Safe Distance Measurement Test Case
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Seizing the Opportunities in the Chinese Application Market: NI's Challenges and Answers
- Tektronix Launches Breakthrough Power Measurement Tools to Accelerate Innovation as Global Electrification Accelerates
- Not all oscilloscopes are created equal: Why ADCs and low noise floor matter
- Enable TekHSI high-speed interface function to accelerate the remote transmission of waveform data
- How to measure the quality of soft start thyristor
- How to use a multimeter to judge whether a soft starter is good or bad
- What are the advantages and disadvantages of non-contact temperature sensors?
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- STM32F765@216MHz output I2S test ES9023P audio listening experience [code] [video] [firmware]
- MSP430F1101A MCU button and LED detection program
- 【Badminton Training Monitor Project】--Project Introduction and R&D Plan
- Application example of using 555 to realize timing function
- How does TI's battery management chip complete the development process and obtain mass production documents?
- 【Mil MYX-1028X】(IV) Network Communication Demo
- Today's live broadcast at 10:00: Introduction to ST machine learning, bone vibration, and SensorTile.box sensor development kit
- Network Camera Data/Port Forwarding Hardware Design Solution
- [Comic] Confession of a PCB layout engineer!
- How to distinguish between pads and vias_Differences between vias and pads