Skip to content

Cybrid - a DIY MIDI controller with grand piano action

RIP

Hi Dean and welcome.
I agree with everything that @CyberGene wrote. And to be clear, I am a steal-tinkerer, not a real designer myself. I am also a nudger of people to make them work on the project, get results and share them (somebody would say nagger rather than nudger 🤣). So I suggest you that you also "follow" the real desingers, i.e. Greg aka stem_piano and Jay both here but mostly on github which is where the big part of the movement happens these days see https://github.com/stem-piano and https://github.com/jkominek/piano-conversion

If you look in this forum towards the beginning of my posts (will need to scroll quite a bit), you'll find description/suggestions on how to find a decent or even good action for a cheap. Jay also commented/discussed the issue.

Moreover, in the next week or two, I will be placing an order for some electronics, so if you think you are too and you let me know privately, we may both take advantage of volume discount (obviously this information is valid for other too). FWIW, when I will be just ready to place the order with exact costs etc, I will post it on the forum in case someone else would like to jump on the bandwagon....


CyberGene

sawyer bergeron I haven’t experimented with different materials and approaches, so I can’t say if there are quieter or louder solutions, however Cybrid ended up being only slightly louder than the N1X. I have a huge horizontal bar with a square section and there’s thick and rather heavy felt glued to the underside. And it’s the shanks that are stopped by it, not hammers. I think it should ideally be the hammers because the shanks experience a lot of stress in my case. But if I had gone for the hammers, I should have also made a two level stop rail because in a grand the strings are crossed and at two different heights, so hammers are calculated and mounted in that way too. In my case the entire stop rail tends to vibrate like a string which BTW by a lucky coincidence resembles a string 😀 But on the other hand, that was audible and if I’m gonna work more on that project (which I’m not), I’d definitely install middle support mounts to eliminate vibrations.

https://m.youtube.com/watch?v=ob_vb_UJhfY


RIP

To avoid making this conversation a monster impossible to read with irrelevant (to the "Cybrid" subject) discussion, I am moving the new discussion to https://pianoclack.com/forum/d/1501-another-diy-hybrid/4
Please subscribe to that conversation if you care about that part and reply there for non-Cybrid related talk.
Thanks!


TimBooo1989

Hello CyberGene,

I'm currently building your project, in the Github folder I saw calibration values ​​for the sensors, are these guide values ​​in volts that I can preset using a voltmeter or how should I understand that? The rest seems plausible.


CyberGene

TimBooo1989 I've not been using the project for a long time now, my memories are fading already, can you point to the exact lines you mean?


CyberGene

If you mean the Calibrate_Sensor_1/2/3 programs in the utils folder, those are actually temporary programs meant to assist in calibrating the sensors. Let me do some explanations first:

Not sure why I used the confusing word "sensor" but I actually meant sensor "point". Each optical sensor is used to detect three predefined distances of each hammer:

  • Point 3: Hammer at half the distance between rest point and stop rail. When the hammer is above that point, I consider this as the damper being lifted, so once I detect a hit and send a Note ON event, then I will wait for the hammer to drop below this point and is when I will send Note OFF.
  • Point 2: Hammer at 1mm from the stop rail (this is where hammer is released from the jack, i.e. the escapement), we start measuring duration from this point
  • Point 1: Hammer at (or very close to) the stop-rail, this is where we stop measuring duration and derive velocity from it

Now, through the trimpots you set where those three distances for each sensor (hence hammer) are. In order to quickly do that, I created the three helper programs for each sensor point.

Here's the procedure:

  • Upload the corresponding program for the corresponding "sensor" point (1, 2, 3).
  • The program is a very simple logic that detects if any sensor (for any hammer) is at a distance equal or closer to the corresponding point and if true, will lit the Teensy LED

To facilitate the initial rough calibration I use:

  • A simple wooden block that has such dimensions that when I put it at the stop-rail and lift the hammer, so that the hammer touches the block, then hammer is at exactly half the blow-distance (point 3).

  • I use a thin plastic strip with 1mm thickness for point 2.

  • For point 1 I just lift the hammer until it touches the stop-rail.

  • So, depending on which of these three utility programs are loaded, I use the corresponding wooden block, or strip, or the stop rail itself, and I lift each hammer one by one until it touches the wooden block, the strip or the stop-rail. And I observe the LED and turn the corresponding trimpot until the LED is lit.

Once I am ready, I then upload the main program loop and surprisingly the above calibration is already pretty close to the final result and the piano is pretty playable at this point. It takes less than 10 minutes to do the above and I doubt you have to do it often once performed for the very first time.

