Will put together the final piece that allows us to finally put this project in to the sunset phase.
He confirmed by rolling back the compiler to GCC 4.3.3 (the original compiled version) we could get the unit to actually work as it is supposed to. Apparently, AVR-GCC is available usually through microchip or some various locations and older versions are not available readily. So Will ended up snooping He did it through this GitHub repository (https://github.com/smeshlink/Arduino-Plus/tree/master) a fork of the Arduino main line development from 2013 (11 years ago now!). That repo happened to upload the old AVR-GCC version and will pulled it down and started the compile.
Now, I was warned about this over by the original developer. See the post I read once or twice back when I had all those issues with what ended up being the AVR fuses…
Found wisdom of the comments
I suppose until you have gone down the rabbit hole you don’t really understand what not guaranteed to work really means.
I’ve yet to recompile on my end, but using Will’s compiled build removes all of the chaotic behavior the synthesizer was showing before. One of the points of code that is likely quite dependent on this compiler version is a snippet that occurs in the editor.cc file.
Note that this function does a direct read of program memory via the pgm_read_byte() function. This function is used to directly read pgm memory. In this case, the code works to reading flash out into memory at a specific address as command. Now this could work but the method of using “programmer_switch_mapping + that index means at some point the compiler (no matter how good it is) is not aware of this memory location. The call in this case requires foreknowledge of where this given piece of information resides in active memory. The compiler is unable to check for any sort of error condition in the way it is written. For all it cares, the compiler is presented with a sum of two numbers before passing up to pgm_read_byte. No checks can be done on whether the memory is valid or not or if there is anything at the target address.
I can imagine something like this was done to same memory usage in a constrained design (to do: is there a linker output report?) if you aren’t going to use up these things as much in the code space. But again this is mere speculation. At least at the moment we have functioning products.
New PWBs and manufacturing errors
I received a new set of PWBS this week. I was excited to build and started soldering them up when I saw this
Note those cuts in the PWB
Traces broken in multiple sections of the board from what looks like a razor blade or something run across the board. Whats odd is its just one out of the group of boards so I didn’t lose my entire $230 on these from OSH park. I emailed them out and received a very quick response. They let me know this board should have been screened out of my order as a test sample and I’ve gotten the extra boards as a show of good faith.
I do like the aesthetic of the clear solder mask style, but with so much of the copper plane covering each side I think I’ve lost the cool factor that would have come with more black.
“It’s possible the fab was attempting to indicate an etching failure on that one copy. During AOI testing they’ll scratch the traces, which lets someone else down the line know to mark it with a big silver “X” so we can notice it and get a replacement started. “
Onward to soldering up this round of boards and getting prototypes out to my friends. Will is still on the enclosure part then we can start packing this project up.
Roadmap
Build the remainder of analog and digital units
Send them to friends!
Design and fab cases for these synths
Create a lessons learned
Random Observations
Until this point my head was so deep in the design I never questioned the original name of this synth the Shruthi. I happened to mis type a google search and I learned that this is an accordion like drone instrument out of India. Some links below.
https://gcc.gnu.org/releases.html I’m not quite sure about my AVR-GCC comments any more or even whether or not AVR-GCC is just standard GCC wrapped with some libraries. I have gotten turned around on this on. Something to report back on in another post.
It’s been a while since my last post, so I thought it prudent to provide a State of the Project update for the Shruthi Clone.
A major breakthrough came in understanding the firmware build chain. Until late last year, the build process yielded a loadable hex file that enabled some functions of the display and LEDs but didn’t result in a fully functional synthesizer.
I experimented with multiple ways to build a hex output, each with varying levels of success. Initially, I was convinced that we had to build in an old Ubuntu virtual machine with the exact GCC version to make everything work. However, after delving deeper into the makefiles sequence and rewriting portions (with the help of my brother Will), I finally managed to generate a load that produced audio and communicated via MIDI!
There are still issues in both the firmware and some of the hardware build (no design issues so far) that we are tracking over on GitHub.
Debugging noisy hardware through firmware understanding
Onto the hardware side of things. This design is susceptible to noise. This concept isn’t surprising in analog electronics, but coupled with firmware that was only “sort of” working, this caused a ton of head-scratching and soldering/desoldering before I discovered the real issue.
What brought the debugging process to a crawl was “noise” ( in truth it was signal bleed) from the analog pots (potentiometer encoders). These pots are on the digital board and are intended to control everything about the synthesizer’s oscillators, filters, sequencer, LFO, and everything else. For the majority of the time working with the first three prototypes, these were useless.
The synthesizers display indicated random settings (for instance, the analog filter cutoff) were constantly changing when none of the actual knobs were manipulated by hand. So, consulting back to the original design build instructions (Here), Pinchettes called this phenomenon “moved by a ghostly hand,” which I really love.
Now, onto the code. The source code includes a nice function here that caused a kind of feedback loop in our debugging efforts:
*PortA::Mode::ptr() = 0xfe; pots_multiplexer_address_ = (pots_multiplexer_address_ + 1) & 31; if (adc_resume_scan_to_ == 0) { adc_resume_scan_to_ = pots_multiplexer_address_ + 1; pots_multiplexer_address_ = adc_hot_address_; } else { pots_multiplexer_address_ = adc_resume_scan_to_ - 1; adc_resume_scan_to_ = 0; } /*------- The ADC conversion is run on the particular Pot now that the mux is set up --------------*/ int16_t previous_value = adc_values_[address]; int16_t delta = value - previous_value; int16_t threshold = adc_thresholds_[address]; if (delta > threshold || delta < -threshold) { adc_hot_address_ = physical_address; adc_thresholds_[address] = kAdcThresholdUnlocked; queue_.AddEvent(CONTROL_POT, address, value >> 3); adc_values_[address] = value; } }
The code drives the rate at which the multiplexors on the boards are scanned at. Lets walk through it:
Case 1: adc_resume_scan_to == 0. The adc hot address is loaded to the pots_multiplexor address and the conversion just proceeds Case 2: adc_resume_scan_to =/ 0 The current value of the mux address is read again it appears and then the resume_scan is pushed back to 0.
Now working our way down, where does adc_hot_address_ get initalized? That is a copy of the inital pots_multiplexor_address that started the entire operation. There also are some “warm up” conversions to the pots which I presume are related to the settling time of the multiplexor before valid voltages are present. You can see the threshold here establishing the adding a new event and pushing the hot address now back to the physical address that started up the operation.
At a higher level, this means that when the firmware notes a change in the last Voltage read from a given potentiometer, the rate at which that signal will be sampled will go up. This means that a faulty pot that may not be emitting a DC level will get sampled much more.
This deep dive came after noting that I was observing the multiplexer rate changing based on the current positions of certain pots. A potentiometer would have signal bleed through when it was sampled and would show a what looked like a spike, which i presume was an effect from switching another pot to the problematic pot. The firmware (as noted above) was looking for changes that would exceed this adc threshold setting and once that happened a given mux setting would be sampled more often and the loop would continue. Apologies on the seemingly repetitive nature of this section, but the debugging indeed went in these circles for a while before I developed an idea of what was going on and then looking into the firmware.
Ultimately, the solution was to remove the problematic pot but not leave the signal floating (an open signal drove the same quick sampling behavior), but terminate the removed pots traces to ground. Once I understood this failure mode of the system, I could move further to review of how the actual analog section was working.
Analog Output Exploration
Once the two analog boards were generating some audio, I took some baseline scope shots of the analog output Voltage. Waveforms from the analog out at various synthesizer presets are captured below. Note the “hash” on these waveforms is the PWM (Pulse Width Modulated) signal present in the output. The theory is that once you run the audio through another system that signal should get wiped down. I’m debating whether I want some outboard filtering in addition at some point, but that would be a whole feature.
Basic
Basic Preset
Flobass PresetMoonrise Preset
Virgin Preset
I am not sure if the outputs here match whats intended but Its definitely audio waveforms that make some sense with the patch names!
Building more Samples
Many of the related headaches that I encountered had to do with the build. It took a very long time to establish a baseline performance on either prototype, and the original digital control board is now all but useless. The two issues mentioned above were only possible to solve by building fresh digital and analog boards and comparing the differences between them. This classic “two prototype” issue always arises in hardware development. The more prototypes you develop the more you can compare their behavior instead of go right to theoretical failure modes. I spent a long time just with one build and that slowed me down a good deal.
Once I had a good grasp of how the firmware operates and how to successfully load working code, I went back and built another analog board to run two synths simultaneously. Even that alone has sped up my workflow and debugging. Ultimately, it revealed that my first build of the analog board had far more issues than I originally thought. As of today, we have two sets of hardware that perform (almost) the same.
Next major step is to build at three more prototypes of the synth before I call it a day on this project and decide where it goes next. I have already noted that obsolete parts, like DIP ICs again, are cropping up on this design as I go back to Digikey. A decision will have to be made on how much I want to invest in this project long term, but I have at least three friends who need final products (or, at best, working prototypes).
I still haven’t gone into the enclosure design for the product, but that needs to be done before these last three are totally finished.
A third part will be reviewing pricing and cost of the whole project. This wasn’t done for free and I just want to review where the money went even on something as simple as a rebuild of an existing design.
This blog will continue to serve for these sorts of snapshot updates on the design, although I’m considering using the GitHub wiki to log the design changes or modifications for the future… who knows. What should appear on the blog is a summary and description of the price of all these parts, even with my steps/missteps along the way.
Thanks to my brother Will for the assistance on all of this. There’s no way I could have navigated the makefile and git conflicts as quickly without his help.
After my last post on this project I thought I was losing my mind and all hope was lost. But now I have figured a fundamental boneheaded mistake out and am moving forward again!
There is life!
I had to address two conflicting theories to resolve this. First, I didn’t trust the custom makefile provided from the repository. I had visions of memory overruns and corruption of some level. I was also suspicions about ESD or mechanical damage of the hardware as I carted this thing back and forth from my lab and my home.
So I soldiered on. The next step I took was to install Microchip Studio and get back to basics. I developed a pure “Blinky” setup to vet the micro itself, without any of the complications of the end application. To be explicit, running Blinky means m to cycle on and off all of the digital output pins and probe them to get a baseline of life. This would remove my concerns about the custom makefile because i was just using the manufacturers IDE.
After toying with Microchip Studio for a while I found that I needed to manually run AVRDUDE to program the .hex file from the command line and hope this would give me the truth I was looking for. I wrote the program to continuously blink all the I/O lines so it would not really give me a blinking LED but it would allow me to probe for life and find any problematic pins. The ATMEGA is setup with various byte accessible ports of I/O (A,B,C,D) that i could write to with a single command.
After getting this new test build loaded I walked through the pins on the micro right at the device with the following results:
Micro Pin
Good?
Function
PC7
Yes
Display Pin 14 (LCD_DATA4)
PC6
Yes
Display Pin 13 (LCD_DATA3)
PC5
No
Display Pin 12 (LCD_DATA_2)
PC4
No
Display Pin 11 (LCD_DATA_1)
PC3
No
Display Pin 6( LCD_EN)
PC2
No
Display pin 4 (LCD_RS)
PC1
Yes
IC1 Pin 5 (SDA)
PC0
Yes
IC1 Pin 6 (SCL)
PB7
Yes
IO_SCK
PB6
Yes
IO_MISO
PB5
Yes
IO_MOSI
PB4
Yes
CV2
PB3
Yes
CV1
PB2
Yes
ENC_SW
PB1
Yes
ENC_A
PB0
Yes
ENC_B
So in my previous few days I was reviewing the differences between the ATMEGA644 as opposed to the newer variant ATMEGA644A. After a few hours of realizing the differences were minimal I threw up my hands in exhaustion. But something stuck in my head. Could the I/Os be used for muliple purposes? And how would JTAG work on this device.
In reviewing the table above I see the pins that don’t work (and coincidentally are connected to my display) are connected to the JTAG interface port. So how does the micro control these different pin modes??
Excerpt from ATMEGA644A datasheet
The answer is fuses! I use AVRDUDE to check my high fuse status, and i see that is 0x99! After following the steps on this website.
So JTAG is sure enough enabled! I set that JTAGEN bit back to 1 and my clock wave is coming out the pins connected to the display.
I then proceed to load one of the builds of the the Shruthi source code I made a few months ago and I see activity on the display!!!! WooHoo!
Next Steps
I’m going to setup MIDI stuff now to see what i can control.
A Few Observations
Now I want to reference a few things at this point. The firmware building guide is totally fine for the Shruthi project but it presumes that you have a strong handle on AVR development before starting this modification. So I’ll explain here the gaps
Clearly pinchettes make and bake commands work
You need the understanding of memory flash space versus eeprom space versus boot loader space
You need an understanding of what the AVR fuses mean (here was my tripping point earlier).
Its hard to believe how much (or how little) can happen in five months. So I wanted to do an update on where I’ve gotten to on this Shruthi synthesizer project since February. At this point I expected to be wrapped and building units two and three, but things rarely go so close to plan.
So far this project has tackled:
PWB design
Analog electronic analysis
Source control and Git when working in an emulated version of Ubuntu
Logistics on buying parts and when in 2023 you can and cant get them.
How to keep sane when you cant fit all of your equipment in your apartment.
How to manage workflow going between a lab in your parents basement and your own place.
Time management around this hobby project, personal crises and relationships, and the day job.
But the biggest realization is running this sort of project for me is that I need a better system for this sort of work. That system should be easy to make a habit out of.
The plan was to make very clean summary blog posts of each phase as i went through the project. The second post on buying the components and the PWB has been in draft for quite some time now even though there are many words written. There’s nothing that is inherently problematic about that post, its just that formalizing it and feeling “comfortable” releasing that article is entirely independent from where I’m at in the project today.
Today I’m looking at the two Highest bits of parallel data signals toggling to the OLED display and they are active and look to be reasonable transition times!
But when I inspect the front display there is no active OLED display activity…..
👎👎👎👎
I’ve built two prototypes (this one performing better than the first one I butchered with some trace destruction. So now I’m grappling with a few other ideas Id like to explore more as this project moves forward.
How to synchronize work across multiple computers
This has been easily the slowest process. I could have kept it basic and done a google drive of everything months ago but I insisted on using Git to its full intent and not what works for me. I’m glad for the experience but more calories have been spent in pulling my Digikey order googling the the same datasheet on multiple machines that I’d like to mention.
Other options are out there I’m sure and Git should work I think too but deciding on this is a task in itself that gets me away from the hardware.
How to prioritize work
I had an instinct this was going to happen but it was only magnified with personal issues with my family over the time I had to tend to. Quick takeaway is that this project needs space in my week without the consideration of what I’m going to do once I get there. Preparing for the next week may be a better matter of keeping documentation organized and available to jump in no matter what location
How to keep the right tools available
I bought quite a few things so far on this project that haven’t gone into the hardware. Flux, Solder Iron tips, a new drafting chair after my back was hurting, magnifier glasses. But I’ve also made the mistake of taking have soldered assemblies back to my apartment with my o scope and needing either a 9V adapter or a DMM i didn’t bring back. Maybe the solution here is to have a semi “mobile” lab setup if I’m going to do certain tasks in one place as opposed to another, and just pack it up each time.
How to get a more systematic hardware bring up plan.
On the last one I think I couldn’t have known that ahead of what I experienced.
How can this be so? The display gets a clearly intentional signals from the micro (pins are wiggling correctly) but it does nothing to drive the display with anything meaningful. Could this be a pin assignment issue?
Parallel Data lines (DB7, DB6) From Micro To NHD-0216KZW-AG5
Schematics indicate the same pins are used to connect to this Display. The other oddity is that the control pins look deliberately controlled. Pin 5 (R/W MPU Read/Write select signal, R/W=1: Read; R/W: =0: Write) stays Low. Pin 6 (E MPU Operation enable signal. Falling edge triggered) always high. Since I didn’t write this code I’m not sure how the firmware could screw this up in this partial manner. Could a transfer to the device really be occurring that would have some pins activate and others stay high???
A fork is a personal copy of an existing Github project that the developer can do to with whatever you like. A developer can work on their own stuff in their protected bubble and then “push” back up the changes to the original project and thread if the original project wants to incorporate the forked features. A fork is in contrast to a branch, another agile software development term. A branch means a developer takes a copy a project (just like with a fork) with the goal of correcting one or more “issues” or “bugs” that the developer is interested in fixing. By creating the branch everyone on the project is aware of what the developer is trying to fix but they can go off their bubble with the intent that my changes will be compiled and tested solo. Then a kindly wizard associated in the project one day will allow me to “merge” those changes back in to the main Tree of the project.1
A good infograhic from theserverside.com
So merging gets complicated when we are dealing with files in different electronics CAD packages instead of lines of code. I will use transitioning development software platforms from Eagle (as I will discuss below) to KiCad as an example. If I compared the actual schematic design files on my local hard drive you would be left with a long list of changes of the bits and bytes that no human can use to track changes happened. The file extensions you save into are different the GUI interface is different, none of this can just transfer from one platform to another without a person in the loop. So for this project, I will create a branch and leave breadcrumbs in the Readme.txt file for those curious to work their way back.
After inspecting the original files in the shruthi/hardware_design/pcb folder, I discover these files were originally developed in Eagle 6. The PWB folder contains two types of files .sch and .brd. Currently Eagle is up to version 9.0 and no longer available without bundling together with some other AutoDesk features, which is exactly why the goal is to take these files out of something not exactly maintainable and to move it to Kicad.
Going back to the design folder and searching around this /pwb directory is what I am looking for. These are the schematic and Printed Wiring Board files for multiple designs in the project. 14 designed boards with schematic and PWB design files!
The Github Shruthi PWB directory
After converting all the schematic files over to inspect them, I found that the original Shruthi product concept isn’t to have fourteen PWB’s on one assembly, but to have the end user select analog boards and plug it into the digital control board, and if the musician wants they can swap between boards for different voices. From the archives, i can see there was an original control board (powered by a micro controller), but at some point theXT versionof the Shruthi was released. This version exposed more encoder controls that were hidden behind menus and clicking buttons in lists within the original. For this project it means there may be more pots and buttons to solder, but more fun to mess with when it all works at the end.
I’m going to limit the scope here and after looking back at thebuild documentation I’m going to start working with two specific boards, the SMR4 mkII_V02. which is a four pole “Roland like” analog filter board, mark II being the second version of this and V02 being the second revision of the second generation.
With these two boards chosen the work begins. Kicad in theory supports Eagle file import but not from the old Eagle files used 12 years ago on the Shruthi2.. So to start, I have to open Eagle to get these Eagle 6 boards rolled up to the newest version and spent a few hours installing this Autodesk Eagle combination, opening the files and then saving them again to be current Eagle files. Once that was completed Kicad successfully recognized the files and could import them.
Kicad and PWB Updates
Kicad Up and Running with the Converted Board File
Now I would just congratulate myself and crack a beer in victory, but I didn’t realize the work had just begun. I had discovered one of the main components for the Analog section of the Synthesizer the LM13700 no longer existed in a PDIP package.
I figured I could solder surface mount (more on that later) and could easily swap out the SOIC version for the PDIP. So I set to work making a new footprint for the part and rewiring the schematic and PWB file to ensure my new part fit. It ended up fitting fine as it was smaller than before but because of the shrinking of the component other assumptions about signal and ground trace lengths had to change and i ended up rerouting more than i planned. I still maintained the two layer setup but much was streamlined and moved from the original SMR_mkII_V02 design to the new SMR_VJK3.
I was lead through the process by the very useful Kicad documentation as well as remembering my old scars using electronics design tools at my day job. Kicad by far was an easier flow than other packages Id used before.
Imported Original Analog Filter BoardImported Original Schematic
Theory: Transconductance Amplifiers
Lets talk about the nitty gritty of the design. So the PWB is quite simple once I got my head around it. It is only a two layer board, with a handful of different through hole parts. Having been the “analog guy” for a few years now the Voltage to current mode transformation of the LM13700 was very interesting. Whats more is that it seems to be a common mode of operation with classic analog synthesizers. Control of the audio signal path is done via potentiometer DC setting the current through these trans conductance amplifiers. This is done both in the gain section of the design as well as the filter section. So the voltage is fixed but the resistance changes and that shifts the level. The diagram below shows an example circuit. So for the gain stage at least its quite obvious that your base current in the output is a function of the gain setting voltage. The current sources used in this application are actually exponential in relationship to the output signal.
LM13700 Example Circuit
And here it is in action within the LPF analog filter board in the Shruthi.
Note the Amplifier with the two large circles
So you can see there’s an off board potentiometer that controls the I_GAIN current and then gets buffered before being driving out the line level cable. I’d love to get deeper into how this is all working (and I Imagine I will in bring-up) but lets get back to the task at hand. The PWB update and removing the PDIP to get an SOIC into the design. Well whacking in the new pads was a piece of cake but since everything got smaller many small changes rippled through the rest of the board.
Back to Board updates
Larger pins mean larger and thicker traces, and once i shrink the pins the room you had is reduced. The thickness of the old device allowed of running voltage rails underneath the part, once i shrunk down to the SOIC i lost all room to do that trick and had to move the rails out from underneath. Now that the power was routed outside, I had to re route the signal traces under or around what Was already there. And finally I noticed a few things i didn’t like so I had to deal with those.
Original Layout of DIP LM13700NNew Layout of the Same Section.
Some other highlights. The DRC settings were set to roughly default but I did space the VDD and VSS on the LM13700’s to be further spaced apart than the older design. My Thought was that the pads also shrunk so any more copper wont move the needle very much. Although we will see in the testing where that ends up.
Overview of the New PWB design
You can take a look at the full design and Kicad files at the project directory for the project.
The next section will be about purchasing the parts for the build as well as an over view of the assembly. The final post will be about testing the end product and lessons learned.
Since the time I started this project is now at 7.02 and will probably be further along by the time I post https://www.kicad.org/blog/
SOIC versus PDIP comparison of footprints.
Pinchettes does a much better job than me at actually explaining the theory of the VCO/VCF/VCA. At this point im merely an observer until the day I have to debug the thing.
Work with a PWB fab again on a more complex board.
Use Github to successfully fork a project.
Have a new midi monosynth to play with!
Introduction
I’ve been thinking about a new hobby project for 2023. Last year I dove somewhat deep into USB drivers and proprietary Microchip libraries which had my head spinning when i just wanted a simple USB audio interface. So this year, I’m going to tackle something hardware only and use my oscillocope more than ever!
A few months back https://mutable-instruments.net/ announced that their synthesizer product line was shutting down. Sad news, but fortunately for the engineers with too much time pinteretes has opened source’d many of his designs. Before starting my first job in 2012, I was really into synth kits and modified my monotron for midi control but never returned so this will be fun. Those kits were cheaply made for a reason and I didn’t really have the patience or spare resources to build a more proper synth. So I’m going to attempt to build the Shruthi!
Based on my failed attempts at trying to recreate the blog post Marc Nostromo put up on his own blog to Add MIDI to The Monotron I figured that I’d start from his inspiration and begin my own code development step by step to show how I got from cool idea to finished product. Including all the steps in between.
This project is built as a USB MIDI solution, so all uses of MIDI from here on out will be done via a USB connection, or at least the endpoint of the midi chain will be routed to a USB connection through a computer. The way we are going to handle the USB and the MIDI is via the Teensy 3.0.
The Teensy 3.0 is a 32-bit ARM cortex based microcontroller with a 48Mhz clock speed. The main reason it was applicable to this project is the small form factor and direct USB MIDI compatibility. This means that the developers of the Teensy have developed functions that can interpret MIDI messages to and from the Teensy itself. If you flip a switch then, the Teensy could send middle C (MIDI message) to your computer and then play that note.
In our case, we are going to do exactly the opposite.
The Teensy will be set up as a USB midi device, much like a USB MIDI interface, that will take a given MIDI message and set voltage levels on various pins that will be connected to the Montoron’s voltage control test points (gate, pitch, and cutoff). This will allow us to control the Monotron via the computer and any midi messages we desire. In our case we are going to design the system to correspond correctly to the pitch tempo and cutoff control frequency that is contained in the midi message, but you could always adjust this code to do something more nutty like play only a certain scale of notes no matter what the input message note is.
Since I usually like to see things for myself, the first step for me is to check out whether all the hype is real, does the Teensy actually know what MIDI notes its receiving, and how can I check that it’s getting the right message at the right time? This is what LED’s are for.
Below is a code segment that identifies a particular MIDI note, and gives a unique event to recognize that the Teensy knows the note is played. I have it set up here for middle C to trigger led 1, D to trigger led 2, and E to trigger led3.
// J. Kolb Midi test 1/21/14// This is a test to see how the midi usb complience of the teensy 3.0 works int ledPin = 5;
int ledPin2 = 6;
int ledPin3 = 7;
int ledPin4 = 4;
void OnNoteOn(byte channel, byte note, byte velocity)
{
if(note == 48) // check for middle CdigitalWrite(ledPin, HIGH);
if(note == 50) // check for ddigitalWrite(ledPin2, HIGH);
if(note == 52) // check for e digitalWrite(ledPin3, HIGH);
}
void OnNoteOff(byte channel, byte note, byte velocity)
{
if(note == 48)
digitalWrite(ledPin, LOW);
if(note == 50) // check for middle CdigitalWrite(ledPin2, LOW);
if(note == 52) // check for middle CdigitalWrite(ledPin3, LOW);
}
voidsetup()
{
// Initialize hardwarepinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
// Initialise midi input callbacksusbMIDI.setHandleNoteOff(OnNoteOff);
usbMIDI.setHandleNoteOn(OnNoteOn) ;
// Initialization pin checkdigitalWrite(ledPin, HIGH);
digitalWrite(ledPin2, HIGH);
digitalWrite(ledPin3, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
delay(1000);
}
voidloop()
{
usbMIDI.read(1); //only reads midi channel 1
}