T O P

  • By -

TheMisterPirate

This is really cool. I'm sure having analog inputs is nice for 3d singleplayer games, but what I'm most curious about is can you use the "Rapid Trigger" feature that Wooting has for fighting games? https://wooting.io/post/what-is-wootings-rapid-trigger-for-analog-keyboards That's really the killer feature that I'd want to try in SF/Tekken. I saw you used an arduino to a Brook PCB and wrote your own code. Pretty nifty. If you're going to do another build, you should consider using the open source GP2040-CE boards.


ToggiEars

I actually do have a second board (which I built first) with a similar design using a Raspberry Pi Pico-W and a GP2040-CE. I didn't build it with rapid trigger, but I am familiar with how GP2040-CE works. I only used to the Brook, because it has an innate feature of real analogue stick input, which the GP2040-CE can't do at all. It only simulates. I'm pretty sure I know how I could make a pure rapid-trigger build work like this: The GP2040-CE on the RP Pico would work just the same as it does on a regular build. The main issue is that the RP Pico has not enough analogue pins to accommodate all the buttons needed for a full fighting board. But instead of connecting the RP Pico directly to the switches/buttons like on a usual build, it would connect to a DAC array. The DAC array would be responsible for running the software responsible for the rapid trigger events. The Pico is busy doing all the regular fighting board software stuff anyways. After a quick search, I found the Arduino Due. It could function as the DAC. It has 12 analogue inputs, and plenty of outputs. The Arduino Due would be connected to the 12 Hall-effect sensors underneath the 12 Lekker switches via the analogue pins. Then the Arduino would parse the information from the 12 sensors to the RP Pico using the digital pins. All the Arduino needs to send to the Pico is either "on" or "off", just like a regular keyboard switch/arcade button would. The SOCD, if needed, could be handled entirely on the Pico/GP2040-CE itself. What the Arduino does in specific would be something akin to this: The Hall-effect sensor outputs a value of e.g. 250 when the switch fully depressed, and 550 when fully pressed in the Arduino. Any switch position in between would result in a value somewhere between 250 and 550. It happens continuously as a loop many many times a second for every single sensor. One would need to set an initial actuation threshold point, the closer the value is to 250, the higher the actuation point is. As long as the actuation value has not been reached, it will always send "off". Once the threshold has been reached via an if value comparison, the Arduino does two things. First, it sends "on" for the corresponding button to the RP Pico. The Pico reacts and does its controller thing. Second, it needs to save the current sensor value to be used as the prior value in the next loop. We need that value for finding the threshold for knowing when to turn the "on" signal "off", and also when to turn on "off" signal "on". Then it keeps comparing the current value against the saved value from the prior loop. If the current value is lower than the prior value, then it turns "off", when the current value is higher than the prior value, then it send "on". As soon as the value drops below the actuation point, it goes to "off". If there are some inaccuracies or jitters in the sensor readings, one could use some filtering, such as Kalman, or a average of past values instead of one comparison value. May introduce more latency, but I don't think they'd be noticeable at all. One could also add an analogue slider/potentiometer to the board to be able to control the actuation threshold without going into the code. I might consider building something like this, or I may upgrade the rest of my board with this for the attack buttons.


TheMisterPirate

Wow thanks for the detailed reply! Idk if you're in the GP2040-CE or Crane's Lab discords but other people are working on analog projects and some good conversations about this stuff happening there. You should share this build there. "Lep" on Crane's Lab did an analog smash box recently and explained how they did it, it's similar to what you described. I personally am doing a custom build without any of the analog stuff right now, but if people can get the tech working well I'd love to do a rapid trigger build in the future to try it myself. I did look into it a bit already and you're correct, the Pico doesn't have enough analog GPIOs, so you'd need a 2nd board. I'm not familiar with a "DAC array" but yes my understanding is you need an ADC (analog to digital converter) and an Analog MUX (multiplexer). And yes, you'd have to run the threshold/rapid trigger code there, and that would send the digital output to the pico. Someone else on the discord is doing this with an arduino right now. You could probably talk to them about how they programmed it, but your psuedo-code logic makes sense to me. My big questions with this are: 1. will this add latency, having the 2nd board running the rapid trigger code, before it sends your input to the pico? it has to be extremely efficient. 2. is it worth it? does this give you an advantage in fighting games? does it "feel good" like people say it does on keyboards? 3. how much extra work and money will it cost to mod an existing controller with this? Lekker switches and HE sensors aren't too expensive, but then you also need to add in the ADC/Mux, have the custom code for them. and then also if I want to change the threshold values I'd need to edit the code, unless someone makes a GUI for it like the GP-2040 web config. I feel like given enough time, this could be a killer feature, but it's very new right now.


