I and the diode, or the new adventures of the mouse
As you may recall, not so long ago I soldered a capacitor to my mouse and joyfully reported on this landmark event . But it soon became clear that my joy was premature. So, I bring to your attention a continuation of the detective story.
No, the button did not crumble to dust, as one of the commentators prophesied. In general, none of those present guessed the fate of the long-suffering mouse, although, as I understand it now, it was almost obvious.
On a tip from a reputable ploop, I discovered the xev program , which, among other things, shows which buttons are pressed. I press the right button and see:
That is, whenever I press the right button (3), the mouse thinks that the left button (1) is also pressed! At this point, I remembered that after altering with this mouse it became impossible to call the context menu in the title bar of the Chrome window. Then I did not attach any importance to this, because at about the same time period the movement along the history with the “forward-backward” buttons fell off, moreover, only on the Habré / GT and only on the second mouse, with which I (my mother swear) did nothing.
Drinking out the capacitor, I was convinced - indeed, it was he who was guilty of pressing the extra button. And this put an end to the whole idea of a panacea for the bounce from the previous post. Since I did not want to choose between habrasuicide and a deal with conscience, I had to think about how to overcome this unpleasant side effect. So again we disassemble the mouse, cut the oscilloscope and try to achieve the very understanding that we did not have enough last time.
The mouse turned out to be based on the popularly known microcontroller nRF24LE1 .
By ringing, it was found that all the terminals of the switches go straight to the feet of the processor, and each such leg is connected to more than one switch. More precisely, the scheme looms like this:
(The button with an asterisk means the dpi change button, which does not go to the mouse output.)
This allows us to suspect the authors of the use of the technique called “matrix keyboard” . A signal is alternately applied to the scanning legs and looks at which reading legs it appeared. This allows you to save legs - because the buttons in this way can be set in proportion to the square of the number of legs used. (In this case, we have 6 buttons and 5 outputs - that is, a whole one leg is saved. However, I forgot to ring the wheel, so it is possible that the same circuit also serves the wheel, then it saves me two feet.)
But for now this is only an assumption, it is necessary to check it.We set crocodilesConnect the conductors P0 and A (in terms of the previous picture) to the oscilloscope. When you press the left button (1), we see:
An impulse lasting 20 microseconds (indicated by an arrow) is sent to P0, which comes to the A leg by a closed switch. This is not visible here, but the interval between pulses is about 10-15 milliseconds. This means that software protection from bounce is still present, and it becomes unclear how it turns out that it does not help. But back to our rams and release the button:
As we expected, the scanning signal on the read leg disappears. Now press the left and right buttons at the same time:
And again, in full accordance with expectations, at the output we get two signals from two legs, separated in time. If you now press the middle button, there will be three signals that merge into one big dash.
But how does it turn out that with two pressed buttons the scanning legs do not short with each other and do not spoil the signal to each other? In this article, it is proposed to use diodes for this. Everything is simpler here - when the leg is inactive, it is transferred to Hi-Z (high resistance) mode, that is, it is actually disconnected from the circuit, and no current flows through it. As evidence in favor of this, if the buttons are inadvertently touched by the scanning port while the buttons are open, the oscilloscope will show a characteristic “coat” (that is, interference from the radio broadcast received by our body):
To finally confirm our guess, we will put an experiment. If a button press is registered to increase the voltage, then if the scan port is shorted to power, the mouse should perceive this as pressing all the buttons on this port.
Again, everything is as we expected, plus Easter buttons 6 and 7 were found, which physically are not on the mouse (the wheel corresponds to buttons 4 and 5).
So, we learned the truth about the mouse and its buttons. But how does this help us cope with our original misfortune? To do this, we need to understand two more things - why the capacitor delays the release of the button and why it helps to press it when another button is pressed.
When we close button 1, the capacitor instantly discharges, and the voltage on it becomes equal to zero. While the button is pressed, the capacitor is shorted, so that the mouse perceives the press of the button as if there was no capacitor.
Now let go of the button. Since the capacitor has a capacitance, the voltage on it is still zero. So, if you apply a scanning voltage (2.5 V power supply) to P0, then at input A there will also be 2.5 volts, which corresponds to the pressed button.
However, with each such pulse, the capacitor will gradually charge (through the resistance R1). And at one fine moment it will be charged, say, up to 2 volts, and at input A there will already be 0.5 volts, which is not enough for a unit to appear at this input. Therefore, for some time after releasing the button, the mouse will think that the button is still pressed, and then “will understand” that it was released.
You can even approximately estimate this time. Our RC chainconsists of a resistance of 13 kΩ and a capacitor, for example, 0.1 μF. We multiply these two quantities and find a characteristic time of 1.3 milliseconds. But since the current does not flow all the time, but only 20 microseconds every 10 milliseconds, this time stretches to 0.65 seconds - as we intended last time.
It would be possible to rejoice at such an exact coincidence of the calculation with the experiment, but we still need to add another spoonful of tar. The thing is that the characteristic time is the time during which the voltage drops in the number e, that is, 2.7 times. But the datasheet on nRF24LE1 tells us that Input high voltage is 0.7 VDD, and Input low voltage is 0.3 VDD. That is, the inputs of our processor work as a Schmitt trigger, and so that they perceive the unit, we need to raise the voltage to 0.7 supply voltage. Why did we take 0.7, not 0.3, you ask? It is very simple - since the main part of the time at input A is pure zero, then at the time of the pulse we need to raise the voltage to 0.7 supply, otherwise the Schmitt trigger will not switch to unity. So the calculation gives the time
ln (0.7) / ln (1 / e) * 0.65 = 0.23 seconds.
But in fact, we have 0.6 seconds! If you subtract the time when the button is closed, it is 0.5 seconds, which is still a lot. To explain this, we can assume that in Hi-Z mode, the resistance of the leg P0 is still not infinite, and “quietly” mimics the capacitor in the interval between the measuring pulses. It is very rough from our data that we can estimate its value - since it discharges the capacitor in 10 ms comparable to the value it charges in 20 ms, this resistance is more than 6.5 megaohm.
And here we must recall one more fact, to which I did not attach importance. Namely, if you solder a capacitor smaller than 2 nF, the mouse will think that the button is always pressed. And now this fact gets an explanation - in 10 milliseconds the capacitor manages to discharge (2 nF * 6.5 MOhm = 13 ms), so that with a pulse the Schmitt trigger fires, and while this pulse goes, the capacitor charges (2 nF * 13 kOhm = 26 μs), but does not have time to charge to such an extent as to overcome the threshold of 0.3 supply voltage.
Now let's see what happens when we shake the right button, not the left one.
At rest, we have 2.5 volts on the capacitor. Close circuit breaker 3, and 20 microsecond pulses from port P2 will go to conductor A. But if on A 2.5 volts plus on the capacitor 2.5 volts, then on the leg P0 should already be 5 volts! And the controller is designed for no more than 3.6 volts. Especially for such cases, protective diodes are provided in the microcircuits so that the voltage at the inputs does not exceed the supply voltage:
Therefore, as soon as the supply voltage appears on P2, the capacitor is discharged through this diode, and it will already have 0.7 volts, or even less. And then it is still additionally discharged through 6.5 megaohms. And when the time comes for the measuring impulse on the leg P0, the voltage on the capacitor will be so small that at the input A there will be an almost complete supply voltage and, as a result, a clear unit. So we got the left button pressed while the right button pressed.
Now, finally, we have answered all the questions from the category of “who is to blame”, there is only a little left - what to do? Since the root of our trouble is discharging the capacitor, we put in the way of this current an obstacle in the form of a diode:
I found the first diode that came across, soldered - and indeed, unauthorized button presses no longer occur. That's just the delay after releasing the left button has disappeared. How so? And it’s very simple - as we already know, for operation at input A there must be at least 0.7 supply voltage, that is, on the entire “capacitor + diode” connection, there must be no more than 0.75 volts. And on the diode, as you know, about 0.7 volts drops, plus another capacitor - that’s not enough voltage.
The Schottky diode will help us , the direct voltage drop on which is noticeably less than on a conventional diode.
Unfortunately, I could not find the Schottky diodes, so I found the diode with the lowest voltage drop (the multimeter showed 0.44 V) and soldered it purely to make sure that the proposed solution works. You can search for it on KDPV (hint - it is black and pink). I also had to raise the supply voltage to 3.3 V, but nevertheless the desired effect was achieved! The button release delay is as long as 0.4 seconds, while no button is pressed “for company”. True, for obvious reasons, this design had to be dismantled, but the main conclusion was made - Schottky diodes will save the father of Russian democracy.
Here, in fact, is the end of the tale.
UPD: It turns out, and this is not the end. In kamenty rightly point outthat the above circuit with the diode cannot work, because the capacitor will not be able to discharge when the button is closed. And it worked, apparently, only because this capacitor was discharged through the resistance of the oscilloscope probe, which is equal to one megaohm. The following scheme is declared truly correct for today:
That is, it is necessary to cut the track on the board leading from the switch to the "scanning" leg and solder the diode into the resulting section. Well, or not necessarily to the scanning one, the main thing is that the current cannot flow to our scanning foot from any other scanning foot.
Probably, writing a third article on this topic is already too much, so if I am going to experimentally test this scheme, I will add it here.
No, the button did not crumble to dust, as one of the commentators prophesied. In general, none of those present guessed the fate of the long-suffering mouse, although, as I understand it now, it was almost obvious.
On a tip from a reputable ploop, I discovered the xev program , which, among other things, shows which buttons are pressed. I press the right button and see:
Oh God
ButtonPress event, serial 56, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 3959640285, (43,112), root: (1109,578), state 0x10, button 1, same_screen YES ButtonPress event, serial 56, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 3959640285, (43,112), root: (1109,578), state 0x110, button 3, same_screen YES ButtonRelease event, serial 56, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 3959640436, (43,112), root: (1109,578), state 0x510, button 3, same_screen YES ButtonRelease event, serial 56, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 3959640452, (43,112), root: (1109,578), state 0x110, button 1, same_screen YES
That is, whenever I press the right button (3), the mouse thinks that the left button (1) is also pressed! At this point, I remembered that after altering with this mouse it became impossible to call the context menu in the title bar of the Chrome window. Then I did not attach any importance to this, because at about the same time period the movement along the history with the “forward-backward” buttons fell off, moreover, only on the Habré / GT and only on the second mouse, with which I (my mother swear) did nothing.
Drinking out the capacitor, I was convinced - indeed, it was he who was guilty of pressing the extra button. And this put an end to the whole idea of a panacea for the bounce from the previous post. Since I did not want to choose between habrasuicide and a deal with conscience, I had to think about how to overcome this unpleasant side effect. So again we disassemble the mouse, cut the oscilloscope and try to achieve the very understanding that we did not have enough last time.
The mouse turned out to be based on the popularly known microcontroller nRF24LE1 .
By ringing, it was found that all the terminals of the switches go straight to the feet of the processor, and each such leg is connected to more than one switch. More precisely, the scheme looms like this:
(The button with an asterisk means the dpi change button, which does not go to the mouse output.)
This allows us to suspect the authors of the use of the technique called “matrix keyboard” . A signal is alternately applied to the scanning legs and looks at which reading legs it appeared. This allows you to save legs - because the buttons in this way can be set in proportion to the square of the number of legs used. (In this case, we have 6 buttons and 5 outputs - that is, a whole one leg is saved. However, I forgot to ring the wheel, so it is possible that the same circuit also serves the wheel, then it saves me two feet.)
But for now this is only an assumption, it is necessary to check it.
An impulse lasting 20 microseconds (indicated by an arrow) is sent to P0, which comes to the A leg by a closed switch. This is not visible here, but the interval between pulses is about 10-15 milliseconds. This means that software protection from bounce is still present, and it becomes unclear how it turns out that it does not help. But back to our rams and release the button:
As we expected, the scanning signal on the read leg disappears. Now press the left and right buttons at the same time:
And again, in full accordance with expectations, at the output we get two signals from two legs, separated in time. If you now press the middle button, there will be three signals that merge into one big dash.
But how does it turn out that with two pressed buttons the scanning legs do not short with each other and do not spoil the signal to each other? In this article, it is proposed to use diodes for this. Everything is simpler here - when the leg is inactive, it is transferred to Hi-Z (high resistance) mode, that is, it is actually disconnected from the circuit, and no current flows through it. As evidence in favor of this, if the buttons are inadvertently touched by the scanning port while the buttons are open, the oscilloscope will show a characteristic “coat” (that is, interference from the radio broadcast received by our body):
To finally confirm our guess, we will put an experiment. If a button press is registered to increase the voltage, then if the scan port is shorted to power, the mouse should perceive this as pressing all the buttons on this port.
We close port A
ButtonPress event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940208, (547,509), root: (1297,734), state 0x10, button 6, same_screen YES ButtonRelease event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940208, (547,509), root: (1297,734), state 0x10, button 6, same_screen YES ButtonPress event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940208, (547,509), root: (1297,734), state 0x10, button 1, same_screen YES ButtonPress event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940208, (547,509), root: (1297,734), state 0x110, button 3, same_screen YES ButtonPress event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940208, (547,509), root: (1297,734), state 0x510, button 2, same_screen YES ButtonRelease event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940253, (547,509), root: (1297,734), state 0x710, button 2, same_screen YES ButtonRelease event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940268, (547,509), root: (1297,734), state 0x510, button 1, same_screen YES ButtonRelease event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059940268, (547,509), root: (1297,734), state 0x410, button 3, same_screen YES
We close port B
ButtonPress event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059977818, (172,409), root: (922,634), state 0x10, button 7, same_screen YES ButtonRelease event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059977818, (172,409), root: (922,634), state 0x10, button 7, same_screen YES ButtonPress event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059977818, (172,409), root: (922,634), state 0x10, button 8, same_screen YES ButtonPress event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059977818, (172,409), root: (922,634), state 0x10, button 9, same_screen YES ButtonRelease event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059977950, (172,409), root: (922,634), state 0x10, button 8, same_screen YES ButtonRelease event, serial 166, synthetic NO, window 0xb200001, root 0x274, subw 0x0, time 4059977950, (172,409), root: (922,634), state 0x10, button 9, same_screen YES
Again, everything is as we expected, plus Easter buttons 6 and 7 were found, which physically are not on the mouse (the wheel corresponds to buttons 4 and 5).
So, we learned the truth about the mouse and its buttons. But how does this help us cope with our original misfortune? To do this, we need to understand two more things - why the capacitor delays the release of the button and why it helps to press it when another button is pressed.
When we close button 1, the capacitor instantly discharges, and the voltage on it becomes equal to zero. While the button is pressed, the capacitor is shorted, so that the mouse perceives the press of the button as if there was no capacitor.
Now let go of the button. Since the capacitor has a capacitance, the voltage on it is still zero. So, if you apply a scanning voltage (2.5 V power supply) to P0, then at input A there will also be 2.5 volts, which corresponds to the pressed button.
However, with each such pulse, the capacitor will gradually charge (through the resistance R1). And at one fine moment it will be charged, say, up to 2 volts, and at input A there will already be 0.5 volts, which is not enough for a unit to appear at this input. Therefore, for some time after releasing the button, the mouse will think that the button is still pressed, and then “will understand” that it was released.
You can even approximately estimate this time. Our RC chainconsists of a resistance of 13 kΩ and a capacitor, for example, 0.1 μF. We multiply these two quantities and find a characteristic time of 1.3 milliseconds. But since the current does not flow all the time, but only 20 microseconds every 10 milliseconds, this time stretches to 0.65 seconds - as we intended last time.
It would be possible to rejoice at such an exact coincidence of the calculation with the experiment, but we still need to add another spoonful of tar. The thing is that the characteristic time is the time during which the voltage drops in the number e, that is, 2.7 times. But the datasheet on nRF24LE1 tells us that Input high voltage is 0.7 VDD, and Input low voltage is 0.3 VDD. That is, the inputs of our processor work as a Schmitt trigger, and so that they perceive the unit, we need to raise the voltage to 0.7 supply voltage. Why did we take 0.7, not 0.3, you ask? It is very simple - since the main part of the time at input A is pure zero, then at the time of the pulse we need to raise the voltage to 0.7 supply, otherwise the Schmitt trigger will not switch to unity. So the calculation gives the time
ln (0.7) / ln (1 / e) * 0.65 = 0.23 seconds.
But in fact, we have 0.6 seconds! If you subtract the time when the button is closed, it is 0.5 seconds, which is still a lot. To explain this, we can assume that in Hi-Z mode, the resistance of the leg P0 is still not infinite, and “quietly” mimics the capacitor in the interval between the measuring pulses. It is very rough from our data that we can estimate its value - since it discharges the capacitor in 10 ms comparable to the value it charges in 20 ms, this resistance is more than 6.5 megaohm.
And here we must recall one more fact, to which I did not attach importance. Namely, if you solder a capacitor smaller than 2 nF, the mouse will think that the button is always pressed. And now this fact gets an explanation - in 10 milliseconds the capacitor manages to discharge (2 nF * 6.5 MOhm = 13 ms), so that with a pulse the Schmitt trigger fires, and while this pulse goes, the capacitor charges (2 nF * 13 kOhm = 26 μs), but does not have time to charge to such an extent as to overcome the threshold of 0.3 supply voltage.
Now let's see what happens when we shake the right button, not the left one.
At rest, we have 2.5 volts on the capacitor. Close circuit breaker 3, and 20 microsecond pulses from port P2 will go to conductor A. But if on A 2.5 volts plus on the capacitor 2.5 volts, then on the leg P0 should already be 5 volts! And the controller is designed for no more than 3.6 volts. Especially for such cases, protective diodes are provided in the microcircuits so that the voltage at the inputs does not exceed the supply voltage:
Therefore, as soon as the supply voltage appears on P2, the capacitor is discharged through this diode, and it will already have 0.7 volts, or even less. And then it is still additionally discharged through 6.5 megaohms. And when the time comes for the measuring impulse on the leg P0, the voltage on the capacitor will be so small that at the input A there will be an almost complete supply voltage and, as a result, a clear unit. So we got the left button pressed while the right button pressed.
Now, finally, we have answered all the questions from the category of “who is to blame”, there is only a little left - what to do? Since the root of our trouble is discharging the capacitor, we put in the way of this current an obstacle in the form of a diode:
I found the first diode that came across, soldered - and indeed, unauthorized button presses no longer occur. That's just the delay after releasing the left button has disappeared. How so? And it’s very simple - as we already know, for operation at input A there must be at least 0.7 supply voltage, that is, on the entire “capacitor + diode” connection, there must be no more than 0.75 volts. And on the diode, as you know, about 0.7 volts drops, plus another capacitor - that’s not enough voltage.
The Schottky diode will help us , the direct voltage drop on which is noticeably less than on a conventional diode.
Unfortunately, I could not find the Schottky diodes, so I found the diode with the lowest voltage drop (the multimeter showed 0.44 V) and soldered it purely to make sure that the proposed solution works. You can search for it on KDPV (hint - it is black and pink). I also had to raise the supply voltage to 3.3 V, but nevertheless the desired effect was achieved! The button release delay is as long as 0.4 seconds, while no button is pressed “for company”. True, for obvious reasons, this design had to be dismantled, but the main conclusion was made - Schottky diodes will save the father of Russian democracy.
Here, in fact, is the end of the tale.
UPD: It turns out, and this is not the end. In kamenty rightly point outthat the above circuit with the diode cannot work, because the capacitor will not be able to discharge when the button is closed. And it worked, apparently, only because this capacitor was discharged through the resistance of the oscilloscope probe, which is equal to one megaohm. The following scheme is declared truly correct for today:
That is, it is necessary to cut the track on the board leading from the switch to the "scanning" leg and solder the diode into the resulting section. Well, or not necessarily to the scanning one, the main thing is that the current cannot flow to our scanning foot from any other scanning foot.
Probably, writing a third article on this topic is already too much, so if I am going to experimentally test this scheme, I will add it here.