The history of one oscilloscope on stm32
A little over a year ago, the thought occurred to me that it would be nice to make an oscilloscope. Then I wanted it to be an independent device with its own TFT display, and indeed, the idea to deal with TFT displays seemed to me very promising. After some time, a 3.2-inch TFT with the SSD1289 driver was ordered on Ali .
At that time, I already had experience programming AVR microcontrollers , so I decided to launch the display on my favorite Atmega16. I didn’t know if it came to creating an oscilloscope, but I knew for sure that I would use TFT in my projects, so I didn’t look for third-party libraries, but decided to write my own, which I still use today.
After it was possible to initialize the display, it became clear that the Atmega16 could not make an oscilloscope. It is very slow for a display of this size. And something inside told me that it was time to switch to STM32, but it also stopped me. In general, the thinking process was short-lived and a board with STM32F103VET6 on board was ordered on Ali. But besides the reason described above, there was another reason to switch to STM32 - the built-in 12-bit ADC at 1Msps, which can be used to digitize the signal.
To my surprise, after several weeks of working with STM32, it became clear that there was nothing complicated in them and I no longer understood why I did not switch to them earlier. It was not difficult to transfer the code written for AVR to STM32, but the thought that I needed the display to work at maximum speed, and for this I had to deal with FSMC, was not restless . In fact, everything turned out to be simple here - it took me one weekend. On this, the preparatory activities with the display were completed and it was possible to proceed directly to the implementation of the oscilloscope.
The primary task was to learn how to display the signal on the display, for this I accumulated the required number of ADC samples, then displayed them on the screen, filled the screen with black color and so on in a circle. By the way, even then I used DMA to save data to the buffer.
The first step was taken and I was filled with joy and pride in the work done. Further, I wanted the sine wave to not run, but to stand, for this it was necessary to learn how to start the conversion of the ADC by the trigger.
This can be done using a conventional comparator, as shown in the diagram below.
Comparator on the op amp.
A reference voltage is applied to the inverting input, which is generated using a PWM and an RC circuit. And a direct signal is sent to the direct input, the same as that fed to the ADC input.
When the voltage at the direct input becomes higher or lower than the voltage at the inverse input, the polarity at the op-amp output changes. This change captures the MC pin configured for external interrupt. By changing the active front, for external interruption, it is possible to carry out a capture on both the rising and falling edges.
Further, in the interrupt, DMA is turned on and works until the buffer is full. Yes, it is DMA, ADC that always works in my implementation. A feedback resistor is necessary to increase the slew rate, and the op-amp itself is for this matter, it is advisable to choose faster.
After some time, the DSO 138 review caught my eye and from the same review I found out that its scheme is available on the Internet and decided to borrow a piece from there.
A fragment of a DSO 138. schema.
What does this piece of schema do?
The voltage range with which the ADC can operate determines the levels of the reference voltage ( + VREF and -VREF ), they should not go beyond the power range of the microcontroller. The lower limit of the range is limited to 0 volts, the upper - 3.3 volts. From this it becomes clear that the ADC cannotmeasure negative voltages, and this is necessary.
In order for the ADC to feel negative voltages, it is necessary that, in the absence of a signal, half of the reference voltage in our case is 1.6 volts. In this case, when measuring negative voltage, for example, minus 0.3 volts, the voltage at the input of the ADC will decrease by 0.3 volts and become equal to 1.6 - 0.3 = 1.3 volts. This voltage ADC easily digitizes. This example is approximate because it does not take into account the gain of the circuit (in this case, we took it for 1), but it is clear.
I also wanted to draw attention to the fact that the op-amp power supply is bipolar, this is necessary so that the op-amp can operate with a negative voltage. If the op-amp power supply is unipolar (0 is supplied to one power output and 5 volts to the second) and a negative voltage is applied to the input, the op-amp simply does not feel it and cannot do anything with it, like this.
To implement bipolar power, I used two charges from the phone, connecting the plus of one with the minus of the other, and took the potential of this connection as a reference point, that is, ground.
The circuit was assembled on a breadboard and now the oscilloscope could capture by trigger and measure negative voltages, I had no ideas what to do next in terms of hardware, so I switched to software.
At that point in time, I already had a clear understanding that the buffer should be circular, and the size was borrowed from DSO 138, that is, 4096 points.
Why so many points?
Such a number of points, using thinning, allows you to implement some scans that cannot be implemented in hardware. For STM32, the conversion duration is 12.5 cycles, in order to find the sampling period, add to the conversion duration a value that is determined by the SMPx bit field [2: 0]. At the moment, DSO 138 has reduced the buffer size to 1024 points, but I still have 4096.
So what is the ring buffer for?
An annular buffer is needed to change the ratio of the number of pre and post samples at fast scans. Prefetch - samples before the trigger is triggered, post-samples - samples after the trigger fires. The operation algorithm is as follows, after drawing the waveform:
- we accumulate the necessary number of pre-samples;
- enable external interrupts;
- MK starts performing some kind of third-party tasks until an external interrupt signal arrives.
Based on this signal, the buffer is supplemented with post-samples and the entire waveform is displayed.
The user can set the number of pre-samples only at fast sweeps, at slow immediately after capture points are drawn on the screen, bypassing the buffer. In fact, of course, there is a buffer, because it has become clear from time to time that it is unreasonable to paint over the workspace after each drawing, you can simply draw the same waveform only in black and restore the markup, thus reducing the time for drawing one waveform and disappear, such an unpleasant effect like a flicker.
The result can be seen in the video.
What could the prototype of the oscilloscope at that time? (And what could it be?)
You could change the sweep time, select the type of trigger, select the active edge, change the number of pre and post samples, change the trigger level, and also change the base level.
As for the type of trigger, in auto mode, everything happens the same way as in normal mode, except that if a signal does not occur within 100 milliseconds that causes an external interrupt, a timer interrupt occurs and the buffer is filled in it.
In order to implement the remaining functions, I had to return to iron again. And I think many have a question, why not zayuzat the entire circuit from DSO138?
It's simple, I wanted the attenuator to be switched by the electronics, not by the switches, and, most importantly, when the open input was changed to the closed one and vice versa, the relay clicked))
In general, I had the task to find the analog part that would meet my requirements. Actually, this is not an easy task, if not for one thing ...
At one point, I remembered that I had an oscilloscope, and its developer about a year ago answered me questions about its use in skype, in general, I decided to write to it.
After he told him about his plans to make an oscilloscope, he offered me several options for the analog part, I chose the most understandable scheme for me, asked him the questions I had, and set about implementing it. A few months later, the oscilloscope was ready.
As a result, it turned out to make an oscilloscope with the following characteristics:
Supply voltage: 9 V
Power consumption: 110 mA
Sampling frequency: 1 MS / s
Analog bandwidth: 0 - 200 KHz
Vertical resolution: 12 bit
Maximum input voltage: 50 V
Vertical sensitivity: 10 mV / div - 10 V /
div Horizontal scan time: 10 μs /
div to 200 ms / div Input impedance: 1 MΩ / 20 pF Input
modes: DC, AC, ground
Trigger - scan modes: auto, normal, one-shot You
can see the result in the video.