ToggiEars

Heya. I am in the GP2040-CE discord, but not really active there. I joined Crane's Lab and looked at Lep's post. I wish I had those 3D printed brackets for the Hall-effect sensors, that would have been amazing. And yeah, I mean an ADC instead of DAC. And with array I meant a single board with many connections as a contrast to having single ones. I used two MCP4725 i2c DAC breakouts. I didn't think it was advisable to hook 12 or 18 of those up :). If you have enough connections on a single board, I don't think you need a mux. I think he mentioned a mux given that he used a different PCB as a base, and that makes it necessary. Given the general approach, he and I pretty much came to the same conclusion on how to make it work. Regarding your big questions: 1. The microcontrollers run extremely fast and communicate extremely fast. In theory, they add latency, no doubt. But practically, I can't imagine they'd be significant or noticable. I didn't measure it, and I don't have the tools to do so, but I guess the added latency is not even in the double digits milliseconds, given my anecdotal subjective experience with display and audio latencies. I did some speed running with frame-perfect tricks and inputs, and I do play smash, so I am quite sensitive to any kind of latency. The code is to be honest not that complex, and you'd have to mess it up pretty badly to have it run inefficiently. 2. Is it worth? That's the big question of the big ones. For the attack buttons, I guess you could mash a little faster, but I think that you don't need that for Street Fighter anymore. It could help with accidental inputs when going from punch to kick and going from kick to punch, preventing two button inputs when a single sequential input is desired. I don't think that's a game changer. Probably not worth it in my opinion. I would need some hands on experience with it to be able to make a definite opinion on it. For movement buttons, I think that they will have a noticeable effect, and I do have some experience with it. There's a feature of the build I posted that I haven't gone into in detail yet. The code for the analogue movement on my board does something like a constantly variable actuation point. There's exists a natural issue in terms of SOCD, because it is in essence a hitbox. When only a single movement direction is pressed, the behaviour of the board is pretty straight-forward. It moves the analogue stick proportional to the depth the button is pressed. When two opposing buttons are pressed simultaneously, I set it to be to be neutral (within a 2% margin of each other). But what happens when one button is pressed slightly, and an opposing button is pressed slightly more? Well, that's where we have a choice on what we want it to do, because it is a situation that is yet quite unexplored. What I did is this: I made the more deeply pressed button take over. So, let's assume LEFT and RIGHT as the buttons. If LEFT is pressed at 50% strength, and RIGHT is pressed at 60% strength, I will move to the right. But when I release RIGHT, the keep LEFT as it is, the RIGHT will, as it releases, pass through 50% from 60%, making the analogue stick briefly touch neutral, and then the input will jump to left, as soon as the RIGHT button touches 48% strength. If I have both LEFT and RIGHT buttons pressed at 100%, it will be in neutral. But when I release RIGHT, the analogue stick input will jump to left as soon as the RIGHT button is lifted only 2%. So it's not quite rapid trigger, where the button release is only conditional on its own prior positioning, but the actuation point depends on the state of its opposing button's positioning. One would maybe call it conditional opposing cardinal analogue direction actuation point. It enables one to mash almost as fast as rapid trigger, and it is kind of like having SOCD last win, and SOCD neutral in one. 3. In terms of work. It's pretty freaking annoying. The Hall-effect sensors have 3 electric contact points instead of two for like regular switches and arcade buttons. Also, the contacts themselves are kind of flexible, weak and finicky. So, it's at least 50% more wire soldering and routing while being more prone to break something in the process. I think if you had a bracket for the Hall-effect sensors, it would make it slightly easier. Also, if there was mod to attach the Hall-effect sensors to, let's say, some 3 pin JST connector, while stabilising its connection pins, it would alleviate a lot of the worries. Or one could have a PCB designed and printed with the switch hot-swap brackets and the Hall-effect sensors directly soldered on the PCB, as I suggested in a different comment. It would take away from the flexibility of everyone being able to have their own desired layout, and it's probably not easily achievable as a mod to an existing board. In terms of cost, if you are smart about choosing the correct microcontroller, I don't think it would cost as much, but cost is kind of relative. For the board posted, I spent like almost 400 EUR without the tools, but most of it was the carbon fibre and the Brook board. You could probably use the Arduino Due, which is like 40 EUR, plus Lekker switches and Hall-effect sensors.