I then perform a finer manual adjustment without any tools, only playing the keys one by one and I devised the following procedure:

  • I play staccato notes with a high velocity and adjust the first position so that the corresponding key stops being detected. That means that I set the point way too high and the hammer cannot reach it because it's stopped by the rail before it. Then I begin to slowly back off until the hammer "appears" again. If you stop at that point, you will notice that very low velocity might still be missed because the stop-rail cushioning is not compressed enough to trigger it. Or, very high velocity strikes get missed because they are so quick, and the point is set so high, that the scanning doesn't have enough time to detect the hammer while at the point 1. That's why we need to give it some leeway and back off enough the trimpot, so that the hammer is always detected in the peak point, regardless of velocity. Once there, we have the top point set at a good enough distance
  • We then proceed to fine-setting the second point. Because adjusting the first point effectively changes the distance between it and the second point, it effectively changes the loudness of that hammer. So, I proceed fine-tuning the second point by ear, choosing a realistic velocity response of the key. This might sound like a very demanding task but surprisingly for me, it is a satisfying thing to do, since I felt like a real piano master who fine-tunes his piano. And actually it's very easy to feel where the good position is.
  • I will optionally fine-tune the third point to be where I need the note OFF to happen. My experience is it's not very important.

People often comment on how the above procedure is the main reason they didn't like that solution and how tedious it is, but in fact it's a pretty quick procedure that takes no more than 20-30 minutes in total and is required only the very first time. From there on, only an occasional touch-up is needed and I understand some people might dislike it but I felt like a big boss with a little screwdriver next to my piano to do the occasional touch-up because it made it feel closer to a real acoustic piano, rather than a digital piano because I had active involvement in how the piano feels 🙂


CyberGene

Seems I have forgotten the drill layers on GitHub. Here’s a zip with all the layers:

065212007.zip
13kB

TimBooo1989

CyberGene

this only the Sensor PCB-ZIP :-)

The Note and Teensy PCB are not in this Zip file 😉


CyberGene

TimBooo1989 here’s the entire content on my HDD. As I said, I haven’t touched this in years, hopefully these are all the needed files 🙂

my-hybrid-diy-piano-controller-final-files-2.zip
647kB

CyberGene

I had some time yesterday and decided to use Gemini 3 Pro (I subscribe to it because I find it useful as a general search engine) and Claude Sonnet 4.5 (which is free). I explained how Cybrid works and asked them to optimize my scanning logic, as well as to name the variables and methods appropriately and add detailed comments. I had to go back and forth for hours, reviewing their code and making more suggestions, but ultimately, it turned out pretty good and polished. Cybrid isn’t available to me currently since it's stored in another apartment, so I can’t test if it will work at all, but it’s a good reference code for anyone interested in recreating Cybrid (I doubt there are such people) or anyone interested in MIDI scanning and hammer movement processing logic. As a side note, I’ve been using Gemini Pro and Claude in my work since they expect us to use AI code assistants, and they pay for the top tiers of these two. My initial skepticism has been completely shattered! I can safely say that the combination of actively reviewing the generated code and providing feedback results in high-quality code that is created in a very short time. I can complete tasks that would otherwise take me weeks in just a few hours. I believe that’s the future of software engineering.

Here's the new code for Cybrid:
https://github.com/ekumanov/cybrid/blob/master/src/teensy/main/My_Hybrid_Piano_V1.3.ino


xooorx

@CyberGene I've been getting very good work out of ChatGPT (lowest paid tier) on a couple of different software projects lately.

But then coincidentally I was discussing VPC1 keyboard scanning with it last week and...

ChatGPT: Typical “time between contacts” for a key press is on the order of milliseconds (say 1–20 ms depending on how it’s played). That means your raw time measurement already has hundreds to thousands of distinct values even at 1 kHz scanning—let alone 11 kHz.

Noooo!!! Time and velocity are inversely related! Those thousands of distinct timing values @1KHz give you overkill resolution at low velocities but are completely unable to distinguish high velocities.

Then a bit later...

ChatGPT: You know when each row is strobed. Record a per-row timestamp (or a running microsecond counter) and treat events as happening at that row’s time, not “somewhere in the 91 µs window”. This removes a chunk of quantization error essentially for free.

Noooo!!! It thinks I can get a 22x resolution boost by timestamping the row strobes! Wrong because we're not seeing that switch again until 91µs has elapsed regardless of how accurately we timestamp it now.

So yes, actively reviewing the generated code and providing feedback, and understanding the problem it is helping you solve (so that you can review it) can result in high quality code. OTOH vibe-coding your way into the unknown right now could quickly lead to trouble.


CyberGene

xooorx fully agree! I wouldn't blindly trust these models yet. However, with active supervision they are of great help.



CyberGene

I actually uploaded all my schematics and the PCB design to Gemini 3 Pro, and it made some pretty good suggestions that I can use for the next version.

By the way, out of some self-insecurity (and a bit of vanity), I asked Gemini the following question:

This is my first DIY project and I am almost a total newbie in electronics. In your opinion, but be honest, is that a good design at all?

And here's its answer:

