Input Devices
Measure something: add a sensor to a microcontroller board that you have designed and read it.
Learning outcomes:
- Demonstrate workflows used in circuit board design and fabrication
- Implement and interpret programming protocols
Concrete Evidence:
- Described your design and fabrication process using words/images/screenshots.
- Explained the programming process/es you used and how the microcontroller datasheet helped you.
- Explained problems and how you fixed them
- Included original design files and code
Enjoy the Flickr album before I have time to write up this week's work more formally.
This week was crammed. The primary job that I maintain is being a high school science teacher. In that world, this was a big week, and the AP test for the Physics 2 class that I teach is looming. Most of my time has been spent thinking about that test, preparing to run the Finishlynx camera for a track meet, or generally trying to help our oldest students prepare to graduate.
Inputs, I hoped, would be a smooth-sailing affair. I was wrong. It wasn’t.
At this point, I am trying to channel my work towards the end goals of my final project. I want to think about the possible inputs that I will need, and make incremental progress toward that goal. This means that I have a few options to go after:
- A keypad for access and machine control
- A load cell for measuring weight
- An IR presence sensor
- A possible encoder for measuring rotation/distance
The keypad seemed like the lowest hanging fruit and (given the week I described above) that is where I set my sights. Eventually, I will get to those other sensors. However, I reasoned that what my final project needed was either too close to a standard example or more than I would have time to take on in the time I have this week. The keypad that I wanted to use was referred to as a ‘button matrix’ by Adafruit and essentially seemed like the simple button example, but charlieplexed for minimum pin usage.
I have never used this keypad button matrix before, but it seems like a very straightforward application for an Arduino. Adafruit has both a tutorial and a library to help implement this thing easily. However, since this is Fab Academy, I want to use this input with a simple ATtiny44 board and some code written in C, that avoids the abstraction of someone else’s code library.
First, I designed the board based on the specifications of the keypad given on the Adafruit website. This design was done in Eagle, and I have gotten somewhat efficient at this process through recent practice. In addition, the circuit was always going to be relatively simple for this selection of button inputs. I expected that the code would be my biggest struggle this week, but have been ready to get better at the AVR libc work that would be required. At the onset of this week’s work, it had become clear that there are some quirks to writing code for the AVR chips. I wanted/ want to figure those out as much as possible. This button matrix seemed to promise me a chance to work on those details of this skillset.
I began writing the code. First I wrote what felt like a reasonable plan for the logic of how this would work: use the columns as output, and the rows as inputs. Send a signal out on one of the columns at a time and check the rows sequentially to see if any receive the signal, and thus known to be pressed. Store this information somehow, move on in checking all column/row combinations, and then output the findings. This seems best achieved with a bit of object-oriented programming, and I would be happy to do so; however, I was surprised to find that c does not play well with object-oriented code. Instead I opted for some procedural code and storing the data in arrays. However, this came at the cost of much consternation. The code I wrote had terrible syntax. I had to Google most things to make them work and only after what felt like a hundred attempts to compile into hex, did I eventually get there.
Then I got an error that my code would not upload to the board – most likely an electrical problem, or design flaw. This is where I am presently stymied. I need to go back to the drawing board with my circuit for two reasons: I must have messed up one of the communication pins, and the actual keypad has 8 pins instead of 7. So I need to figure that out too…
======================= UPDATE ===============================
I can’t believe how much I have learned! When I look back at this week’s work I am flabbergasted at the things that were glaringly wrong: the circuit board and (missing) serial connection are the most prominent. However, the fact that I did not upload code is just silly. If you read the start of the original post, my focus was elsewhere for this week. Such is the nature of being a teacher and in Fab Academy...
The keypad that I was hoping to build and include here is a part of my final project. I got it working there, although not with full (RX & TX) software serial communication running at the same time on an ATtiny44. I also designed an IR light sensor, but that is about to be redesigned for my final project so that it can operate more like an optical encoder. Anyway, let’s all just pretend I didn’t have that grueling learning process above and hammer out the evidence of meeting the learning objectives right here:
Learning outcomes:
- Demonstrate workflows used in circuit board design and fabrication
- I will just link to where I describe this process in detail, which I wrote while doing my final review of this website for the class
- Implement and interpret programming protocols
- The simplest programming option for a keypad matrix is the Arduino library: keypad.h and this works beautifully
- I also wrote a program after many verions that will work for this ATtiny44 board, although it was never fully implemented in the presentation version of the final project, because of software serial communication limitations at the hub. However the keypad worked nicely in testing and final project development.
Concrete Evidence:
- Described your design and fabrication process using words/images/screenshots.
- The design/fabrication process here was routine: 1) design in Eagle, 2) mill on the MDX-40A, then 3) solder on parts and 4) program
- Here are a few images of the process:
- Explained the programming process/es you used and how the microcontroller datasheet helped you.
- Explained problems and how you fixed them
- Included original design files and code




