1
\$\begingroup\$

I'm working on a personal project which consists on a keyboard that also serves as a hub in order to connect more keyboards. For example, I could have the main keyboard with the letters and symbols and attach to this one another one that has the numbers. Another example could be a keyboard that is split into two pieces: left and right. The left piece will be connected to the computer and the right piece to the left piece. I know that most of the people do split keyboards using the I2C bus but I would prefer to use USB for better flexibility. The first challenge I have to solve is how to pass the signal from right to left. I have thought to use a USB HUB controller so each piece will have an Arduino micro which output will be connected to one input of the USB HUB controller and then the output of the HUB controller will be the output of the keyboard. The rest of the ports will be used to connect other pieces of keyboard or others peripherals.

schematic

simulate this circuit – Schematic created using CircuitLab

Of course, all the keyboard modules will be built the same way so I can connect 3 of them in series and just the last one to the computer. I would like to have one input and one output in each side of the keyboard in order to get less messy with the cables:

schematic

simulate this circuit

The problem with this solution is that I would need a lot of USB type C ports and someone who is not used to this keyboard could connect output to output for example. The ideal solution would be to have just one USB on each side that can be used as input or output. So my question is: Is there a way to make a USB port IN or OUT depending on if it is giving power or receiving it? I was thinking to use the FE2.1 USB HUB controller and some kind of USB switch but I'm not sure if this is possible. Any suggestion will be appreciated.

PS: My experience in electronics is pretty low so sorry for all the stupid things I have said.If something is wrong or is difficult to understand just let me know and I will edit it.

EDIT 1

I have chosen the USB C because it's very thin (the keyboard needs to be portable), it does not care in which direction you try to connect the cable and, as far as I know, it's supposed to be more durable than the micro USB port.

The keyboard will be made by me, it's not an adapted keyboard so the Arduino will be used to handle the button matrix. All the keyboard modules will be made by me in the same way so all of them will have an Arduino and a USB HUB.

It's a personal project and I think that is more elegant to use just one USB per side (I will be spending some money and a lot of time in this project so I want it to be as good as I'm capable of). Using two different types of USB ports in each side is a solution but, if I can, I would like to have just one in each side.

EDIT 2

I think the best solution would be this one:

I would recommend looking a development kit for a usb type-c hub chip or chipset which is able to automatically switch ports from upstream or downstream, then you can leave all the gory details of usb-c to them and get on with building your usb peripheral.

And if I'm not able to find a usb controller like that or is too expensive this one:

just provide connectors on all sides and have them switch type host/device depending on where the power is coming from. (use USB switch chips)

I just want the connector to be USB C, I don't care which protocol is running under it. It's thought just to connect keyboards so anything should be fine.

\$\endgroup\$
  • \$\begingroup\$ use USB type A jack for an input and any other type jack for output ..... that way you cannot plug two inputs together or plug two outputs together ......... USB type C seems too fragile to use on a device that gets moved around a lot (i could be wrong on the fragility of the connector) \$\endgroup\$ – jsotola Jan 26 at 20:14
  • 1
    \$\begingroup\$ It might be very useful conceptually if you start using official USB terminology, where there are no input/output, but "upstream" and "downstream" ports. This will help to clear a lot of misconceptions. Also, keep in mind the the use of hub hierarchy in USB framework is limited to five hubs in one linear branch, so your idea might have limited expandability. \$\endgroup\$ – Ale..chenski Jan 26 at 20:24
  • \$\begingroup\$ I don't understand why, if the keyboard modules have an USB connection, and the identification protocol to talk with the PC, why do you need an arduino and why you can't simply plug them in a normal hub? \$\endgroup\$ – Fredled Jan 26 at 20:36
  • \$\begingroup\$ Now if only the main module has a USB chip (for simplicity and lower cost), then it doesn't make sens to use USB jacks and wire. Use the common I²C interface which can be plugged in and out with other type of jacks. This will expand the number of connected devices to 256 (If I remember correctly). \$\endgroup\$ – Fredled Jan 26 at 20:41
  • 2
    \$\begingroup\$ Simplest solution would be to make the upstream cable captive, as indeed most keyboards do. For the downstream ports, you probably want USB power switch chips (which are not part of the HUB IC) with some enable logic driven by the USB-C mode resistor. Trying to make it safe against misconnection shouldn't be that hard; trying to make it so that either side can be used for the upstream port may be impractically difficult. \$\endgroup\$ – Chris Stratton Jan 26 at 21:17
1
\$\begingroup\$

just provide connectors on all sides and have them switch type host/device depending on where the power is coming from.

(use USB switch chips)

