This thread will show how to create a two octave piano all within the Nextion logic without the need for an external microprocessor. As we go through the process of creating this piano, I will deal with a few techniques that may be useful in your projects. Again special shout out to Steve (indev2) for tripping across the b[.id] component array.
This project will use the Nextion 3.5" Enhanced NX4832K035_011 <Order Here>
and the Expansion Board for the Enhanced Nextions <Order Here>
It was once asked what the expansion board might be useful for, and I honestly didn't think much until I finally wrapped my head around trying to get the music notes to play. The first trials of trying to find fair sounds that could somewhat resemble notes - well, hard on the ears. But after a little work, I finally have somewhat playable notes. You'll need an Enhanced Nextion display for the pwm IO and the expansion board with the buzzer that we will pump pwm to. So now let's go through how to make a Nextion Piano.
Here we use 15 Text Components for the ivory keys and 10 Text Components for the ebony keys. I chose the Text Component because without any .txt it is simple to create a colored square with, and is fairly lightweight on the memory and resources. Text Components also come with a Touch Press and Touch Release event which we will use to change colors when pressed. So let's set these up now from left to right. Remember to alternate your text components for white, black, white, black. In the end we want to have t0 to t24 matching the keyboard of the piano.
The Ebony Keys
The ebony keys are t1, t3, t5, t8, t10, t13, t15, t17, t20 and t22. You can use multi-select. Set their .w to 25 and .h to 120. Set their .bco to 0 (black) and their .pco to 33808. Using the Define Custom Colors from the bco color selector, white is Red 0, Green 0, and Blue 0. Add to Custom Colors and press OK. All the ebony keys should now have bco of 0. Likewise using the Define Custom Colors from the pco color selector, 33808 is Red 128, Green 128, and Blue 128. Set their .xcen to Center, .ycen to Down, .txt to empty, .txt-maxl to 2, .isbr to false. The ebony keys are placed every 31 pixels with six pixel spacing between them. Line them up with the keyboard background exactly. You can use the fine precision of 1 pixel adjustments using your keyboard arrow keys. Once the ebony keys are placed, multi-select all ebony keys from left to right, and use the Toolbar Arrow Down (Bring Bottom). This will renumber their .id's sequentially starting at 1.
The Ivory Keys
The ivory keys are t0, t2, t4, t6, t7, t9, t11, t12, t14, t16, t18, t19, t21, t23 and t24. You can use multi-select. Set their .w to 30 and .h to 120. Set their .bco to 65535 (white) and their .pco to 50712. Using the Define Custom Colors from the bco color selector, white is Red 255, Green 255, and Blue 255. Add to Custom Colors and press OK. All the ivory keys should now have bco of 65535. Likewise using the Define Custom Colors from the pco color selector, 50712 is Red 192, Green 192, and Blue 192. Set their .xcen to Center, .ycen to Down, .txt to empty, .txt-maxl to 2, .isbr to false. The ivory keys are placed every 31 pixels with only one pixel spacing between them. Line them up with the keyboard background exactly. You can use the fine precision of 1 pixel adjustments using your keyboard arrow keys. Once the ivory keys are placed, multi-select all ivory keys from left to right, and use the Toolbar Arrow Down (Bring Bottom). This will renumber their .id's sequentially starting at 1.
Multi-Select all keys and ensure their .y is set to 188, and if not set to 188. From here on out when we select a key, we will be using the right-click on the mouse as this will not accidently move our keys out of alignment (since we just spent so much effort to align them). So now the keys from left to right have sequential .objname from t0 to t24, with the ivory keys sequential .ids from 1 to 15, and the ebony keys with sequential .ids from 16 to 25. Ordering the Text Component keys in this fashion will allow the key to be played even when selecting the space between the ebony keys.
The Numeric Variables
Now we add to our HMI design 25 numeric Variable Components sequentially with .objnames from va0 to va24, and with sequential .ids from 26 to 50. This will help shorten our code when we are able to employ the b[.id].attribute Component Array later on.
We have to add one Hotspot Component m0 at .id 51 - this will hold two segments of code. Set its .w to 32 and .h to 24 and set down close to "Note" where it wont get pressed.
The Number Components
Lastly we have the 4 Number Components from n0 to n3 with .ids from 52 to 55. You can use multi-select. Set their .w to 40 and .h to 16. Set their .bco to 16904 (dark) and their .pco to 0. Using the Define Custom Colors from the bco color selector, white is Red 64, Green 64, and Blue64. Add to Custom Colors and press OK. All the numbers should now have bco of 16904. Likewise using the Define Custom Colors from the pco color selector, 0 is Red 0, Green 0, and Blue 0. Set their .xcen to Right, .ycen to Up, .val to 0, .lenth to 0, .isbr to false. The numbers are placed evenly after Freq (n0), Duty (n1), Key(n2) and Note(n3). Line them up, multi-select them and set their .y to 163.
Lastly if you started this from scratch you would have to add your 1 font 8x16, and the piano background, and set the piano picture pic 0 for the page0 background. Setting a page background is done by changing the page component's .sta to image and then setting the .pic to 0 by selecting your piano background from the pictures selector.
So now our piano should look okay, the ebony keys should appear to be on top of the ivory keys. Soon off to the coding.
Hmm, okay good new or the bad new first?
The good news is each of the Number Components have no Press/Release Code. So let's dig right in and get this bad new done with.
May as well dig into the keys. To make our code easier we are going to pass our key press over to the hotspot for processing. So in every key we have a sys0 equal to the Text Components .id attribute - 1.
In every touch Press Event, we call our hotspot with click m0,1, every Release has click m0,0. So most of this would be pure repetition:
t0 Touch Press Event would look like:
t0 Touch Release Event would look like
t1 Touch Press Event would look like:
click m0,1 t1
Touch Release Event would look like
If we are just looking to get our notes to play, this will do it. We carry this pattern through to t24
t24 Touch Press Event would look like:
t24 Touch Release Event would look like
So for all of our ivory keys we are going to implement the fill command. There two sections of an ivory key. One of these blocks is a 30x40 at .y of 268 and the other is a height of 80 at .y of 188
So the t0 Pressed Event looks like:
t0 Release Event looks like:
So I am going to now we are going to throw a curve.
- A new feature, more work. How about key names on the keys?
So, if you want this feature, we will have to redo the key events again.
Here is what we need do:
- Create a new number variable, change its .objname to names
- Create a new hotspot, change its .objname to snames
- set its .w to 18, .h to 24, .x to 216, and .y to 158
The snames Hotspot needs its Touch Press Event set to include:
And of course all the ivory and ebony codes will need to include painting the names in the keys Touch Press and Touch Release Events. So just as before, I will leave you with the notepad file with their respective codes for you to replace into each of their respective events.
So what do we have so far. Our keys are in place, they can be named or not (depends if you did the step above). The keys are colored when pressed. And they keys will pass to the m0 hotspot which key is pressed to generate our notes. ... our notes.
the Base Notes
So here is why we had our 25 sequential numeric Variable Components, so that if need be, we will have one spot where our notes can be tweaked. Perhaps we prefer to lower the tones a bit at some other time. We do not need to go through the 25 individual variables one by one, we will have a nice list where these are included in one simple spot .. inside the page0 Page Component's Postinitialize Event.
This Postinitialize Event will do two things. The first task is to set our names and label our keys with click snames,1 for those that did the above step, or it should be commented out for those that did not do the above step by adding two forward slashes at the beginning of the line like //click names.val,1. The second task is to initialize our variables va0 to va24 with our notes frequencies. So our Preinitialize Event should look like:
Now all that remains is getting these notes to play through the buzzer on IO7 of the expansion board.
So okay you have connected your Expansion board to your Nextion using the 10 pin FFC cable, All is looking okay from a connection point -- So lets get that buzzer buzzing.
Dealing with Pulse Width Modulation
There are four steps that we need to deal with for our pwm through IO7
1) First we need to set our duty cycle, this is a percentage of time voltage is HI.
This will evaluate on the Nextion simply as 11. I left the divisor there to make it simple to adjust.
2) Second we need to configure our gpio pin for IO7.
This sets IO7 (7) to PWM output mode (3) and 0 is technically the page component
3) Third we need to set our PWM frequency.
here sys0 passes our key number and grabs the frequency from our sequential set of variables.
The keys start at 0, the va0 series starts with .id 26 and now you see why it was important to make
sure that the components were sequentially ordered. For ease ... great ease.
The PWM for our piano sounds better with a multiplier, and with some tinkering 3 makes it fine.
At this point, we may as well also set our four numbers. So our m0 hotspot pressed event code:
pwm7=100/9 // Set our duty cycle
cfgpio 7,3,0 // enable pwm on IO7
pwmf=b[sys0+26].val*3 // set our pwm frequency
n0.val=b[sys0+26].val*3 // Display our pwm freq in n0
n1.val=100/9 // Display out Duty cycle in n1
n2.val=sys0 // Display our Key Number in n2
n3.val=b[sys0+26].val // Display our base note in n3
But now I did say there were 4 things and we dealt with only three. Our PWM on IO7 will stay configured exactly as we configured it. This will result in the same note being played over and over, and regardless if some musicians sound like that is all they are playing is one note, we demand better. So we need to unconfigure the PWM between uses. So every key release event calls our hotspot release event with click m0,0 -- so in here we have only one line that disables our pwm. So m0 Release Event is:
- Here we simply set IO7 to input binding mode to our page.
There is no other reason why binding to the page other than it disabled our PWM as we needed.
An there you have it - a playable Nextion Piano all within Nextion logic ...
We will expand this later on ... the Pla-ya Pian-na ! Oh yeah.
Spending a bit of time of your new Nextion Piano, there are many things that are possible.
As you can see, I have continued forward to add a key indicator at the bottom of the keys,
Key's Named if desired, a scrolling score, and added five player piano Christmas Carols
So, carry on and have loads of fun.