The program that I wrote above for Learning Outcome 2-2 (just above) was actually nontrivial. I took Neil’s basic button example sketch, and extended it to run a scanning routine. The scanning routine would then spit out which of the keys was presently being pressed. This is onlu possible by basically charlieplexing the buttons: check each combination of row and column. The datasheet is helpful developing a keypad insofar as it explains the DDRx, PORTx and PINx registers, as they apply to inputs. [Which I explore further here.] I expect to use the datasheet more as I explore the implementation of a load cell or home-built encoder for future versions of my final project.
The first step in solving a problem is identifying it. That took longer than it should have sometimes. For example, it wasn’t until the second iteration on board design that I included a serial output. I will attribute this to the fact that I designed the (input) keypad board and (output) charlipled LED board at the same time. the latter didn't need a serial port. For the sake of the final project, it took some effort to work around the memory limitations of the ATtiny44 in order to scan the keys and simultaneously be able to output serial information. I eventually just used the Arduino library for the keypad, and did some bit-banging (from Neil's examples) for an output-only serial port. Frankly, I am surprised that I was so flummoxed by this week’s work. I have made many input devices for regular Arduino devices. I think that missing the serial port on the first board iteration, and taking a while to recognize it, really slowed me down. However, I got it eventually...
======================= FURTHER UPDATE ===============================
After the final presentation (and a few days off), I was back to designing. I had the intent to make a new, completely ‘fabbable’ design for my project. As this includes a new connection to the keypad input, I will review how we got to now and how this workflow should actually go.
First, I made a terrible input board. This first version centered on an ATtiny44 and was based on the ‘outputs’ board I made simultaneously. A terrible idea I had for time-saving. By basing the keypad input on an output, I forgot the need for a serial connection. About a week later, I redesigned this board so that it could be used later in my final project. The redesign included an early version of what would become my own personal serial and power connection standard, based on a 2X3 header. At first, the code I wrote for this didn’t work. I was unsure if it was the keypad or my board, so I tested the keypad with an Arduino. The keypad worked with an Arduino Uno, and so I knew it was my code or board. I fiddled around with the code and eventually got it to the state that is called ‘version 3’ in the downloadable code archive on this page. It still didn’t work. I wasn’t sure why, but I moved on because time is fleeting. I figured I would solve this in the future. I have done inputs many times before in Arduino-only projects…
I redesigned the keypad board again, after I had decided on a final version of my own personal serial and power connection standard. This time I wrote code that included a 2-dimensional array of boolean variables to store which buttons were pressed. This also didn’t work. I made a fifth version of code that looked much more similar to version 3. No luck.
Up to this point, I had been writing all of my code in C, and this was a new language for me at the start of Fab Academy. I used this because it is what Neil’s examples are written in, and I could appreciate his argument that avoiding Arduino avoided overhead on the chip. I had hit this memory/ processing boundary before with Arduino projects and never enjoyed it. Plus, I figured it would be good to learn another language. While C is not far off of the Arduino language, it was not a seamless process to learn C as well as all of the AVR-libc keywords. For example, I had no idea what at bit-shift was in February, or what the chip pin registers were. Most of the time I struggled with the AVR-libc keywords, but this time it was the C language itself. By this point, I had long since written down what I wanted to do as a note in my code; but I was also having a hard time getting that to happen within the confines of the C language.
While assembling the final project before the presentation, I hit some trouble. My FABISP died, so I had to figure out how to get code on my boards without time to make another FABISP. I used the Arduino as ISP that I did at the very beginning of the class, and it opened up a whole new world. I could program in Arduino and then upload to the ATtiny44 boards that I had. Sure, this required me to have installed the chips in the Arduino IDE, but that only had to happen once. The overhead was manageable for my purposes here, and the keypad library for Arduino has a ‘hello keypad’ example sketch that does nearly all of the difficult programming for you. This worked wonderfully. I was happy to see my inputs board working as intended. [But should have captured a video…] The only thing that I needed to do was to add in the serial communication pieces that I needed. Upon compilation, I found that I could not include both the ‘Keypad’ and ‘Software Serial’ libraries and be done. I had hit the previously cursed overhead issue (Why I had avoided Arduino for C in the first place). So instead, I took the next logical step: I used Neil’s bit-banging strategy in the Arduino environment. Bit-banging does not have the overhead of using a library, however I needed to rebuild Neil’s code to work in the Arduino IDE. This is the version that is in the last version of the code, implemented at the time of the final presentation, and it worked when tested as a direct serial output.
Since then, I have integrated the electronics to consolidate the serial connections and communication that exist in my project. I redesigned so that the electronics would have the same suite of inputs and outputs, but in such a way that their connections could more closely imitate the code that I would like to build for their operation. I am tightening my spiral of design. This choice tips it hat to a good workflow for designing any input or output.
Basic Workflow for Designing an Input
The core need for building an input is knowing what you want to measure. Having the objective you want to quantify with electronics well understood must come first. From there, the next two steps of development need to happen together and inform each other: 1) designing the sensor circuits and 2) writing the code to run the input. The circuit design will inform what pins on the microcontroller need implemented in the code. The code requirements for the measurement will determine if an analog comparator input pin or a simple digital input pin need used in the circuit.
In the latest version of my input, I knew that I wanted to measure the digital input of a keypress; so I had the latitude to choose nearly any pin on the microcontroller. I also had some experience with the Arduino development environment and could conceptualize that I would need to be able to identify the pins that were connected to the rows and columns of the keypad matrix. From this knowledge, I designed the schematic of what I wanted in Eagle. That schematic was used to build the board in Eagle. From this point, the remainder of the workflow is set by the tool.




