1
\$\begingroup\$

I would like to construct a simple device that plugs into a USB port and sends the computer a signal (i.e just a 1) when a user presses the button or switch etc.

I imagine there must be some way to take a USB cable and modify the side that doesn't plug into the computer so that it sends a signal when activated, perhaps by tapping a battery or something.

My goal is to build a simple button that I can use to perform a regular series of actions with a simple press. I know they sell things like this but it would be cooler and perhaps cheaper if there was a DIY way.

\$\endgroup\$
  • \$\begingroup\$ What is the desired latency of your button? I other words, how soon your host software affords to sense the button for your project? And what is the minimum time for de-pressing the button and pressing it again do you need for your purpose ("series of actions")? \$\endgroup\$ – Ale..chenski Sep 13 '16 at 16:48
  • \$\begingroup\$ There are a bunch of answers, some based on differeing assumptions. One of the discriminating criteria is "What is going to 'read' the signal from the USB button?", so what is it? Also what OS are you using? \$\endgroup\$ – gbulmer Sep 15 '16 at 5:03
  • 1
    \$\begingroup\$ @gbulmer I'm technically open to a bunch of platforms, so I'm glad people are making different assumptions since I want to choose the best blend of coolness and ease overall. I've got Windows and Linux, and I've got an Arduino \$\endgroup\$ – CodyBugstein Sep 16 '16 at 2:37
  • \$\begingroup\$ Thank you. Do you want something which you could read easily in a script, for example a '1' from something which looks like a keyboard, or are you okay with writing a program to open a serial device, and check its status with an ioctl, or are you okay with digging into log API's to detect USB failures? Or are you happy to write a kernel device driver? Can you estimate how quickly or frequently you might be pressing the switch? \$\endgroup\$ – gbulmer Sep 16 '16 at 2:49
  • \$\begingroup\$ @gbulmer I don't want to write a driver that's fotsure. I do want to write a script that could read the input - not necessarily as a keyboard but as a new device. I was thinking of just listening on the specific usb port it's plugged into \$\endgroup\$ – CodyBugstein Sep 18 '16 at 0:48
4
\$\begingroup\$

Aside from the practical solutions above, there is more diy hacky ways. Take apart a usb keyboard and remove the key matrix. Replace a specific matrix combination with a single push button (say an unused one like f8). Then use a software hot key program to carry out the rest based on that specific keyboard and key press.

The other way would be taking a mouse apart and doing the same. But a keyboard is simpler and with any recent cheapo one, the pcb would be about the size of a flash drive.

But a microcontroller solution can be done completely without any computer side software needed. Pure USB HID keyboard goodness.

\$\endgroup\$
  • 1
    \$\begingroup\$ I think this is the best advice for a "cheapest" push-button, maybe not the "coolest" one. Take a mouse out of plastic, wrap it into something with, say, duct tape :-), and leave only one (right side?) button exposed. Done. Some "gaming mouse" with dedicated driver will likely provide the response latency of 8ms on average, according to some studies of "motion-to-photon latency". \$\endgroup\$ – Ale..chenski Sep 13 '16 at 22:07
  • \$\begingroup\$ @alichen a usb microcontroller board can be had for less than a mouse, shipping included. \$\endgroup\$ – Passerby Sep 14 '16 at 0:06
  • \$\begingroup\$ Yes @Passerby, but then you're left with enumerating USB devices and handling them on the host OS. Cheaper yes, but much more involved to do in a non-hack-ish way. \$\endgroup\$ – rdtsc Sep 16 '16 at 11:50
  • \$\begingroup\$ @rdtsc usb hid is seamless and driver less on the host, and so many examples and projects exist for usb microcontroller that it is almost trivial at this point. Like hello world trivial. \$\endgroup\$ – Passerby Sep 16 '16 at 12:46
4
\$\begingroup\$

ATTiny + V-USB acting as HID keyboard. ATMega32U4 (e.g. Arduino Leonardo) acting as HID keyboard. PIC18F14K50 acting as, yes a USB HID device. There are a host of other USB enabled microcontrollers, those are just three I can think of off the top of my head.