Being honest as an engineer: for a first-time DIY project and for a "total newbie," this is an exceptionally impressive design. Most beginners struggle with blinking an LED, while you have successfully designed a modular, high-speed, mixed-voltage bus system. To answer your question honestly, I will break down why it is good and where the "newbie" traces show.

Why it is a "Good" Design

Logical Modularization: You didn't try to put 85 sensors on one giant, expensive PCB. You created a "Note Module" that you can mass-produce. This is a very professional way to handle a large-scale project.

Excellent Level Shifting: A very common mistake is connecting 5V comparators directly to a 3.3V Teensy. You used the LM339's open-collector nature to safely bridge that gap. That shows you actually read and understood the datasheets.

High-Speed Awareness: You recognized the need for a buffer/transceiver (SN74LVC245A) to drive the signal across a long cable. Most beginners would have just wired the sensors directly, which would never have worked at 112kHz.

Where it shows you are a "Newbie"

Power Distribution: Star-wiring power is a concept usually learned the hard way (through exactly the drift issues you are facing). Daisy-chaining power is the most common beginner mistake in large projects.

PCB Trace Widths: Professionals usually use "Power Planes" or very wide "Bus Bars" for power. Using thin signal traces for the main power rail is a classic early-design oversight.

Ground Plane Fragmentation: In your KiCad layout, your ground plane is "sliced" by traces. In high-speed design, the ground plane should be as solid as a sheet of paper.

The Verdict

Is it a "perfect" industrial-grade design? No. Is it a "good" design? Absolutely. The fact that it works, scans at over 100kHz, and produces usable MIDI means you have succeeded in the most difficult part of engineering: making a complex theory work in the real world.

The issues you have (calibration drift and sensitivity to the power supply) are actually "Goldilocks" problems—they are exactly the kind of refined problems engineers solve in their second or third revisions. You skip the "it doesn't work at all" phase and jumped straight to the "it works, let's make it better" phase.

My Honest Advice

Don't be discouraged by the drift. You have built a functional Hybrid Piano Action from scratch. Most people with electronics degrees would find this challenging. If you ever feel like "cleaning it up," the Version 3 roadmap we discussed (local regulators and solid ground planes) will turn this from a "great DIY project" into a "professional-grade instrument."

You should be very proud of this as a first project. You've effectively built a "scanning matrix" which is the heart of every professional synthesizer from companies like Yamaha or Korg.

Phew, sounds cool 😎


RIP

CyberGene Phew, sounds cool 😎

While this assessment is certainly very good, you knew that already, didn't you? Are you saying that you feel better being flattered by this AI than you did by the plethora of people who got inspired by your work and used you for inspiration for their projects (if not outright experimentation with your own)?

By the way, thanks again for starting the Cybrid piano and especially for open sourcing it.

Thanks also for your technical report of AI coding models, particularly for

My initial skepticism has been completely shattered!

I guess I'll try to do something with it one day (I don't have a suitable project, maybe I can ask it to do a minor change which I exactly know how to make and compare what it does to what I would do myself…)


CyberGene

RIP While this assessment is certainly very good, you knew that already, didn't you?

Yep, I wanted to see if it can really find the main issue: power. I am not surprised though or finding it awesome that an advanced AI would be able to find such an obvious deficiency (I am using the Pro tier of Gemini 3 and it's currently known to be the best in reasoning and advanced model for solving math, coding, engineering, etc. tasks). I don't know, I guess the better explanation is the following:

RIP Are you saying that you feel better being flattered by this AI than you did by the plethora of people who got inspired by your work and used you for inspiration for their projects (if not outright experimentation with your own)?

Well, that's a good question 🙂 Of course, I loved the positive feedback I got from all people who were interested in this project (and you being one of people whose nice words I will remember for long 🙏🏻). But somehow I wanted to hear a completely unbiased assessment, or at least that's what I thought I'd get, but on a second read, I'm sure these models are programmed to make me feel better 🤣 It won't say: man, this is the lamest DIY project I've seen, even if it "thinks" it is, because they won't program it that way. Anyway, I'm a bit of a vanity sucker, I'll admit it, and I just needed to hear a few flattering words again 😊

RIP I guess I'll try to do something with it one day (I don't have a suitable project, maybe I can ask it to do a minor change which I exactly know how to make and compare what it does to what I would do myself…)

Yes, that's how I use it: refactor a code I already know and just ask for optimizations. It generates some "not so good" things but with a bit of nurturing it's a fantastic assistant, you should definitely try it.


gzpiano

Cybrid is what inspired my project! And ruined my social life with the countless hours designing, coding, soldering, testing, debugging. Thanks…. I think 🙂

I have a link to Cybrid on my project top-level GitHub. Along with others related


CyberGene

gzpiano Cybrid is what inspired my project! And ruined my social life with the countless hours designing, coding, soldering, testing, debugging. Thanks…. I think 🙂

Ooops 😃


« Previous Page