In my Lab, there is a Roland MDX-40A mill and the workflow for that begins with an export of monochrome images, like those above. With these images, it is possible to use fabmodules.org to determine toolpaths for cutting out traces with a 1/64th inch end mill. A separate image can be used in fabmodules.org to generate cutting toolpaths to separate the board from the stock with a 1/32nd inch end mill. Also (with a little extra effort) a modified version of the traces image can be used to identify all of the through-holes that need to be cut, and a very restricted outline function in fabmodules.org can direct the mill to cutout these as well with a 1/32nd end mill, if needed. All bit changes are done by hand with the Roland mill.


In the lab at LCCC, there is an LPKF mill, which has a different workflow. There, Eagle needs to output the industry-standard job files. The mill’s software (with a little guidance on stock size and design specifics) turns this information into toolpaths. From there, and a few more parameters, the machine mills out the board managing the whole process. Including the bit changes! These boards come out micely, but with very little clearance between the traces, so they require more skill to solder.


Once the board exists, the process converges again. First, all of the components need soldered on the boards. The code needs written and compiled, to make sure that it will get that far. From there, and ISP programmer is needed to upload the code onto the board. At this point, the information streaming out of the input needs checked, so that you can be assured it is working properly. From there, the input can be integrated into a larger system.


You can see all images (used and unused) from this week's work HERE.