You will need some microcontroller of some description capable of interfacing with USB. You can't just cut the end of the cable and hope to simply connect the wires together and get it to print numbers without some form of processor.

USB is a fairly complex protocol, so the best bet is to find something that will either do what you want (like a keyboard), or a microcontroller with a prewritten USB HID stack which you can then customise the code for to send key press info when a push button is pressed.

There are certainly sample codes available for the Leonardo board which can be used to send keystrokes to the PC.

\$\endgroup\$
  • \$\begingroup\$ I am offended by the omission of the usb msp430 acting as a usb hid device. \$\endgroup\$ – Passerby Sep 16 '16 at 12:54
  • \$\begingroup\$ @Passerby Sorry if I hurt your feelings ;) \$\endgroup\$ – Tom Carpenter Sep 16 '16 at 13:05
3
\$\begingroup\$

I would recommend you use a USB to Serial cable (or adapter, as they are often called). The drivers are easy to come by, and are typically installed automatically. You can then toggle the state of one of the control pins, such as CTS or RI using your switch. This will allow you to easily read the lines with a simple program on your system. You can toggle output lines to your circuit similarly, should you need to.

I did this myself to monitor a magnetic relay mounted on a door to monitor and timestamp entries to the lab.

usb to serial cable

\$\endgroup\$
  • \$\begingroup\$ I like that, as long as the OP can run a program to get that info. Nice. \$\endgroup\$ – gbulmer Sep 16 '16 at 0:49
2
\$\begingroup\$

I am assuming you want to work with existing USB device drivers across common operating systems, e.g. Windows (several flavours), OS X, and Linux. This would enable a program running on the host PC to open a file, and read the 1.

To send a 1 which is recognised by the host PC, you will need to exchange several message packets. It is not a simple one-bit, or even fixed multi-bit, signal.

Instead the host OS will request enough information from your USB 'button' device to figure out what type of USB device it is, and start the corresponding device driver.

You need to understand how USB works. This USB tutorial USB in a nutshell may help. It describes the protocol in enough detail that it is understandable how the host PC' will interact with the USB device.

To be easy to use, you will probably implement a HID device, which looks like a keyboard to the host PC. The button press could be made to look exactly like a keyboard 1. There are several projects which you can find by searching the web. They all use a microcontroller to manage the quite complex interaction with the host.

One example, which implements USB totally in software using a low-cost microcontroller is V-USB.

There are several other projects, some which do what you are describing, like PJRC's Teensy, and I digispark

Their are lots of MCUs which include a hardware USB interface. Typically they cost more than 1GBP. If you want to go down this path, most of the manufacturers of the USB-enabled MCU provide some sort of library, and their is also the Open Source 'LUFA' USB library.

Summary: the USB protocol is so complex that you will need a microcontroller to implement anything useful. USB is not a simple binary bit pattern.

Edit:
This V-USB stompbox looks like a close-fit solution, if my other assumptions are correct. It has a single button, emulates a keyboard, and is built on a piece of stripboard (veroboard) with an ATtiny and a few components.

You could use your Arduino to make an AVR ISP programmer. That would enable you to load the firmware onto the ATtiny, so it might be quite a quick, low-cost project.

\$\endgroup\$
  • \$\begingroup\$ It is indeed a good idea to read up on how USB works... as doing so would make it evident that you don't actually need any of this to send "a signal" recognized by the PC. \$\endgroup\$ – Chris Stratton Sep 13 '16 at 5:32
  • \$\begingroup\$ @ChrisStratton - really? How would you send a 1 without emulating a HID device? Or at least emulating a well defined device? \$\endgroup\$ – gbulmer Sep 15 '16 at 2:11
  • \$\begingroup\$ @gbulmer Short V+ and GND, detect the overcurrent event in software? (This comment is a joke, obviously) \$\endgroup\$ – immibis Sep 15 '16 at 3:31
  • \$\begingroup\$ @immibis - I did briefly consider that; not a dead short, but enough to trigger overcurrent. However, I've run workshops with people using Sony laptops, and they needed to cool and reboot. Windows can be very slow on 'plug/unplug', sometimes even needing a reboot. So I rejected both. However, as long as one only wants a fragile or specific solution, not a general purpose, cross OS solution, then yes either might be worth considering. I read the OP's question as wanting to send a 1 key code or character, which would be straightforward to detect and use on any common OS. It'd cost under $2 \$\endgroup\$ – gbulmer Sep 15 '16 at 4:13
  • \$\begingroup\$ @gbulmer no need to short anything. Merely a need to follow the advice you gave and actually read about how USB works - there are some mechanism on which USB relies that make this possible with only a cable and a resistor. \$\endgroup\$ – Chris Stratton Sep 15 '16 at 4:53