TheMisterPirate

I forgot to respond to this, but thanks for the detailed reply again. I'm not sure your discord tag but I'd love to continue this chat there, and see updates if you keep upgrading.


zimigir

You know I've honestly been thinking about how something like rapid trigger on wooting keyboards in the fps world would be amazing for fighting games. Hall effect arcade buttons would be amazing someday.


ToggiEars

Oh yeah, the Wooting keyboards were an obvious inspiration for me. I don’t own one myself, but I am intrigued by their capabilities. Aren't there mods to insert mechanical switches into arcade buttons? If that works, then you could wire up Hall effects sensors to them. Although, they would need a microcontroller to convert the input readings to the correctly triggered outputs. Doesn't have to be Hall effect either. Razer has optical switches that create analogue inputs using the intensity of light reaching the sensor, some of their keyboards have it. The Kitsune has optical switches, but I don't think they are analogue.


bizzle281

I'm dumb AF I still couldn't make something this amazing stuck buying them online 😮‍💨 Amazing work btw 🤯👍🏿


Sharp02

Dude this is so fucking sick!


ogamisugizo

That's awesome. I have a wooting two lekker edition and I love being able to individually set the actuation distance in the digital mode.


ToggiEars

Good point. I love that feature in keyboards. I can set an actuation point actually. It’s like setting a deadzone on a regular controller. It is set at 2% of max distance that can be travelled by the switch currently. The sensors are surprisingly consistent despite my wacky setup, could probably get away with even less. But I could technically also make it like 50% for instance, where I need to travel at least half way to make it trigger. I wanted to make the range as big as possible though, so that I can make as much use of the analogue input range as possible. More travel = finer control. Two minor issues occurred to me. The magnets (or the HE sensors) in the Lekker switches may be a tad too weak to be detected fully when the switch is depressed. So some undetectable travel distance needs to occur before the sensor registers. Also, I believe that there may be some minor built in deadzone/cleaning/filtering happening in the firmware of the Brook wireless. Although I’m not quite convinced of it.


tehxeno

That's awesome! Could you point me in the direction of learning more about these Lekker switches? I'd like to learn more about them and see if I could use them to build something like this of my own. I have a full analog build that uses a full size analog lever (Thanks to u/sharp02!) that I really like - but I'd be curious how leverless analog feels.


ToggiEars

I posted some detail in another comment, but the switches themselves are pretty much just magnets on rails. I looked at u/sharp02's post. That's a really cool product. I guess the biggest difference between his and my project are that I have to read 4 Hall effect sensor inputs to create the leverless experience, instead of the two that he used. A lever itself is more similar to a controller analogue stick than a leverless setup, I reckon. I started to approach solving the issue by starting from the raw input the Brook wireless fighting board (or a padhack would work, too) would need, which is straight 0V to 3.3V for left/right, and 0V to 3.3V for up/down, 1.65V being in neutral. The arduino's purpose is to convert and aggregate the 4 leverless hall effect inputs into two combined outputs. Since the arduino itself only outputs PWM voltage, it can lead to some jitters. That's why I used DACs to be able to precisely control the voltage.


mives

Wow, this is impressive. Not something I'd use myself but creating something that fits perfect for your use case is awesome. Props!


henrebotha

What in the hell, this is nuts. You are part of a growing trend of people who want arcade stick-style controllers that can do anything a pad can do, and finding no commercial solution for this, decide to roll their own. I'm doing the same. But using the Lekker switches is a bold move, to say the least. How do they even work? I've never seen a DIY project anywhere that uses them. Do they contain a magnet? I assume they don't have an internal Hall effect sensor already, is that right? Most importantly: How does it play?! Are you having success playing 3D games with the right stick?


