Introduction and background
On Ali, an interesting toy – an oscilloscope called DSO138 is sold for a very inexpensive price. It has already gained quite a lot of popularity among electronics lovers, but the parameters of this device, alas, allow it to be more or less fully used only for debugging very low-frequency circuits. Actually, it is not positioned as a tool, but rather as a DIY-kit for novice electronics engineers.
This "toy" oscilloscope is assembled on the STM32F103 microcontroller, and with a fairly competent circuit design of the digital part, the presence of a fairly decent 320X240-dot color display, and not the most rotten analog path, everything, alas, is ruined by very weak ADCs on board the 32F103. The claimed band of 200 kHz can be recognized as such only with a very large stretch. Yes, it will show the presence or absence of a signal with such a frequency, but it will not be possible to really look at something beyond this.
There are also a few more, so to speak, strange shortcomings. For example, a USB port is available, but it can only be used for power supply, it does not work for communication with the computer. The reason? Most likely, the selected core clock frequency does not beat with the 48 MHz required for USB to work correctly. Service functions, for example, zero calibration, without which it is simply impossible to use the oscilloscope, are implemented very inconveniently, and I also would like to have more service, for example, it would be possible to measure signal parameters using cursors.
At the same time, the 103-series has a slightly more powerful brother - the STM32F303, it is almost completely compatible with the legs, but it is significantly better in terms of the parameters we are interested in, there are 4 ADCs on board with a conversion frequency of 5 MHz (6 MHz with a 10-bit resolution). In this scenario, if you use all 4 ADCs in parallel with a 10-bit resolution, you can get a effective resolution of up to an honest 24 MSPS (millions of samples per second). The microcontroller is also inexpensive; you can easily find it on the same Ali for very reasonable money again. It is clear that the idea to change the microcontroller arose almost immediately after I tried this DSO138.
At the same time, if upgraded the toy can turn out to be a completely full-fledged tool that even professionals, not just novice amateurs, could already use. With these thoughts in mind, I decided to try to do something with a Chinese toy in my free time.
Mission statement or minimal requirements which I would like to achieve
So I set myself the following task – to get a tool suitable for debugging digital circuits with microcontrollers as a result of minimal reworking of hardware based on DSO138 and a new program, which would imply:
A band of at least 0 ÷ 2 MHz plus also ability to see the presence/absence of a signal with a frequency of up to 8 MHz (the popular frequency of quartz resonators used with microcontrollers);
The ability to use the USB port to communicate with the computer (save waveforms);
A normal service menu instead of a meager set of button combinations;
The DSO138 kit has two variants, just DSO138 and DSO138-mini. The second (mini) seemed to me more common and suitable for reworking. Its main difference is that there is a clear division into digital and analog parts (boards). This way I took it (DSO138-mini) and started to work on upgrade. The kit I’ve got included the digital board or as in the original Main Board of version I, and the Analog Board of version J.
In honor of the fact that the 303rd microcontroller is used, the project was named DSO303.
Digital part (board)
Digital part changes (Fig.1) are minimal and the following need to be done:
1. We cut one track connecting the R50 and PA7 of the microcontroller, and connect this leg of the R50 with a power supply of +3.3 V (Fig. 2 and Fig. 3). This is necessary for two reasons: the PA7 port is needed for one of the ADC inputs, the constant power supply to the R50 will allow us to use USB in the firmware loader mode.
2. Change the microcontroller to STM32F303СВ or STM32F303CC. The minimal requirements for the program to work are 128 kB of flash memory and 40 kB of RAM.
3. Connect together four ADC pads: PA0 (10), PA7(17), PB13(26), PB14(27). Fig. 4.
4. We also need to replace the EEPROM (Fig. 5) with any standard one, with a capacity of at least 32 kBit, but with 2-byte addressing (for example, the good old AT24C32 in a right package is quite suitable). Let's be honest, I didn't manage to deal with the Chinese EEPROM chip that is already on the board. This chip protocol turned out to be very different from any standard one. And then, in the process of program development, it turned out that at least 4 kB of non-volatile memory is needed to store calibrations and other data. Therefore, the chip that is on the board, and which has a capacity of only 2 kBits, according to some data, would still have to be changed.
5. We solder the 3-pin connectors to the serial port (bottom of the board in Fig. 1) and to the PA3 + GND port (top of the board in Fig. 1). The serial port can be used simultaneously and in parallel with USB for connecting to a computer and transferring data. The PA3 port is used as an input (analog!) to receive an external synchronization signal (trigger). The comparator input inside the microcontroller is connected to this port. The trigger level (threshold) is set programmatically in the oscilloscope menu.
The original DSO138 also had the ability to receive external synchronization, but it required a digital logic signal of the 3.3 V level.
ATTENTION: The synchronization signal is fed directly to the input of the microcontroller. The maximum permissible voltage in this case should not exceed 3.3 V. A negative voltage relative to the ground (GND) of the board at this input, respectively, is also extremely undesirable.
Analog part (board)
In the analog part, the TL084 operational amplifier with a bandwidth somewhere in the region of 4 MHz is used in the original. It is clear that if we want to at least see a signal with a frequency of 8 MHz, then this chip will also have to be changed to a more broadband one. Alterations of the analog part (Fig.6) are actually reduced to such a replacement and accompanying changes in the nominal values of the input path elements.
So, we change the TL084 to any quad amplifier with a band from 100 MHz in a right package. In my case, I settled on AD8054 (another option, for example, TL974). The bandwidth of these chips is 150 MHz, which is good, and for our purposes it is more than enough.
Further, it immediately became clear that the zero offset in the general case for the AD8054 is significantly greater, and, accordingly, it will not work to leave the amplifier input completely open without tightening the resistor to the ground, as in the original scheme, which actually led to changes in the circuitry of the input part. A 110 kOhm resistor was added to the input of the operational amplifier.
Further changes are to some extent a compromise between the desire to leave the printed circuit board as untouched as possible (nothing needs to be cut), and to observe the input parameters at an acceptable level. It is clear that in our situation, leaving a large input resistance in the range of 10 mV is an impossible dream. In the original scheme, an op-amp input without a divider was connected to the oscilloscope input at this range, and the input resistance was determined simply by the input resistance of the op-amp.
In our case, putting a large divider on this range of 10 mV is equivalent to an unacceptably large loss in the accuracy and quality of processing this signal by ADC, or the need to introduce additional gain in the path in some way, which leads to already significant alterations of the board. Therefore, assuming that the main area of our work is digital circuitry, for which this range is not the main working one, I limited myself to just dividing by 2 at this range, which is further compensated in the program, and an input impedance of 200 kOhm, which is of course bad, but acceptable.
Another compromise solution is to make the input resistance of 1 MOhm for the 1V range, which would allow using a probe with a 1:10 divider on this range, as for the 0.1 V range I considered it to be not so relevant. At the same time, for the range of 0.1 V, the input resistance is 660 kOhm, which is also bad, but acceptable.
In any case, I believe that everyone has the right and is free to do this part at their own discretion, the proposed solution is only one of the possible options.
Depending on which amplifier will be used, it may be necessary to add another converter to the power supply circuit of the op-amp to obtain a negative voltage in parallel with the existing one. The circuit in the original schematics uses ICL7660 to obtain a negative voltage. This chip allows parallel connection of an unlimited number of such converters to increase the output current. If it turns out that one ICL7660 converter is not enough to power the selected op-amp, then another ICL7660 chip with two 100 mkF electrolytic capacitors connected similarly to U2, C12, C13 will need to be installed on the free space on the board, and connected in parallel to the existing one.
To check the need for such an installation simply measure the voltage value "V -" at the TP8 control point, ideally this voltage should be at least -3V, even better - -3.5 V. If the measured voltage is significantly less, then it is necessary to put another ICL7660.
Well, now we turn to the most delicious for me – to the firmware…
The main idea was to implement as many actions as possible to process the input signal in an "iron" way and not load the microcontroller core itself with this, which would guarantee, for example, that all digitized data would be consistent in time. Thus, the data collection scheme looks like this:
According to the signals from the timer capture/compare blocks (TIM1 CC1...4) with fixed time shifts, ADCs 1...4 are started, each from its own signal (there is such a possibility in the matrix of internal connections of the microcontroller);
Data after digitization are written to buffers by DMA;
The program learns about the end of the buffer set by an interrupt from the DMA controller;
During internal synchronization, the trigger is generated by the ADC2 analog watch-dog comparator unit;
During external synchronization, the trigger is given by a COMP2 comparator, one input of which is supplied with a synchronization signal, and the other with a voltage from one of the DAC channels, which allows you to set the trigger level.
At the same time, the program turns in an infinite loop:
Check control (signals from buttons and switches);
If something has changed – update the screen;
If ready for a new cycle - start data collection;
If the data are ready – process the data, update the screen, set the readiness flag for a new cycle;
Since synchronization requires a front, which can be both rising and falling, and the signal from the analog watch-dog of ADC is only potential, then during internal synchronization it had to be brought to the input of the timer ETR1 TIM8 to allocate the fronts. And then track the trigger by interrupting the timer.
Further, I decided to simplify the program in the way that all 4 ADCs will always work, even on long scan times, when one ADC would be quite enough. This may be useful, since in this way you can quadruple the effective sampling rate for slow scans, which can help, for example, when searching for "needles", or for looking on the slope of noisy signals.
In principle, everything looked quite smooth on paper… With 10-bit digitization, 12 clock cycles per count were obtained at a frequency of 72 MHz, which gave 72 MHz / 12 * 4 = 24 MHz (24MSPS) digitization, or 24 points in 1 microsecond, with 4 ADCs working with a shift in parallel.
Everything worked fine on slow scans, but when trying to get the maximum speed, problems started to appear... To begin with, it turned out that the ADC offset changes with increasing sampling frequency, and it needs to be calibrated for each digitization frequency separately and, in addition, quite often. But the main problem was that there were clearly visible gaps in digitization, which led to a complete mess when putting together data from different ADCs. Moreover, as the frequency of the input signal become higher and the interrupts from synchronization (triggers) become more frequent, the picture become looking uglier and useless.
It would seem that due to the matrix structure (Fig. 7) and the division of RAM into two blocks, the processes of reading data from the ADC by DMA (S3, S4, M2, M5 are used), and the work of the main program, which at the same time uses everything else, but "practically" does not overlap with the resources that are currently used by DMA, should quite quietly coexist simultaneously.
But, alas, in fact, those operations that occur when processing data synchronization triggers, and after an interrupt, as it is necessary to access both the ADC block and the DMA controller to read the current counter (taking into account the fact that the DMA buses are loaded either 8 clock cycles out of 12, or 12 out of 12, how many exactly I could not find out), turned out to be enough to spoil the picture.
The ADCs have a second mode of operation, when they work in pairs with a fixed shift. At the same time, it is possible to read a pair with only one operation, which should dramatically improve access to the bus. Said and done. For modes with fast scanning (faster than 5 microseconds per div.) I’ve made a variant with paired ADCs. It didn't help… The picture has become better, in the sense that the failures now began to go like waves, but still nothing good. Then I looked at Errata, ups, just right in my case, the pairwise operation of the ADCs with DMA readout for large sampling frequencies is not guaranteed! It is proposed to use the ADCs in single mode only. The situation turned out to be almost a stalemate.
After much thought and attempts to do something, the idea came to my mind that since failures now do not always occur, and access to the DMA controller now does not lead to fatal consequences (the bus is now unloaded!), then you can try to simply monitor the occurrence of a failure by comparing the counters of different DMA channels constantly, and simply repeat the data collection cycle if this failure was detected in the process. This tactic turned out to be acceptable. The failures still remained, but at least something became more or less visible.
Final result is shown on Fig.8. Input signal is meander with 1 MHz frequency.
The 2 MHz signal is also quite clearly visible, but it will not be possible to see the details at all. The presence/absence of a signal can be easily seen for sufficiently high frequencies, at least 25 MHz on the quartz resonator output is clearly visible (Fig. 9). At the same time, we observe a very insidious effect of beats between the sampling frequency (in this case, 12 MHz) and the signal frequency – 25 MHz, which necessarily occurs if the sampling frequency is a multiple of the signal frequency. The signal looks like it has a frequency of 1 MHz, but this is just the difference between the doubled sampling frequency and the signal.
Also note that the probe had to be put in the 1:10 position, since the input resistance of 180 kOhm, connected directly to the quartz resonator, naturally disrupts the generation. The division coefficient is obtained in this case like this (9.1 MOm + 180 kOhm) / 180 kOhm = 52, i.e. there are approximately 520 mV in the cell.
The Russian soul always wants something more than what is achievable. Having estimated the theoretical maximum achievable sampling rate from the point of view of the ADC input, as this is determined by the minimum opening time of the ADC sampling unit, which in our case is 1.5 clock cycles x (1/72 MHz) = 20.8 nanoseconds, which gives 48 MSPS, I began to think, is it possible to achieve this somehow with the existing hardware?
And so, in the end, it appeared to be possible, through some, but quite legitimate focus, to jump over my head and get for some not all of course variations of the input signal, an effective rate of 48 MSPS and a scan times of 500 and 200 nanoseconds per cell, not without artificial artifacts (Fig. 10), but sometimes absolutely clean (Fig.11)! But, this works only for correctly periodic signals, and it is not possible anyway, alas, to look at signals with a frequency above 2 MHz in this way. But this is discussed more detailed in a separate publication…
I want to recognize the result as a quite good. I am ready to share with everyone (for now for free) the program and the instructions for it. A few words about the economics:
DSO138-mini costs from $13 on Ali (complete with a probe and a case somewhere in the region of $20);
STM32F303CBT6 is from $4. (also on Ali);
AD8054ARZ is from $0.5 (in the same place);
ICL7660 is from $0.5. for a batch of 5 pcs. (in the same place);
The rest is not more than $1;
The program is free for now, if there would be a commercial interest, i.e. a large number of people who want to, then I will take money for the license, but not more than $15.
Thus, you can get a price tag of $30, in a maximum $40 for everything. Something similar in terms of characteristics and the possibility of using for debugging of microcontroller devices is likely to be a USB set-top box to a computer, and not a full-fledged autonomous device, and with a price tag in the region of $100.
If you are interested, please write to me, I am ready to answer all your questions and share the program…