\$\endgroup\$
  • \$\begingroup\$ If I'm not able to find a USB HUB controller that handles by itself which port is being used as upstream or downstream probably this is the best solution. Thanks! \$\endgroup\$ – edoelas Jan 26 at 21:06
  • \$\begingroup\$ you won't you'll need to detect that with analogue circuitry \$\endgroup\$ – Jasen Jan 26 at 21:35
  • \$\begingroup\$ I've been searching for a while for a switch suitable for my needs but I haven't been able to find anything. Do you know about any circuit that could be useful? \$\endgroup\$ – edoelas Jan 26 at 21:40
  • \$\begingroup\$ @edoelas, look up "MCHP FlexConnect" hub controller ICs \$\endgroup\$ – Ale..chenski Jan 26 at 22:57
  • 1
    \$\begingroup\$ @james, the OP wants too much without any understanding. He wants an universal switch, where any port may become an upstream port (if plugged into USB host) and all other ports automatically become downstream ports. So all identically-looking Type-C ports are acting properly regardless where a user plugs his PC in. This is asking too much. It is technically doable, but no such thing exists. \$\endgroup\$ – Ale..chenski Jan 28 at 0:12
1
\$\begingroup\$

There are copious examples of USB keyboards with hubs in them. You don't need the complexity you are describing.

If you have a USB keyboard (your device with only half the keys on it) then it works with the standard driver ….you simply never get to hit the keys that don't exist on it. If you plug into the USB port on your keyboard another keyboard device with the other half of the keys, then that will work too giving you the other keys. It does not matter to the keyboard driver that multiple keyboards exist, and the key values are all treated as the same stream by the 'OR' logic of the driver.

You DO NOT need to be conscious of in versus out, they are simply devices in the USB tree that load the required service/driver.

You can try this out for yourself by getting a keyboard with a USB hub in it (for example this Logitech keyboard has passthrough). You only need USB Type A plugs on your devices. Plug another keyboard into the hub on the first and you have what you want. They tree can be extended to many levels deep (the USB spec quotes 7 layers deep including the root Hub).

\$\endgroup\$
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. Any conclusions reached should be edited back into the answer. \$\endgroup\$ – Dave Tweed Jan 29 at 13:10
1
\$\begingroup\$

There is a simple solution to your problem: don't use type-C connectors.

Since your keyboard is going to be, at best a high speed usb device, you can use Type-A and Type-B (or, better, micro-B) connectors.

Your upstream (hub like) ports will have the type-A connectors on them, and your downstream (device like) ports will have type-B connectors on.

Since neither A to A, nor B to B cables should exist according to the USB standards (and the ones that exist are rare/specialized), you can rest easy knowing the only way the modules would likely be connected is the correct way.

If you think about it, a (non-type C) USB hub has exactly the same problem, which it solves exactly the same way.

Since your devices are likely to only have one upstream port, you also can't have the user make a loop.

-- edit, since you say you want to use USB C --

If you're determined to use USB C, you can use captive leads to distinguish your upstream ports (captive cable) from your downstream ports (socket).

If that doesn't appeal to you will need to determine if the port is an upstream port or a downstream port and route it appropriately you'll also need to do at least a minimal amount of PD negotiation. The only devices which I've seen which are able to do this are USB-c docking stations.

I would recommend looking a development kit for a usb type-c hub chip or chipset which is able to automatically switch ports from upstream or downstream, then you can leave all the gory details of usb-c to them and get on with building your usb peripheral.

If you don't mind about not being fully USB-C compatible the minimum you could get away with is a usb 2.0 hub, some sort of usb 2:1 multiplexer (an analog switch, or a dedicated IC, plenty exist to handle the fact usb-c can be turned over) used as a multiplexer between your usb 2.0's upstream port, and one of it's downstream ports, and the a microcontroller which monitors the CC1 and CC2 lines of all the usb-c ports and sets your multiplexers appropriately.

It's a fairly hard problem, but doable.

-- edit after failing to find any suitable development kits --

I had a look at cypress, via, and on semiconductor, none of them have a usb hub offering that does both upstream and downstream USB (plenty do dual role for power) on a single port, so I think that leaves you with the usb 2.0 switch solution. Which would look something like this:

schematic

simulate this circuit – Schematic created using CircuitLab

Note there's a lot missing from this schematic, but with a uP that has switchable direction, pull up, pull down capabilities on its GPIO (yes the pull ups won't be correct for the USB-c spec, you can do better with some fet switches and the correct value resistors) you will be able to determine which ports are upstream and which are downstream, and signal appropriately.

Note when you implement this that you add a little randomness to your probing algorithm so you don't end up with ports hunting whilst they try and figure out if they're the upstream port. You'll need to do something to make all the ports identify as upstream ports when there is no power, as a USB-C downstream port won't power up unless it spots an upstream port. (The most budget way of doing that would with a couple of diodes from CC1 and CC2 to a rail which is clamped to zero until the system has power)