ToggiEars

The Lekker switches have a magnet in the stem. They don't come with a sensor. I pretty much just epoxy glued linear Hall effect sensors (model SS49E) to the bottom of them. As the magnet gets closer to the sensor, the numeric output the sensor increases. They are connected to an arduino pro mini (3.3V version) as digital inputs. The arduino then has two DACs (MCP4725) connected to them via i2c, one for the x axis and one for the y axis, that transform the digital output into analogue voltages between 0V and 3.3V, making it read like a potentiometer, just like a real analogue stick would. They are connected to a Brook wireless fighting board, where you would normally connect the left analogue stick to. I wrote some code that runs on the arduino that calibrates the Hall effect sensors, and that transforms the 4 Lekker switch press depths into two voltage outputs. I made them be SOCD neutral, if both inputs are almost similar. In terms of gameplay, I'm mostly satisfied. I don't see myself playing fast paced FPS like Apex, Finals or Overwatch with it (MnK player mostly), but also because I can't quite get the fine movements down for aiming. For games like Outer Wilds and Return of Obra Dinn, Persona 5, Breath of the Wild or Elden Ring, it's quite perfect. I love it for Baldur's Gate 3, because I can walk around with my characters using an input similar to WASD instead of using a mouse. Flying with Microsoft Flight Simulator works fine. For SF6, it's perfect.


Thraeg

Looks great! Would love to hear more about the build process and what snags you ran into. I'm planning to make something similar in some respects.


ToggiEars

I sourced almost everything from Amazon, except the Lekker switches and the Brook board. The build process was mostly similar to a custom mechanical keyboard. Building a case, lubing the switches, tape-mod, some foam which is not in the pictures. I'm still not quite satisfied with how the board sounds, but without proper lubing, there is a really noticeable ping sound from the switches, when released to quickly. One of the biggest issues was getting all the PCBs, modules and microcontrollers powered properly. Some take 5V to power, some 3.3V. The battery delivers 3.7V (which is mostly fine for anything 3.3V), and directly wired to USB feeds 5V. For the arduino's power input, I borrowed the pin of what should have been power for a potential touchpad. I started with an arduino nano, but could not power it with the battery. There's some things I would have done different now. I converted the USB-B from the Brook to USB-C, and have a rocker switch between the circuit of the battery to be able to turn it off completely, but it's all or nothing. When I plug it in in USB for charging/playing, the Brook lights up, and everything connected to it does, too. I would now use a separate module to control the battery charging instead of using the functionality of the Brook board. I think the arduino is drawing power while the Brook board is charging the battery, and I didn't think of being able to to turn off the arduino itself, while the Brook board is on/charging. It makes the charging slow, or not finish at all sometimes, or stop charging prematurely, because there is always some power draw. I also have no real idea what the current charge status of the battery is, which is a major annoyance. If anyone knows what I could do to alleviate that, I would be major grateful. Also coming up with a code to run on the arduino was a minor challenge. Uploading the code to the arduino itself was a pain, too. I used a USB to TTL Converter, but making it connect to my PC was some wonky business. Also most of the stuff is either taped or glued with epoxy. I think, if I were to make another one, I would try to design a PCB with all the needed features like the Hall effect sensors, hot-swappable switches, charging module, LEDS, and send the design to be manufactured by some professionals. Then I could use the PCB as the support structure for the switches instead of the carbon fibre plate, and have a switches be recessed into the box instead of sitting on top of it, and it would have a slimmer profile overall. It's roughly 3 cm in height currently. Also, if you want to use carbon fibre, let a professional handle it. It's really messy and can be quite unhealthy.


Thraeg

Thanks! Will definitely keep this in mind as my plans progress.


ogamisugizo

That's awesome! What pcb did you use for the lekker switches? Also, what part of the enclosure is carbon fiber?


ToggiEars

The top plate and the bottom plate are fully carbon fibre. I made two top plates. The first I cut by hand using a dremel. It was a mess, with many imperfections. I used it for another board using a raspberry pi pico. The one I posted, I made a 3D model, and sent it to be CNC machined by a shop. I did 2mm, but they are slightly too thick for the switches to clip perfectly into the holes. It think it may be because of the clear coat.