The fateful day has finally come to present our final prototype and honestly… I don’t feel too great about it. We stayed up late the night before finishing everything, and it didn’t go according to plan. After connecting everything together we faced a lot of audio hardships which I discussed in my previous blog post. In addition, there were a couple of scripting issues on my side which made the system slow and clunky, which only worsened the fact that the prototype’s buttons came out rather stiff.
Overall, I’m not happy with the artifact we created in the end. Our teamwork and communication was spotty, and this slowed out project down to the point where our final prototype is what we should’ve had completed two weeks prior to the deadline. This could be put up to inexperience in our team members. Most of us had little experience in any of the relevant jobs for this project, each saying we were willing to try new things and up-skill ourselves. While I can say I did that myself, I feel like a couple of my group members didn’t fully commit to that promise. While I’m frustrated with these particular teammates for not giving it their all, I can’t help but wonder if things would have turned out differently if I took a more hands on approach the project management. Perhaps if I’d been stricter about deadlines and progress updates things would have gone smoother? However, when nobody else ever updated a single task in our project management software, “Hack’n’Plan”, that might not have been the case. Regardless if I were to be thrust into another position of leadership I know for sure that I would work twice as hard to keep track of my team’s progress and maintain pace through all the deadlines. I now know how important such a role is.
Hack ‘n’ Plan. Sadly abandoned by all in the lead up to final submission.
While I’m not satisfied with the outcome of this experience, I do feel like I’ve learnt a lot. In terms of practical skills, I learnt stuff from the use of project management software like “Hack’n’Plan” to programming and building Arduino circuits, as well as the wielding of the mighty soldering iron. In addition, there’s a whole host in interpersonal, collaborative and leadership lessons to be taken from my time on this project. So regardless of the artifact created, I do think there are many positives for me after undergoing this project, and I do hope my teammates had similar learning experiences.
The time came for me and my team to put together our final prototype by combining a small box of pressure plate-buttons, our Arduino based audio system and my input extending shift registers. However, not all was well in the realm of audio. Our audio system worked in a strange way that I found to be rather impractical. I decided to trust my teammates in making it work, and in the end it did… partially.
The system worked by reading files from an SD card to a small cheap speaker. We used an SD card because the Arduino didn’t have enough memory to keep all the sounds on it. However, this presented a couple major issues. The first being that we had to stream data from the SD card to the speaker, instead of loading the whole sound into memory and playing it normally. Because of this we couldn’t combine sounds through the Arduino either. To resolve this, my teammate created a python script that took 13 sounds (for the 13 buttons on our prototype) and found every single combination of these sounds.
This is the part I found to be impractical. It created a vast 8193 individual sounds that took up 7 gigabytes of space on the SD card. Looking at this I felt that there had to be a better way to go about this. I only mentioned this briefly and didn’t chase the point much further because time was scarce, and I didn’t want to demoralize my friend.
In the end I’m not sure if there were any flaws with this system, besides the excessive use of space on the SD card. There seemed to be no major delay in the Arduino finding the correct file. The python script we used wrote out the file names as letters. “A” represented the first sound, “B”, the second, etc. In the main script for our prototype, we assigned each button a letter too. When the system checked if a button was pressed, it would write the button’s letter to a string if it was activated. We then used this string to get the correct sound to play. This meant we could play one sound with each button press, or we could play combinations of sounds.
I’ll relevant pieces of code attached at the end of this blog post.
Yet in the end it was our cheap speaker choice let us down. Playing individual sounds through the speaker was noisy and it only got worse when we played one of the fusion sounds by pressing two buttons at the same time. All we got back was a distorted abrasive mess. Unfortunately, this is where the road would end for us. With no more time all we could do was connect all the electronics together and hope for the best.
Masterpost || <009> 010 <011>
Keep reading for the relevant pieces of the Arduino script:
pin_read(); can be found in blog post 008. This script uses two arrays of booleans - named “RegisterOutX” - instead of bytes to track the output of two 74hc595 shift registers.
playSound();
```
void playSound()
{
// Check inputs from registers (buttons) and calibrate trackName
if (RegisterOut1[0] = true) trackName = trackName + "A";
if (RegisterOut1[1] = true) trackName = trackName + "B";
if (RegisterOut1[2] = true) trackName = trackName + "C";
if (RegisterOut1[3] = true) trackName = trackName + "D";
if (RegisterOut1[4] = true) trackName = trackName + "E";
if (RegisterOut1[5] = true) trackName = trackName + "F";
if (RegisterOut1[6] = true) trackName = trackName + "G";
if (RegisterOut1[7] = true) trackName = trackName + "H";
if (RegisterOut2[0] = true) trackName = trackName + "I";
if (RegisterOut2[1] = true) trackName = trackName + "J";
if (RegisterOut2[2] = true) trackName = trackName + "K";
if (RegisterOut2[3] = true) trackName = trackName + "L";
if (RegisterOut2[4] = true) trackName = trackName + "M";/*
if (RegisterOut2[5] = true) trackName = trackName + "N";
if (RegisterOut2[6] = true) trackName = trackName + "O";
if (RegisterOut2[7] = true) trackName = trackName + "P";*/
if ((trackName.equals(playingTrackName)) || (trackName.equals("")) || (tmrpcm.isPlaying()))
{
Using default electronics kit buttons is great and all, but for my team’s prototypes we need to make our own. Our prototype is a button-wall that plays different sounds when certain buttons are pressed. However, these buttons are in fact small sections of the wall.
So that is to say when one of these sections is pressed down, it should act as a button and complete a circuit. We wanted to make the prototype cheap, so our primary material will be cardboard. For circuitry purposes we will use small tin wires, electrical tape, solder, header pins and aluminum foil.
We used one large piece of cardboard to create a backing for the buttons and cut up 13 individual pieces of cardboard in the shape of the concept buttons. We then created 26 electrical contacts, two for each button. One contact would go on the underside of the cut-out button piece, and the other would go on a raised piece of cardboard attached to the top of the large backing board. We would then put a pair of wires through the backing board and strip the ends off of both of them. The bare wires are attached to one contact each using electrical tape to ensure the ends of the wires stay in place and are insulated from the opposing contact. To finish each button, thin pieces of foam were glued to the cut-out and then the backing board. The foam keeps the contacts separated until a force is applied to the top of the button. When enough force is applied the two contacts meet and a circuit is formed with the two wires.
To finish things off, the other ends of the wires are grouped in pairs depending on what button they came from and are soldered to a pair of male header pins. This allows us to connect our newly made buttons to the Arduino board, and know exactly which button we are interfacing with.
Methodology Blog 008: Multiple Input with shift registers
The other week I created an Arduino prototype meant to take input from an array of buttons and play a music loop depending on which one was pressed. Upon play-testing this system, the most common piece of feed back was “why can’t I press more than one button at once?”. When every single play-tester commented on this issue it makes me wonder how I didn’t even think about the issue. Perhaps I was too caught up in the programming/circuit building side of things? Whatever the reason, there was an issue with the system I had created which needed to be resolved.
Reading multiple inputs directly from the Arduino pins would be easy, however that means I’d need one free pin for every single button but that’s not practical when you’re looking at 10 or more of them. In addition, the system needed to be quick, as significant input delay could ruin the experience. So, I need a system that’s fast and works off of a few pins from the Arduino board.
Thankfully, youtuber Kevin Darrah had already created the perfect solution.
He used a couple 74hc595 shift registers to create a means of creating an infinite amount out inputs, using only four pins on the Arduino board. Traditionally shift registers are used for the opposite, to create lots of outputs for the Arduino using only three output pins. The twist to turn these expandable outputs into inputs is to link all of the shift register output pins to buttons, before linking these buttons together and taking their collective output into one input pin. A script can then detect if any button was pressed in the array, and then begin a process to check which button was pressed. As soon as the Arduino detects an input on the input pin, it turns each of the shift registers’ output pins on one by one. If a button connected to one of these outputs is held down, the Arduino will detect this on the input pin, and make not of this. By the time the process is complete, the Arduino will know which button(s) were pressed down. Because this system checks each pin one by one it can detect if multiple buttons were pressed at the same time.
Diagram drawn using Autodesk Eagle Educational Edition
That’s not to say that this system is flawless. I created my own version of Darrah’s circuit and script but found that my shift registers would to completely haywire on me. Darrah had used an SPI interface to communicate with the shift register chips. However, when I used this exact same system my shift register chips wouldn’t work properly. The data sent to them would get completely jumbled and pins would turn on and off at random.
To resolve this, I used the Arduino’s default command for sending data to other devices, however this caused my system to operate significantly slower than Darrah’s. While I would like to make the SPI interface work, time is closing in one me and my team, so I have chosen to use this slower, less optimal version. I’ve now passed the circuit and scripts onto my team member Drew, so she can solve issues we were having with the speaker and SD card setup. If all goes to plan, we will have a system that can read multiple inputs and send mixed outputs to the speaker. Time will tell.
Masterpost || <007> 008 <009>
Keep reading for the Arduino script:
```
// Pin connected to latch pin (ST_CP) of 74HC595 // Originally 8
const int latchPin = 4;
// Pin connected to clock pin (SH_CP) of 74HC595 // Originally 12
const int clockPin = 13;
// Pin connected to Data in (DS) of 74HC595 // Originally 11
const int dataPin = 11;
// Pin connected to output of switch array // Originally 2
const int inputPin = 2;
void setup()
{
//set pins to output because they are addressed in the main interrupt
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(inputPin, INPUT);
// Ensure latch and clock pins are low to start.
digitalWrite(clockPin, LOW);
digitalWrite(latchPin, LOW);
// shift a full byte to the register
shiftFullByte();
shiftFullByte();
// Create an interrupt routine that calls the function pin_read();
Serial.begin(9600);
attachInterrupt(
digitalPinToInterrupt(2),
pin_read, RISING);
}
void loop()
{
}
void pin_read() // Check to see which buttons were pressed when an input is detected
{
for (int j=0; j<50; j++) // Delay to make sure the buttons are solid on and to give time for simultaneuos activation
{
delayMicroseconds(1000);
}
check = 1;
for (int j=0; j<8; j++) // For loop, cycling through one shift register (8 cycles for bits)
{
// shift a check byte to the register
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, emptyByte);
shiftOut(dataPin, clockPin, MSBFIRST, check);
digitalWrite(latchPin, HIGH);
delayMicroseconds(500); // Small delay to make sure pin goes high
if(digitalRead(2) == HIGH ) // Create a byte that stores which button is currently active
{
bitWrite(buttonActive1, j, 1); // Write 1 if the pin being checked is HIGH
}
else
{
bitWrite(buttonActive1, j, 0); // Write 0 if the pin being checked is LOW
}
check = check<<1; // Move the bit in Check over one place. I.e; 10000000 to 01000000
}
check = 1;
for (int j=0; j<8; j++) // For loop, cycling through one shift register (8 cycles for bits)
{
// shift a check byte to the register
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, check);
shiftOut(dataPin, clockPin, MSBFIRST, emptyByte);
digitalWrite(latchPin, HIGH);
delayMicroseconds(500); // Small delay to make sure pin goes high
if(digitalRead(2) == HIGH ) // Create a byte that stores which button is currently active
{
bitWrite(buttonActive2, j, 1); // Write 1 if the pin being checked is HIGH
}
else
{
bitWrite(buttonActive2, j, 0); // Write 0 if the pin being checked is LOW
}
check = check<<1; // Move the bit in Check over one place. I.e; 10000000 to 01000000
}
I touched on play-testing a little in my last post but wanted to elaborate further on it here.
The main piece of feedback was: please pretty please allow us to press multiple buttons at once! Every single play-tester commented on this so it’s easily our highest priority. Drew will look into a system that allows us to play multiple sounds at once and I will look into creating a system that accepts multiple button inputs at once.
The rest of the feedback came in little bits and pieces of what people wanted to see.
Some people talked about looping systems, others mentioned recording would be a cool idea. Our initial idea for the part we prototyped was a wall of switches that worked like a drum rack from a DAW (Digital Audio Workstation) application like Ableton. Some of our play-testers brought this idea back up, meaning that there is likely potential in that original idea that we have neglected.
In the meantime we intend to continue working on this current version of the button wall by improving it with simultaneous activation and playback.
It’s finally time to dive into Arduino code circuits and programming! I began by ordering a starter kit from PBtech, which came with a handy booklet explaining the basics of electronics and the Arduino Uno.
Inside this kit were instructions for a “4 Key keyboard”. I gravitated towards it immediately due to its musical nature. This project worked by taking inputs from a “resistor ladder” and using those inputs to decide what signal to send to a piezo, which is a small speaker like device.
A resistor ladder is a set of buttons, connected by resistors of differing strengths. Because resistance effects current and voltage, each button’s ‘line’ has its own unique voltage. Feeding the output of the resistor ladder to an analog pin on the Arduino board allows me to determine which button was pressed by checking for its unique voltage.
I soon moved on to create our first prototype using this knowledge. In the case of the “4 key keyboard”, 4 buttons are used to determine 4 different pitches to play from the piezo. For this prototype I wanted to use 10 buttons. This wasn’t too difficult to achieve, as I just used more and more resistors to create more unique voltages. There would be an eventual limit to how many unique voltages you can squeeze out of a resistor ladder, however 10 was well within this limit.
Schematic created using Autodesk Eagle Educational Edition
Instead of outputting to a piezo, I used a system created by my classmate Drew. She had connected an SD card and small speaker to the Arduino and could tell the speaker to play one of the sounds on the SD card.
However, there is an issue with this system. The Arduino isn’t powerful enough to remember an entire audio clip and write it out, so it has to “stream” the data from the SD card to the speaker. Consequently, it cannot mix two clips together. This relates to another issue created by my resistor ladder, which became very apparent when we started play-testing. It cannot detect when two buttons are pressed at the same time. These two issues mean that there cannot be simultaneous input or playback of sounds which all our play-testers commented on, saying that this is a feature they would like to see.
Out whole pitched concept is this interactive installment called “The Cube”. It’s a large 2.5m3 white cube with two faces missing. These faces are adjacent to each other, and people are able to enter the cube by passing through these missing faces. On the inside of the remaining two faces will be a couple of interactive displays. One will feature a wall of buttons, which each play one of a curated set of sounds sent in by the Auckland community. The other wall features several touch sensitive interfaces that allow users to distort and modify the sounds created by the button wall. Finally the central part of the floor will be pressure sensitive, and standing on it will create harmonies and bass tones to form a grounding layer for the sounds played by button wall.
While this would be amazing to create in full, we are just five inexperienced uni students with limited time. Instead we will endeavor to prototype just one of the three interactive parts of the cube. We have chosen to create the button wall for this as it is the central and most important component of the cube.
As mentioned before this wall will play sounds sent in by the community. To do this we will use a mobile application or a website which users can upload sounds to. Each week we will collect these sounds and filter through them to find the best and remove all inappropriate, offensive and joke submissions. We can incentivize user uploads by rewarding the samples that get chosen with a voucher or other reward, and letting users know that we’re looking for interesting and unique sounds, not a collection of memes.
This week’s class readings have us learning about teamwork, communication and documentation. Apparently, it’s all about love. Dangit Schell.
Love
Shell informs us that the way to overcome the vast differences in personality, opinion and worldviews that one will encounter in a team, is with love. Not loving each other, though that’d be nice, but loving the game everyone is making.
Problems arise when there is no love. When there Is no passion. When people don’t give a damn about what they’re doing. This can happen for various reasons, and simply cannot be ignored.
Those who do not love games need to be eradicated.
Those who do not love the kind of game being made should be provided opportunity to re-invest themselves.
Those who do not love the direction the game is taking must be consulted. In a team all must be heard, and all must share the same common vision.
If all else fails, think of the game as a gift to someone else. That way you can love it even if it’s not something you want.
Communication
As mentioned before: Every voice on a team must be heard. It is therefore wise to keep everybody involved in the iterative design process. This communication prevents designers from going off on their own tangents and getting all hissy when nobody shares their vision of game perfection. Moreover, bringing everyone in on the design process means more minds churning over and over. We’ll get more ideas and dispose of flawed concepts much more rapidly. It provides many perspectives and finally, helps unify the team around one all-important vision.
A common design cycle is for designers to first brainstorm, then work independently before coming back together to share ideas and improve upon them, leading to more brainstorming etc. It’s important to bring in as much of the team as possible at the beginning/end of this cycle, as this is the point where ideas undergo the most evolution and ideation occurs.
Teamwork Tips
It wouldn’t be a Schell chapter if he didn’t give us a nice big list of tips on something.
My personal highlights from this round of teamwork tips include:
Objectivity Encourage the participation of everyone by removing all personal connections to ideas. You say “the twisted rose idea” instead of “Sierra’s” idea. You don’t put ideas down, instead you push ideas up. It’s interesting how changing phrasing like this can supposedly create much more harmony.
Honesty, Trust and Respect How important trust is for harmonious teamwork. These factors really play into each other, especially the latter two. Nobody respects a liar, and it’s hard to trust someone when you have no respect for them. Schell makes a point out of how physical real-world interaction is important for trust. He says that there is a certain chemistry that simply doesn’t happen over online communication that builds trust like nothing else.
Unity It’s impossible for everyone to agree, but compromises must be made in the name of progress! If someone will not step down from their views, ask: “what would it take to bring you in?
As I keep repeating, a common vision is important. Without it unity fails and the team will eventually crumble as everyone works towards something different from their co-workers.
Documentation
It’s ironic really that while reading this week’s chapters I took these notes:
Documentation about documentation. Talk about meta.
I do agree that human memory is weak and that writing things down is of high importance. However, documentation is also a means of communication, not just memory retention. Consequently, this allows designers and other team members to share, critique and evolve ideas, and is vital to success in early stages of development. Documents also become a key point of reference across the many disciplines and departments within game design as the project progresses. That isn’t to say that documentation is meant to be a solid plan. Far from it. Adhering to the Game Design Document is the path to hell… apparently. Documents instead exist in a state of flux as the game y’know, develops. This is especially true of scheduling documents. Thankfully we have hack and plan which should help us heaps in that area.
It’s kinda exciting working in a team. Also, daunting. I worry about us all harmonizing. I worry a lot about everyone being invested in the project. I really want people to care about what we’re making, instead of say… feeling guilty for letting the others down. Maybe I’m too into this but eh whatever. I want this group project to be a success, not a disaster.