You keyboard controller and any other things you want to show up on the bus would hang off one of the (un-shown) other downstream ports on the hub.

-- edit more details --

Note - this is simplified - there are more sophisticated mechanisms used for communication on the CC1/CC2 pins and to arrange power delivery:

At start of day a usb-c DFP (downstream facing port, for example in your laptop) does not supply VBUS. It instead pulls the CC1 and CC2 pins high with Rp (36k to 3.3V, or 56k to 5.0V).

The UFP (upstream facing port to which it connects) pulls CC1 and CC2 low with Rd (5.1k). The cable has one wire for CC1/CC2, and can be inserted in one of four ways to connect CC1->CC1, CC2->CC2, or CC1->CC2, or CC2->CC1 ).

When the DFP port sees one of CC1 or CC2 pulled low by Rd it applies power.

The point of this design is so that if you connect UFP ports together the don't both try to supply power to each other.

You deisgn your board so that, unpowered, it pulls CC1 of each USB connector low with 5.1k, and leaves the inputs to the mosfets floating.

When an cable from an Downstream facing port (like your computer) is connected, the DFP will detect your port signalling that it an upstream facing port and apply the power.

The power will flow through the diode, and power your circuit, but it won't flow out through any ports as your mosfet is disabled. Your arduino will boot and will look at all the CC pins to work out which port is the upstream port that has been connected. Once it's done that it'll switch the multiplexer to connect the D+/D- for that port to the USB hub's upstream port.

Next it'll pull up all the CC pins on the remaining ports and look for exactly one of CC1 or CC2 being pulled low. When it sees that it can enable the mosfet on that port and begin supplying power.

You might want a circuits like the following to interface the each set of CC pins to your uP.

schematic

simulate this circuit

(again lots omitted in that schematic, if your uP can cope with 0.1mA without going into SCR latchup you can omit D3)

With your uP unpowered, the downstream facing port (in your computer) applies 5V through 56k to CC1 and CC2. The cable only connects one of CC1 or CC2.

C1 charges, and turns on M1 (you need to make sure M1 is fully on with just 0.8V on the gate). This pulls down CC1 with 5.6k. The DFP applies 5V to Vbus and your uP powers up.

Your uP enables weak pull ups on GPIOS A-C for every port.

The for each CC line (2 per port) it looks at GPIO B. When it finds a port with one GPIO B < 1V, and the other GPIO B ~ 5V, it knows it from the upstream port, and it flips the multiplexer to connect D+/D- to the hub's upstream port.

It then for all the other ports CC lines it sets GPIO A be an output driven high (to start looking for devices), and GPIO C to be an output driven low (to stop indicating that it's a downstream port). It then scans GPIO B and looks to see if exactly one of GPIO Bs is < 1V for that port, when that is true, it switches on the Vbus mosfet to provide power.

If on the original upstream port, GPIO B goes high the device should disable all the mosfets and, set all the GPIOs to high impedance and start looking for a new upstream port (or more likely lose power)

(The complexity of this circuit is to enable it to do the right thing even when your uP is powered off and its protection diodes are pulling all of its inputs low.)

\$\endgroup\$
  • \$\begingroup\$ I think a USB HUB chip that is able to switch from upstream to downstream automatically is my best option, but I do not know any integrated like this. Thanks! \$\endgroup\$ – edoelas Jan 26 at 21:00
  • \$\begingroup\$ They certainly exist as a least one HP docking station I have has 3 USB-C ports any one of which can be upstream and the rest of which switch to downstream, I'll have a look to see what chipset it uses. \$\endgroup\$ – james Jan 27 at 1:10
  • \$\begingroup\$ Thank you james, this is the solution that I will use for my project, this information is really useful. I just have one doubt: What is a uP? I was not able to find anything on the internet. \$\endgroup\$ – edoelas Jan 27 at 14:47
  • \$\begingroup\$ uP is a microprocessor, you'll need to program it with code to interface with the CC pins of your type-c connectors and then set the various Muxes and Power switches as appropriate. \$\endgroup\$ – james Jan 27 at 15:24
  • \$\begingroup\$ So could I use another Arduino or, if I have enough pins, the same that is being used to control the button matrix in order to accomplish that? I still do not understand why I need to use a diode and a mosfet to connect VBUS to the power and why I can't just use a diode on the cc1 and cc2 pins and when de current can pass through the diode the switch gets activated. If these are too many questions I will try to get the answers in reddit.com/r/AskElectronics so don't worry if you can't answer them. Thanks james. \$\endgroup\$ – edoelas Jan 27 at 16:56

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.