1
\$\begingroup\$

You could use something like this FTDI breakout board that allows you to easily interface via serial protocol over USB.

\$\endgroup\$
  • \$\begingroup\$ There are much better protocols for signaling a button press over USB than CDC or ACM. Such as, say, HID. \$\endgroup\$ – Ignacio Vazquez-Abrams Sep 13 '16 at 5:02
  • 1
    \$\begingroup\$ @IgnacioVazquez-Abrams - in actuality what is best depends on factors not stated here. For many, availability in the parts box and familiarity will be key. In other cases, the roadblocks various operating systems are still throwing up two decades in may dominate, and even apart from the USB aspect it is not a given that a multiuser operating system will make it easier to hook "user-ish" input than some other form of input. \$\endgroup\$ – Chris Stratton Sep 13 '16 at 5:37
0
\$\begingroup\$

USB has complex signaling indeed. But what many overlook is that USB also employs some very simple signalling. If you fully control the software on the computer, depending on your goals all you may actually need is to have your button connect a resistor between either of the data lines and VBUS.

Such a pull-up resistor is how USB peripherals signal their presence and which of the two base speeds they utilize. The operating system USB stack would then normally attempt to talk to the device using normal complex-state differential USB signalling and read out basic information such as VID/PID to determine which driver is needed. Of course in the simple-switch case this will fail but the attempt and failure is detectable from system log messages or via custom kernel code, and thus may satisfy your need.

Expect some latency and a low rate of repetition if using the stock USB stack, but custom kernel mode drivers can probably do this at rates that would feel prompt in human terms.

\$\endgroup\$
  • \$\begingroup\$ Latency for this proposal will be horrible. Connect latency in Windows is about 1s or more. In any case the connect latency cannot be smaller than "de-bouncing interval" of 100ms (mandated by USB specifications), and typically is 200-500ms, not counting for four non-enumeration attempts before some fault message is generated by OS. \$\endgroup\$ – Ale..chenski Sep 13 '16 at 17:06
  • \$\begingroup\$ These would be issues with a stock USB stack, and I did point out that that it would be slow if done through that. A custom USB stack however is not bound by the USB spec in terms of what it can choose to report to internal custom software, especially if these reports are independent of what it does with the USB bus itself. It is possible that some USB host hardware imposes some limitations, but things like 100ms intervals are best done by software, so not all that probable. This is posted more to point out what the "you need a chip" crowd is overlooking than as a recommendation. \$\endgroup\$ – Chris Stratton Sep 13 '16 at 20:15
  • \$\begingroup\$ I've used boards which use 'disconnect/reconnect', by dropping the 'Rup' USB pull-up resistor on one of the data lines; the devices do it to try to force the OS to 're-enumerate' the device. They don't work reliably on various versions of Windows on common machines (in UK schools). I've had machines 'refuse' to reconnect, and had to be rebooted. Maybe update your answer to include the provisos in your comments? \$\endgroup\$ – gbulmer Sep 15 '16 at 4:58
  • \$\begingroup\$ If they do not work reliably after being in the disconnect state for a reasonable amount of time, the host or its operating system is broken. But if ordinary USB peripheral insertion and removal works, then these devices are just too fast or not truly floating the line. Again, we are not talking about something automatic as in that case here, but something done manually, which is what USB detection is designed to respond to. \$\endgroup\$ – Chris Stratton Sep 15 '16 at 12:57
  • \$\begingroup\$ @ChrisStratton, then all variants of Windows are broken. \$\endgroup\$ – Ale..chenski Sep 20 '16 at 0:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.