Creating a Webcam from Scratch

Tell us the story of your project: 

I had an open spot for a class during winter quarter of my freshman year of college, and saw an upper level course that didn't have courses as hard prerequisites. It was EECS 395: Engineering System Design I, which was about creating a webcam from scratch in a team of two or three. It was the hardest class I've ever taken, but I also learned more than I ever have in it.


The webcam features an Atmel SMART ARM-based SAMS48B microcontroller and an AMW004 Wallaby Wi-Fi Chip. The SAM4S8B features 512kB of flash memory and 128kB of SRAM. The AMW004 Wallaby can communicate through UART, SPI, I2C, and USB, can achieve data throughput up to 10 Mbit/s over UART or SPI, and has 1MB flash and 128kB Ram onboard. Additionally, an Omni Vision OV2640 was chosen as the desired camera, with a maximum possible frame rate of up to 15 frames per second. The Wi-Fi chip has a feature where it can act as a server so the website designed for the webcam can be hosted directly on the chip, which can broadcast 1 frame every 3 seconds.

Designing this PCB required many iterations, including two breakout boards provided to us by the professor, one for the microcontroller and one for the Wi-Fi chip. These boards were connected using wires and breadboards to ensure the pin selections and wiring was correct before creating the design in Eagle.

Creating the code proved especially challenging, but luckily, Atmel Studio offers many example projects. Of the nineteen functions (not including the main function) in the final design, only five had to be written from scratch. The program executes as follows. First, the clock, camera, Wi-Fi chip and all the pins are initialized. The program then enters the main loop, where the microcontroller checks for a Web Setup request, and if connected to the internet, waits for a websocket connection. It continues to wait until a connection is available. Once there is a connection, it takes the picture, calculates the length, creates a file on the Wi-Fi chips flash, then writes to the stream so that the website knows to update its image.

One of the more interesting functions that had to be developed is seen below.

This function, while not overly complicated at first glance was actually quite difficult to implement. Because we decided to store the image in a preallocated buffer, it was impossible to determine ahead of time where the buffer started. Additionally, because of the JPEG protocol, we could not know the length ahead of time. This function then, in essence, determines where the start of the image is, here an 0xFFD8, and then from there counts until the image terminates, with an 0xFFD9. Once completed, it ensures that the length does not equal zero and returns the length. 

My partner kept the functional webcam at the end of the project, and we neglected to take any screenshots of the website, so I only have screenshots of the JavaScript from it to show. 

One of the trickiest parts of the JavaScript was getting the timestamp to appear once the webcam started or a websocket was opened. In order to determine that a websocket was opened, an event listener was utilized. This was triggered on mouse click. From there, the code determined whether or not the websocket was opening or closing and reacted accordingly. Another tricky function was related to the time stamp, the messy code of which is shown above. The function setTime() is triggered earlier in the javascript when a message is received from the code. This is the “write” message seen earlier in the C code.

The first case we designed for the webcam went through 4 iterations, and featured a box with a flat top. After printing out the first version of this case, we noticed that it was difficult to set the board down because of how the holes for the power cord and the Wi-Fi chip were placed. The long edge of the board needed additional space to fit inside the case properly. Additionally, the standoffs/screw holes on the top of the case were on the wrong sides, so we couldn’t even get the board partially into the case. When printing out the second version of the case, since the board actually fit into this one, we noticed that we had to really push to get the camera side of the board to fit in the case, which was because we hadn’t noticed the little switch on the top of the camera and neglected to reflect that in our measurements. The third version of the case cut through the top wall, hoping that the camera would stick entirely out of the case, but our measurements were off and this was not the case. The final version’s fix for this was to replace the hole we took out in the last version of the case and to cut out 1.25mm from the inner wall by the camera hole so the switch would fit in the box.

When we were writing the code for the camera, it worked on the breakout boards, but not on our PCB, and we couldnt tell if it was the PCB or the code, so we used one of our professor's boards for the final design.

Most of the soldering was surface mount, which I had never done before and ended with a lot of mild burns from the heat gun, but the end result was pretty clean.

Because we used our professor's board, another enclosure was printed to fit the solution PCB. This iterative process of printing the enclosure went much faster and required minimal editing. In fact, the final version printed was only required in an effort to move the camera hole so it was more centered. Even still, the width of the standoff/screw hole was printed as 0.75mm instead of 1.4mm, which is smaller than expected. This causes the user to have to thread the plastic with the screw, which is not ideal, but still functional. 

The final step was placing the board in the case, screwing it in, and presenting to our professor.

Number of Forks: 
Team Members: 
Team member name: 
What role did this person play on the project?: 
Sort Order: 
Created the circuit board, programmed the Wi-Fi chip and MCU, designed a website to access the images from the webcam, and modeled a 3D printed case to hold and protect the webcam
Show & Tell video as default: