Final Project – Merit Pagoda – Merit Pagoda & Luna (Zichen) Feng

Merit Pagoda

 

Michelle Hua

 

Professor Andy Garcia

 

I would like to begin this documentation by recounting a conversation Luna and I had with Professor Garcia in the early phases of this project.

“ I love your project idea,” he said, “ but this is going to take a lot of late nights.”

“ Well, that was in our plans anyways,” I said, like a fool.

Now that the project has been finished, I can accurately say that Professor Garcia’s assessment was correct, and that hubris is one of my many great follies. Nonetheless, despite the all-nighters and not-entirely-successful results, I can also say that this was a very great learning experience.

 

For our project, we created a “Merit Pagoda”.

This project was inspired by a pagoda near Luna’s home, which would show nightly light displays on it. Especially in tandem with the stressful finals coming up, we hoped that creating an eye-pleasing experience reminiscent of peaceful temple atmospheres would appeal to our fellow students. The pagoda is operated by 3 muyus, or Chinese temple blocks. The middle muyu turns on all the lights of one of the five floors of the pagoda. The leftmost muyu would trigger a “flash” function (all lights blinking on and off) on the floor last activated, while the rightmost would trigger a “spin” function (lights turning on in a 1-2-3 pattern, as though they were rotating). With these three functions, the user could theoretically create interesting patterns throughout the pagoda to enhance the light display.

This idea was created in the brainstorming phase, where Luna and I came up with our first three proposals: the Merit Pagoda, the Horror Maze/Final Boss, and the Kungfu Guqin. A few ideas that we made along the way were axed due to their unclear purposes and mechanics. We discussed the mechanics of each project fairly in detail and afterwards wrote and submitted our proposals separately so our “final” idea of each project was more individualized. After we received feedback on our proposals and further discussion with Professor Garcia, we ruled out Kungfu Guqin, as it received little feedback and was also a game like the Horror Maze/Final Boss. We eventually decided on the Merit Pagoda for a few reasons. The main reason was that it wasn’t a game, since we already made a game during the midterms and we wanted to step outside our comfort zone, try something new. This was an especially big point in my book as well, since in my preparatory research, I had decided I would prefer to make a project that was more of an “ongoing experience”. The Merit Pagoda concept fit this description, as it was designed to be an interactive light display that users could change befitting their mood and aesthetics rather than a game with strict rules, start, and end point. Horror Maze/Final Boss also experienced severe conceptual divergence in our proposals, so it was also easier to focus on the project which we had a more similar understanding of. The project evolved and simplified a great deal throughout the course of us working on it, with the final version being roughly what was described above.

A note to make: because of the amount of details and changes we made throughout the entire making of the project, there was never a clear plan that we had — it was always just loose pieces of plans being dealt with one at a time. Additionally, our poor sleep schedules during this time also means our memories of making this project have become a little blurry. As such, we made six “versions” that are roughly representative of our plans throughout the working process for clarity’s sake — the exact steps of this project have been lost to history.

The first version of the Merit Pagoda was an absolute behemoth of a plan that took 5 pages of single spaced writing, a great number of sketches, and two animations to fully capture. For those who have yet to read our proposal essay, you can refer to it here to get full access of the sheer volume of this project we thought of: https://docs.google.com/document/d/10ObCw9Lx3DwQKf_GgQ5jtTxwu0yeUPdj4DBj_XgJhyI/edit

The first version of our plan for this project’s functionality contained 5 muyus controlling different functions in different orders, 5 neopixel lights beside each muyu to track the active functions, neopixels underneath the muyu to represent whether it could be struck or not, and a gold function. The full version of the plan is as follows (Note: a more simplified plan exists below, if you are already familiar with this version, you can refresh your memory with the shorter version instead): 

V1:

  1. Muyu 1: Turns all the lights on a floor on (activates it). Determines floor based on knock strength. The most recently activated floor determines the floor the other muyus control. Muyus 2, 3, 4 can only be activated after muyu 1 is struck
    1. Neopixels 1: the number of lights that are on is the floor level of the active floor. Ex: the fourth floor is active, so four lights are on.
  2. Muyu 2: controls the volume of the most recently activated floor. Each knock brings the volume higher, until the count exceeds 5, at which point it turns to zero/volume off (what Michelle thought the function would do) or one/volume low (what Luna thought the function would do).
    1. Neopixels 2: the higher the volume, the more neopixels are one. Each strike, the volume increases, an extra neopixel turns on.
  3. Muyu 3: activates flash function & turns off spin function if on. A flash drawing appears around the pagoda with the flashing of the windows
    1. Neopixels 3: if function is active, 5 neopixels on. Else, all 5 off
  4. Muyu 4: activates spin function & turns off flash function if on. A spinning frame appears around the pagoda that spins in time with the lights on the windows
    1. Neopixels 4: if function is active, 5 neopixels on. Else, all 5 off
      1. Note: In Luna’s interpretation, when the user switched between muyus 3 and 4, whenever one is first activated, the speed would return to default. In Michelle’s interpretation, the muyu would be at whatever speed it was last on when the function switched.
  5. Muyu 5: changes the speed of the flash or spin function, with the same mechanism as muyu 2 — knock until it exceeds 5, then return to 1 (this we had the same interpretation over).
    1. Neopixel 2: the faster the speed, the more neopixels are one. Each strike, the volume increases, an extra neopixel turns on.
  6. Golden Function:
    1. Plan A: If all the lights of a column are on, the column’s lights turns gold
    2. Plan B: ???? We reserved this spot for a plan better than Plan C but this plan was never made
    3. Plan C: If floors 1, 3, and 5 are “flash”, and 2 and 4 are “spin”, the entire pagoda turns to gold
    4. Plan D: If all lights are on, the entire pagoda turns to gold
    5. Plans E to infinity: We definitely made more plans, but unfortunately they have been lost to the passage of time
  7. General neopixels: under each muyu, there would be neopixels strips glowing under them if the muyu could be activated. muyu 1 always has a glow underneath to show it is always possible to be activated, muyus 2, 3, and 4 would glow after muyu 1 is struck, muyu 5 would glow after 3 or 4 is struck

Here, I would like to highlight a small note I made after rewriting this plan:

  • we were crazy, right? How did we not notice that we were clearly crazy? This was crazy. Why did we plan this.

Hindsight once again proves itself to be 20/20.

 

Here is a drastically simplified version:

  • 5 muyus
    • First controls floor level via strike strength
    • Second controls volume of the floor last turned on
    • Third makes the floor last turned on “flash” + flash pattern
    • Fourth makes the floor last turned on “spin” + spin frame
    • Fifth controls the speed of the “flash” or “spin” function being displayed
  • Neopixels:
    • Five beside the first muyu representing which floor was last struck and thus “active”
    • Five beside the 2nd that represented the loudness of the volume
    • Five beside the 3rd that represented if the flash function was on or off
    • Five beside the 4th that represented if the flash function was on or off
    • Five beside the 5th that represented the speed of the flash/spin function
    • Neopixels always glowing under the first muyu to represent that it can be struck anytime
    • Neopixels under the 2nd, 3rd, and 4th muyu that would glow after the 1st is struck to represent that those muyus can now be struck
    • Neopixels under the 5th muyu that would glow after the 3rd or 4th was struck to represent it could now be struck

As you can see, this plan was overwrought with detail and extremely complicated. In comparison, the physical portion of the project was simple to decide on. We decided on wood as our pagoda material with fairly little discussion. Cardboard, while functional, was much less stable or clean looking, and 3D printing an entire pagoda at the size we wanted would’ve been a decision ranging from unreasonable to impossible. However, laser cutting it was perfectly doable, and as we were especially inspired by the video of a laser cut stringless pipa that was shown in class, we thought the aesthetic would work well too. We planned to use vibration sensors to detect knocks, then decided to 3D print the muyu, as we could then customize it to fit our project. 

At this point, we had come across the issue of hiding our wiring and arranging our muyu in a way that wasn’t hopelessly confusing for the users. To solve these issues, we decided to create a box, similarly laser cut, with a fish design on it. The fish design theoretically would’ve been able to create a helpful and aesthetically fitting guide to show the users what order to knock the muyus in. Additionally, we could hide the wires beneath it. 

^The Muyu box: Lines on the fish to point towards the next muyu, 5 visible neopixels connected to each muyu

With this plan in mind, we set off to accomplish our project, with the same confidence Icarus probably had when he flew towards the sun.

I think one of the great weaknesses of our working process this time around was our synchronization. During the midterms, a singular session of intense planning was enough for us to get on the same page about the entire plan. However, as this project’s original plan was so complex, we would inevitably realize there was a detail that we didn’t quite agree on and have to stop and debate the best direction to head in. More issues again emerged as coding began and the actual feasibility of certain plans began getting challenged.

At this point, to change up the roles, we decided that Luna would code while I focused on the physical aspects of the project. During this time, I built the circuit, modeled the muyus on Blender, and began a very rudimentary pagoda design on Adobe Illustrator. However, the further the code progressed, the more issues seemed to crop up, and the more we realized the sheer scale of what exactly we were trying to accomplish. Throughout this entire process, Professor Garcia had been providing us with very helpful feedback and advice on our problems. Around this time, he suggested that we simplify our project down to 3 muyus, removing the volume muyu and speed muyu. Seeing this much more reasonable plan, we decided to edit ours as such, creating the “second version”:

3D Models:

V2: After discussion with Professor Garcia:

  1. Muyu 1: plan remained the same
    1. Neopixels 1: the active floor’s correlating neopixel turns on only. Ex: the fourth floor is active, so the fourth neopixel in the strip turns on, others off.
  2. Muyu 2: activates flash function & turns off spin function if on. A flash drawing appears around the pagoda with the flashing of the windows. Each strike increases the speed, until the count exceeds 5, at which point the speed returns to 1.
    1. Neopixels 2: the faster the speed, the more neopixels are on. Each strike, the volume increases, an extra neopixel turns on.
  3. Muyu 3: activates spin function & turns off flash function if on. A spinning frame appears around the pagoda that spins in time with the lights on the windows. Each strike increases the speed, until the count exceeds 5, at which point the speed returns to one.
    1. Neopixels 3: the faster the speed, the more neopixels are on. Each strike, the volume increases, an extra neopixel turns on
  4. Gold Function:
    1. Plan C, Plan A if we had time
  5. General Neopixels: Would be integrated if we had time

Going off this plan, we printed the muyus, attached the knock sensors with masking tape, and began coding again. Due to coding issues, we switched roles back, with me starting a new code (rest in peace, Luna’s 600 line code) and Luna working on the physical design of the project. We managed to pull off a very rudimentary version of this second code for the User Test, with 3 working floors instead of five. The code references several different example codes, including the Detect a Knock Arduino code, the automatic triggering sound file code, and neopixel recitation codes.

The User Test went very well for pointing out our existing deficiencies in our project. Here is a list of notes I made after the User Test:

User test insights:

  • People just…go for it. They knock the muyus like nyango star playing the drums.
  • The code has been broken in new and previously unknown ways
    • The issue is, i don’t know how they did it.
    • I can recreate the effect? If i also knock them crazy fast
    • But…i’m getting no data from that. All I know is knock very fast in random order = code breaks eventually. I can even read the serial monitor because I can’t tell what the hell is happening and what exact event is triggering the code breaking
      • Here’s what I do know > eventually, one 
      • OH
      • WAIT
      • I think i figured it out?
      • Ok so
      • An example of broken code is: the first light is on on the third floor, but the second two are on on the second floor. The floors should either be all on, spinning, or flashing. At no point should only a few be on without moving
        • Actually wait no i have no clue how they did this
        • I was thinking they switched
        • OH
        • Wait i got it?
        • So the spin code, everytime a certain light is reached, it sets its own boolean to false, the next to true, and the second next to false.
        • So I guess they managed to hit the function as the boolean just after…the code got set to false? Wait but that doesn’t make sense
          • Logistically (i think) or code wise
          • Nevermind I don’t understand anymore
  • SOLUTIONS:
    • 1) GET NEOPIXEL TRACKERS
      • We’re hoping if they notice the lights on the neopixels changing every time they hit a muyu, they’ll be more inclined to go “wait, each time I’m hitting it and something is happening” and slow down to check
      • More instantaneous feedback, essentially
        • …i’m remembering the candy game project from midterms and how they had a very thought out LED indicator system which the users completely missed. I am. Very worried.
        • I’m hoping since ours is connected 
    • 2)…we don’t have a solution 2 yet. We’re just really hoping solution 1 works
    • Oh wait:
    • 2) play calming music in the background???? To give a “please… chill out” vibe. Also works w main project theme
      • Like if you’re listening to something akin to “ relaxing sleeping music 10 hour loop” the urge to perform a drum solo will lessen, right?

 

Based on these notes, we can see that the main issue that we were trying to solve was rapid muyu hitting. Additionally, there was also a further note that people were striking at this rate partially because they were unclear what each knock triggered and were thus trying to figure it out quickly. We also noted that our mechanism for muyu1, detecting strength, was very unclear and hard to figure out. As such, we changed our plan to this:

 

V3: After User Test

  1. Muyu 1: instead of strength, floor is determined by the number of strikes. 1 strike = first floor, 2 strikes in rapid succession = second floor, so on & so forth
  2. Rest: Plan same

 

Because we were hoping that finishing our main plan would resolve the user test issues, we didn’t make any significant changes to the plan aside from muyu 1.

Now that I’m in the future, I want to note that I’m a bit confused on how we actually managed to solve the “users knocking very fast” issue. I suppose once it was finished, people came to believe that their actions would have a very clear response if they watched out for it and thus used it slower? Or maybe the user testing was just a very high energy environment, while the presentation and IMA Show was more chill? This is a bit of a mystery, much like other problems that arose within this project.

Speaking of mystery problems, here is one of the main ones that we ran into. At one point, the new mechanism for muyu 1 stopped working entirely. I will quickly recap the history of muyu 1’s code here:

  • After switching to V2, we came into the issue of making the code figure out when to detect the number of knocks
    • We used delays. Professor Garcia explained that this would break the entire code
  • We struggled through figuring our how to use millis — success!
    • I ran into a problem with the millis code. I genuinely cannot remember what the problem was. 
    • Upon checking my code notes, I believe the issue was that a single knock could detect multiple knocks?
      • OH I REMEMBER NOW
      • So our original code was “if (muyu1 > threshold)”
        • So during the knock “spike” and following aftershock, it could detect multiple points when the knock was above the threshold
  • Professor Gottfried helped to fix this section of the code! It followed a very similar pattern to my original code, but worked in a way that bypassed this issue >> I think it used the millis in a way that counted a knock after a certain amount of time rather than only when it crossed the threshold? To be honest, I’m not very sure. However, it worked very well and I integrated this into the code.

Using this fixed code, I created a successful 3-floor version of the code. However, as I added in the neopixels, the code broke down completely. As soon as the neopixel triggered (specifically with the FastLed.show line), the knock sensors began receiving constant input, ranging from 50 to 70. Sylvia helped to investigate this issue, eventually pulling Professor Gottfried into it as well. Eventually, it was decided that there wasn’t enough energy from the Arduino to power the sensors and neopixel, and Professor Gottfried/Sylvia retrieved a 5V battery source to connect the neopixel to. Afterwards, while some extra input was still being shown it was so low (1-5) that it was collectively decided to be a nonissue.

Around this time, I believe we also laser cut and assembled all our wooden pieces, successfully creating the box and pagoda. Unfortunately, the fish design had been weakened by us taking out two muyus, which decreased part of its learnability. We also ran into a large problem when placing the muyus on the box — the hollowness of the box made each knock shake the entire structure, thus affecting the other knock sensors. To alleviate this, we adjusted the knock thresholds and glued cotton balls to the bottom of the muyus to try to dampen the vibration when each was struck.

Also around this time, I ran into an issue with the audio code. We wanted to use sine waves for our audio, since it was most reminiscent of sounds heard in temples. This turned into a very long, convoluted process that was eventually scrapped. I first coded the sine waves to play whenever a floor was turned on. However, due to the different times they were triggered, this quickly caused multiple sine waves being played at once to devolve into a sound similar to demon screeching. I then referenced AudioSample codes to create audiosamples, whose volume I planned to turn on and off whenever necessary. However, I ran into a problem uploading these into my main code (later realized it was because I used a float where an integer should’ve been). Unfortunately, I then found when more than two sine waves of different pitches were being played at the same time, it still sounded awful. At this point, Luna suggested using Tibetan singing bowl audio instead. I found some samples on Freesound.com, uploaded them into the code, and changed their pitches. I also added muyu audio to be played with the flash and spin function, eventually ending up with our current audio.

About two? Three days? Before the presentation, I dedicated two days entirely to finishing the code. As a preface, because of my poor sleeping habits during that time, I remember very little of those 48 hours. Here is the notes I made prior to coding:

 

Notes:

  • Neopixel
  • Video (Note from the future: we were planning to animate the flash pattern and spin frame, then upload the video onto the pagoda, and make it play at different frame rates depending on the speed. It was ambitious)
  • Floor duplicate
  • Debug?
  • Make speed differences bigger?

 

Here are the notes I made around 6 am(?)  in the morning:

 

Notes:

  • Gold function is in there.
  • Neopixel …???
    • It’s written. Who knows if it works or not. I certainly don’t.
  • Luna i suggest we do not animate the video. Mostly because i will die. This is little in jest. My body is about 8 seconds from self destructing.
  • DEBUG:
    • Neopixels and processing not registering at the same time
    • OK so i deleted the delay(20); on arduino, don’t know if that does anything, have not tested.
  • Video not playing:
    • USE COMMAND F

Around 8:30 am, I took a 2 hour nap, then returned to coding. I think later that day (possibly the day after?) I had a conversation with Professor Garcia regarding our muyu 1 mechanism no longer working — it wasn’t detecting the correct number of knocks on Processing (Arduino + neopixels worked fine). I asked if it was possibly due to the amount of functions happening at once in our code. He looked through our data file and noted that the images we loaded onto it were very large, all around 2 MB, and suggested we reduce the file size. I believe here Luna and I also came to attribute the speed function of muyus 2 and 3 as a function ultimately causing more issues to the code — once we got rid of it, the muyu 1 mechanism seemed to function better. As such, we came to “version 4”:

V4: After we stared into the face of despair and realized it a reflection (time was running short and we were tired)

  1. Muyu 1: remained the same
  2. Muyu 2: Same except for removed speed function & flash pattern
  3. Muyu 3: Same except for removed speed function & spin frame
  4. Gold Function: Plan A + flash pattern & spin frame would turn on at gold function
  5. General Neopixels: removed 
  6. Also: all tracker neopixels: if the floor was on but not active, the corresponding light would be white. If it was active, it would be blue. Ex: floor 1 is on, but user is controlling floor 2: floor 1 neopixel = white, floor 2 neopixel = blue

Later that night, I fixed up the neopixel code, added the spin frame and flash pattern as an additional component of the gold function. I also added an on/off function to the code, bringing us to “version 5”, then finally went to sleep at 4 am:

V5: The night before the presentation:

  1. All the same except each time a muyu was struck, it’s floor/function would be turned off if on. Ex: if muyu 1 was struck 3 times when the third floor was on, the third floor would turn off, muyu 3 & 4 deactivate. If muyu 3 was struck when the flash function was on, the flash function would turn off.

The next morning, Luna and I came to the classroom early to set up. We spent some time figuring out how to best align the projector we were using to project the images onto the pagoda. After testing version 5 of the code, Luna said it felt more confusing, so we then took it out. Unfortunately, when taking it out, I accidentally broke the code and had to quickly replace it with an older code and remove the speed function from it. We managed to have everything up and running just before class started. However, because of this last minute fixing, we ran into a problem: the flash function would have a large portion of it blacked out due to my hasty changes to the gold function. Additionally, during the presentation, the first floor would for whatever reason, automatically trigger. This was a problem we never actually found the root issue for. However, it wasn’t an issue during the IMA show and only showed back up when we were making documentation. Here, we found a solution — if we switched the USB-C port the arduino was plugged into and reuploaded the Arduino code, it would prevent the first floor from automatically triggering. This would only work for one run, so everytime we ran the code anew, we would have to switch ports and reupload. During the IMA show, we also had more issues with muyus 2 and 3 — the more floors that were on, the less they seemed able to trigger. We’re also unsure why this happened. As a side note, when we were disassembling, we did find that muyu 3’s knock sensor was actually broken. We aren’t sure when it broke, but it’s very possible it had been the source of our muyu 3’s poor reactivity.

I think the greatest drawback of our project is its learnability. As Professor Garcia said in our presentation feedback, there’s a very fine line between making instructions too obvious and having a presentation be too confusing. Unfortunately for us, I think our project landed well on the side of “too confusing”. The plans we made to improve the projects predictability were unsuccessful, and some mechanisms, such as muyu 1’s, would’ve been near impossible to guess. Professor Gottfried made a very important note that it would’ve been best to show a response on the pagoda instead of the neopixel trackers, as users would be focused on the pagoda instead of the box. Through all the testing after the presentation, I think this comment rings especially true. Additionally, because the code was fairly buggy, an input did not necessarily create the correct command, which made learning it even harder. With more time, adding in a form of feedback on the pagoda would likely be a fairly easy fix for this learnability issue. However, what’s more difficult to solve would be the lack of response from knocking certain muyus.  Because muyu 1 was the first to be knocked, its issues were very obvious and appropriately dealt with. As such, muyu 1 was almost completely functional, while muyus 2 and 3 often ran into issues. A problem here is also that we still aren’t sure why they aren’t working well. Is it the sensor? The extraneous vibration? Neopixel interference? Too much data? A bad line of code? If we had more time, I would also focus on figuring out exactly where the code went wrong, where the problems arose from, then fixing it so that the project would run completely smoothly.

Throughout this process, Luna and I often joked that the Merit Pagoda ran on equivalent exchange: for other people to gain peace from it, we first had to sacrifice our own. After the presentation and during the IMA Show presentation, we received quite a few comments that it did evoke a peaceful feeling, which I’m very happy to hear. We also received a lot of comments saying it looked cool, which was good to hear that the time we spent on design paid off. I think if our equivalent exchange jokes were true, and if the people testing the pagoda felt as peaceful using it as we were stressed while making it, then this project would be an absolute success in my books. Stress and success aside, I do think this was a very educational experience. From this project, I learned a great deal technically (3D printing, removing supports, laser cutting, using millis in code, etc) and emotionally. Importantly, I think that a key takeaway is to plan big, but still small enough to leave time for backup plans. If our plan wasn’t so massive, we likely would have had enough focus to at the very least figure out our issues and have a way to nullify them. I want to give a very heartfelt thanks to all the Professors, LAs, and Fellows, especially:

  • Professor Andy Garcia, who spent so much time helping us with brainstorming, feedback, code, laser cutting, and a whole host of other things, in addition to teaching us about code, circuitry, and fabrication in the first place
  • Professor Gottfried Haider, who consistently helped fix horrifically buggy parts of our code and provide resources when we needed them
  • Professor Margaret Minksy, who spent two hours helping me figure out the issue with my audio code
  • Sylvia, who helped us fix the neopixel interference and also prevented us from accidentally blowing out our computer from bad circuitry
  • Freddie, who helped us to 3D print our muyus
  • Kevin, who helped us to operate the laser cutter when we forgot to draw a line and also helped with coding issues

It was with such massive support from Inter Lab that we managed to create an even semi-functional project, and more importantly, made the entire semester an engaging, entertaining, and educational experience.

Pagoda Experience Overview:

 

Full Code:

https://docs.google.com/document/d/15le8f5_p0zvhi3Dryl_CY9h3LinSWh22WCWdW049gwY/edit

Appendix:

Bonus Video: After several hours of the Merit Pagoda not really working, we decided to embrace its “teenage rebellion” and play in “Smells like Teen Spirit” by Nirvana

 

Leave a Reply

Your email address will not be published. Required fields are marked *