The mPAD
The mPAD is a conspicuous, intuitive personal assist device for managing and keeping track of daily tasks.
Process:
There were two main tribulations that caused fairly significant shifts in my plans when building the mPAD. The first of these was a coding issue. I had to create two iterations of the code for this electronic planner. I had decided that I wanted to push my technical knowledge and skills with this project, so I tried to utilize data structures not covered in the class and offer more interactivity than is typical in many of the projects and examples shown: I wanted to go beyond having one input give one specific output, or one tool used for only one action. I wanted something that was dynamic. That inspired me to create an electronic device with its own graphical user interface (GUI). I was adding, moving, and removing words, so my first iteration of the programming intuitively utilized Strings and String Arrays. This actually worked quite well up to a point. I was able to move strings between different arrays and I was even able to create a typing system for inserting one’s own tasks via a videogame high-score inspired letter scrolling system. As I implemented more of the rudimentary functions of the planner, I ran into issues where the Arduino would read various arrays where I was storing tasks as empty. The error appeared to be that I was either running out of memory, or that data was being accidently overwritten due to the large size of the Strings, which, I learned, were actually objects. Though this obstacle was encountered quite late into the project time, I decided to rebuild my program using char*’s rather than Strings. They took up less memory, and were easier to use for creating data structures which I hoped to use for creating a permanent memory. I was able to create this new program by the critiques, but I did have to relinquish some interesting aspects of my project that I had hoped to implement like the videogame-esque task entering system that I had worked on the previous iteration.
The other issue that made me rethink my project was a more physical one. I had decided that I wanted a sleek, minimalist design for the mPAD. I wanted something that would be able to sit on my dark wooden desk at home that would be inconspicuous enough to not seem out of place among my old maps and pseudo-antiques, but also conspicuous enough for me to notice it when I sat down there after school. I wanted something simple and ergonomic, so that the user’s (my) eyes would immediately be attracted to the screen and buttons. I forget things, so I wanted to somewhat subconsciously force my brain to recognize the electronic box full of what I needed to do as important. My inspiration was from the early Apple products, but with the prototype/maker culture styling that I quite enjoy. To attain this form, I wanted to make the buttons and screen take up as much of the device as possible: perhaps a bit utilitarian in style, but effective. I made several designs using CAD to be 3D-printed. From past experience, I knew that printing one would likely take between four to six hours. I put my name on the printing queue, and continued soldering wires together. As hours passed, I remembered that many of the printers were broken and realized that if anything went wrong with the print, I might not have a housing. It was late at that point, passed when the IDeAte lending desk was open, but I had a large sheet of acrylic from a previous project, so I decided to create a new housing that I could laser cut from it. This involved some difficult aspects such as a backing plate to sit behind the buttons and keep them from being pushed through their mounting holes, but I was able to build it. By the time I was able to use the 3D-printers, it was the afternoon before the critique, so I was fairly happy that I had created a backup. Unfortunately, the acrylic was transparent. If my design meant for the user to immediately focus on the screen, I wanted the screen and buttons to be the main source of dissonance in the design, and seeing all of the wires inside would be quite distracting. To maintain the general homogeneity of the housing for this end and because the color would go well with my mahogany-veneered desk, I decided to leave the protective paper on the acrylic. Though very different from my original housing design, I ended up quite pleased with how it looked. It had the dissonance/visual interest where I wanted it at the user interface, and general cohesion/homogeneity everywhere else.
Discussion:
For this project, I took on my trouble of remembering things when I was doing something else. There are sticky notes and phone apps out there that do this, but I always found sticky notes too inconspicuous (I’d always forget they were there) and phone apps too distracting and their lack of physical interaction unappealing. I wanted something physical and conspicuous that was purely meant for the task of recording and reminding me what I had to do. This project was, overall, a great learning experience, and I was able to push myself into new areas of physical computing: beyond what I could do before. It has also, after the critiques from the last project, allowed me to explore design in my devices further. For the design, there were aesthetic features that I wanted to add such as the minimalism and how it would fit on my desk or nightstand, but I especially wanted to focus on its ergonomics. I wanted to create a device that a person could understand how to use it from its design. I also wanted to create a design that would stand out to a person while they were sitting at their desk. Overall, I was quite pleased with how my choices of size, color, button placement, and menu system turned out. The buttons, for example, were placed in a way similar to old cell phones and arrow keys on a computer: they were arranged in a diamond with the top and bottom scrolling through the menu and the left and right buttons navigating back and forth. I was a bit disappointed in the size of the device, however. I was hoping for something smaller that could perhaps be put in a pocket or clipped onto one’s belt. Unfortunately, due to the constraints of the LCD screen, the Arduino, and, particularly, the wiring, it had to be bigger. Also, due to this, the back of the mPAD couldn’t be affixed, and I had to create a makeshift mesh to hold the wires and Arduino in. Overall, however, the mPAD did what it was supposed to and provided a fairly intuitive and minimalist look. I am happy with how it turned out, but I do want to continue working on it and improving it.
There were many surprises and challenges throughout this build. Most notably were the times when my program indexed outside of an array and random characters and designs filled the LCD like a screen from The Matrix, but there were pleasant surprises as well. One example of this was the backing plate that I created for the buttons on what was intended to be my backup housing. In order to allow wires through, but prevent the buttons from slipping inside the housing, I created holes in the backing plate with two rectangular protrusions coming from opposite corners. I wasn’t quite sure if the protrusions were strong enough or that the holes were big enough as I had already had issues fitting some buttons with solder into the face plate’s holes. Luckily, the design worked quite well and all of the buttons and wires fit through. Another surprise was that when trying to fit all of my soldered wires into the housing, the LCD screen stopped working. I was able to conclude that it was likely an issue with the soldered connection to the common power supply. As a quick test, I took a male-to-female jumper and wired the LCD to the five volt output on the Arduino and moved the common power to the 3.3 volt pin. To my surprise everything started working again, so, rather than having to solder everything again, I used this setup for my final design. Finally, I was surprised as to how effective the buzzer was at making deleting/completing a task. Originally, the buzzer was something I added in just to have, but it ended up making interactions with the mPAD much more enjoyable. It ended up being a form of positive reinforcement: when you checked off a task, the buzzer would play a nice jingle that I based off the Legend of Zelda chest opening sound. Despite the many setbacks and features I had to remove from the mPAD, I was still surprised with how easy it was to actually use and how much I liked it. I could use it to help me remember what I have to do as is.
Through this project I have gone from practically no experience soldering to having soldered my entire project together. Along with the basics of how to solder, I have started gaining intuition and started understanding how to solder in certain situations. One of the major problems I faced in terms of soldering for this project was the packaging of the wires. When I created my housing, I designed it to hold the more apparent materials such as the Arduino, battery, and LCD, but neglected the wires. I imagined that I would be able to easily compress and bend them to fit in the empty space. I was wrong, and it led to me being unable to fit the back of my housing on. This was a bit disappointing, but I do plan on remaking the mPAD with some new lessons I have learned: use stranded wire whenever possible, use the shortest pieces of wire you can, and plan the direction and connections of the wires so that they lay where you want them to. Next time I might even try to implement the breadboards on which one can solder circuits together.
I have also learned a great deal about many more in depth aspects of programming the Arduino. Most notably, as it was the main tool I used to create my program, was gaining experience with arrays and array manipulation. Though I have used arrays using python during a computer science course freshman year and am often using MATLAB, Arduino has many more specifics that challenge how have generally used them. In Arduino, arrays must have a fixed length and cannot be changed. This issue led to me developing different possible workarounds to be able to move tasks around in the programs memory like I wanted. For example, if I were to delete an element in the array I labelled as “To Do” because I had completed the task, it would leave an empty string that would be visible on the menu. To avoid this problem I was able to make a new array that had every element after the deletion shifted over, and then reset the elements in the original array to be the same.
I also worked with the EEPROM memory on the Arduino. This is the physical memory that remains even when the device isn’t powered. I was able to create functions that were able to write and read character arrays to and from the EEPROM memory. It was a very interesting challenge to tackle, and I was able to learn about creating data structures. Unfortunately, there were some errors trying to use the characters once I read them back from the memory. I find this a bit disappointing because it was nearly ready to be used, but due to time constraints, couldn’t. This feature isn’t necessary, but would be extremely useful to conserve battery.
I am definitely planning on creating future iterations of the mPAD. I really do believe that it would be quite useful to me in my daily life: it might actually remind me to do things that I forget. Before I consider it complete, though, there are a few features that I think would make it something actually quite integral to my life. Firstly, I would like to add a method to enter tasks onto the device from the device itself or the computer. I have a method for entering it onto the device from previous coding attempts that weren’t implemented. This would involve a system similar to videogame high score systems where one would scroll through letters to select. I would also like to be able to enter them in from the computer. This would require writing from the serial monitor and a change in the housing that would allow for the Arduino’s USB connection to be exposed. It would also require another feature that I have worked on: reading and writing to the EEPROM memory on the Arduino. Having a permanent memory that won’t disappear when the mPAD is unpowered is quite useful when it is being plugged into computers and being switched on and off. My final addition I want to make is some sort of clock and alarm system so that one could set a time they want to complete or be reminded of a task by and it would play an alarm and show a reminder when it was that time. I believe that these few additions could make the mPAD a useful and unique device.
Schematic:
Code:
#include <Wire.h> #include <LiquidCrystal_I2C.h> #include "pitches.h" #include <EEPROM.h> LiquidCrystal_I2C lcd(0x3F,16,2); int hmPin = 8; int frdPin = 9; int bckPin = 10; int nxtPin = 11; int notePin = 7; char* topMen [] = {"Add Task","To Do","Save","Read Test"}; int menuLen = 3; char* tasks [] = {"Feed Dog","Do Homework","Eat Food","Save the Pres"}; int taskLen = 3; char* toDo [4]; int toDoIn = 0; int toDoLen = -1; int menuPos = 0; int up = 0; int dwn = 0; int nxt = 0; int hme = 0; int melody[] = {NOTE_A5,NOTE_AS5,NOTE_B5,NOTE_C5}; int noteDuration[] = {1000/8,1000/8,1000/8,1000/8}; void setup() { lcd.init(); lcd.backlight(); pinMode(hmPin,INPUT); pinMode(frdPin,INPUT); pinMode(bckPin,INPUT); pinMode(nxtPin,INPUT); Serial.begin(9600); //eepromRead(); } void loop() { int nxtBt = digitalRead(nxtPin); int upBt = digitalRead(frdPin); int dwnBt = digitalRead(bckPin); if(!upBt){up=0;} if(!dwnBt){dwn=0;} if(!nxtBt){nxt=0;} lcd.setCursor(0,0); lcd.print(topMen[menuPos]); if(!up && upBt) { up = 1; if(menuPos < menuLen) { menuPos++; }else { menuPos = 0; } lcd.setCursor(0,0); lcd.print(" "); }else if(!dwn && dwnBt) { dwn = 1; if(menuPos > 0) { menuPos--; }else { menuPos = menuLen; } lcd.setCursor(0,0); lcd.print(" "); } if(!nxt && nxtBt && menuPos == 0) { delay(50); nxt = 1; addTask(); } if(!nxt && nxtBt && menuPos == 1 && toDoLen != -1) { delay(50); nxt = 1; looky(); } if(!nxt && nxtBt && menuPos == 2) { delay(50); saveToDo(); } if(!nxt && nxtBt && menuPos == 3) { delay(50); eepromRead(); } } void addTask() { up = 0; dwn = 0; nxt = 0; int push = 0; int taskPos = 0; int hold = digitalRead(nxtPin); Serial.println("I'm here"); while(push == 0){ int nxtBt = digitalRead(nxtPin); int upBt = digitalRead(frdPin); int dwnBt = digitalRead(bckPin); if(!upBt){up=0;} if(!dwnBt){dwn=0;} if(!nxtBt){nxt=0;} if(!nxtBt){hold = 0;} lcd.setCursor(0,0); lcd.print(tasks[taskPos]); if(!up && upBt) { up = 1; if(taskPos < taskLen) { taskPos++; }else { taskPos = 0; } lcd.setCursor(0,0); lcd.print(" "); }else if(!dwn && dwnBt) { dwn = 1; if(taskPos > 0) { taskPos--; }else { taskPos = taskLen; } lcd.setCursor(0,0); lcd.print(" "); } if(!hold && !nxt && nxtBt) { lcd.setCursor(0,0); lcd.print(" "); menuPos = 0; up = 0; dwn = 0; nxt = 1; hme = 0; push = 1; toDo[toDoIn] = tasks[taskPos]; toDoIn++; toDoLen++; } } } void looky() { up = 0; dwn = 0; nxt = 0; int toMen = 0; int push = 0; int toDoPos = 0; int hold = digitalRead(nxtPin); Serial.println("Look at me"); while(push == 0){ int nxtBt = digitalRead(nxtPin); int upBt = digitalRead(frdPin); int dwnBt = digitalRead(bckPin); int hmeBt = digitalRead(hmPin); if(!upBt){up=0;} if(!dwnBt){dwn=0;} if(!nxtBt){nxt=0;} if(!nxtBt){hold = 0;} if(!hmeBt){toMen = 0;} lcd.setCursor(0,0); lcd.print(toDo[toDoPos]); if(!up && upBt) { up = 1; if(toDoPos < toDoLen) { toDoPos++; }else { toDoPos = 0; } lcd.setCursor(0,0); lcd.print(" "); }else if(!dwn && dwnBt) { dwn = 1; if(toDoPos > 0) { toDoPos--; }else { toDoPos = toDoLen; } lcd.setCursor(0,0); lcd.print(" "); } if(!toMen && hmeBt) { lcd.setCursor(0,0); lcd.print(" "); menuPos = 0; up = 0; dwn = 0; nxt = 1; hme = 1; push = 1; } if(!hold && !nxt && nxtBt) { toDo[toDoPos] = ' '; toDoLen--; toDoIn--; char* newToDo [4]; int newIn = 0; for(int tsk = 0; tsk<4;tsk++) { if(toDo[tsk]!=' ') { newToDo[newIn]=toDo[tsk]; newIn++; toDo[tsk] = ' '; } } for(int tsk = 0; tsk<(newIn+1);tsk++) { if(newToDo[tsk]!=' ') { toDo[tsk]=newToDo[tsk]; } } for(int note = 0; note<4; note++) { tone(notePin,melody[note],noteDuration[note]); delay(100); noTone(notePin); } lcd.setCursor(0,0); lcd.print(" "); menuPos = 0; up = 0; dwn = 0; nxt = 1; hme = 1; push = 1; } } } void saveToDo() { char nextChar = '~'; char endChar = ';'; int addr = 0; for(int tsk = 0; tsk<toDoIn; tsk++) { String saveNow = toDo[tsk]; unsigned int letters = saveNow.length(); char charBuf[letters]; for(int let = 0; let<letters; let++) { if(addr == EEPROM.length()) { addr = 0; } EEPROM.write(addr,saveNow[let]); Serial.println(saveNow[let]); addr++; } if(tsk<toDoIn-1) { EEPROM.write(addr,nextChar); Serial.println(nextChar); addr++; } } EEPROM.write(addr,endChar); Serial.println(endChar); } void eepromRead() { int listEnd = 0; int numTRead = 0; int addr = 0; if(EEPROM.length()!=0) { while(listEnd == 0) { char readWord[16]; int wordEnd = 0; int entWord = 0; while(wordEnd == 0) { char val = EEPROM.read(addr); Serial.println(val); addr++; if(val != '~' && val != ';') { readWord[entWord] = val; entWord++; }else if(val == '~') { wordEnd = 1; }else if(val == ';' ) { wordEnd = 1; listEnd = 1; } } char* aTaskRead = readWord; toDo[numTRead] = aTaskRead; numTRead++; toDoLen++; toDoIn++; } } }
Pitches Code:
/************************************************* * Public Constants *************************************************/ #define NOTE_B0 31 #define NOTE_C1 33 #define NOTE_CS1 35 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978
Leave a Reply
You must be logged in to post a comment.