Friday, September 10, 2010

Trashcan Accelerometer

Digital Stew

The city that I live in provides weekly trash collection services. Customers typically have a 96 gallon trashcan which is left out by the curb early in the morning on a scheduled day. Sometime during the day a large truck arrives and the lone driver/operator activates a giant claw that reaches out, grabs the trash container, lifts it up into the air and empties the contents into the back collection area of the vehicle. Then the giant claw drops the container back down to the ground, retracts and moves on to the next house. The process is very quick and efficient. (See the video further down.)

Watching the truck manhandle my trash container week after week I began wondering what g-forces were exerted on the trashcan by that giant claw? So I decided this would be a good Arduino data collection project.

Hardware

Microcontroller

The microcontroller used in the project was the Arduino (Atmega328) which I have been using in various other projects.

Data Logging

To store the data during collection I ordered and built the AdaFruit Datalogging shield. It has the ability to write data directly to an SD card as well as providing an on board Real Time Clock. Construction was easy with the clear instructions and code samples AdaFruit provides.

Accelerometer

Having never used an accelerometer, I spent some surfing time looking at different types and finally settled on SparkFun's item number SEN-00252 which is a Freescale triple-axis MMA7260QT.

I picked this one because it was a triple-axis sensor on a single IC, because it has selectable ranges of (+/-) 1.5g, 2g, 4g, and 6g, and because it comes on a handy breakout board. For this experiment I set the accelerometer up to have a sensitivity of 2g.


Construction

I decided to create my own simple accelerometer shield to plug into the data logging shield. This would give me flexibility to reuse the accelerometer for other projects later on.

The top view in the image below shows how I attached the accelerometer to a larger circuit board using a nylon standoff. I installed a couple of jumper blocks to let me change the sensitivity of the sensor and also added a switch that the Arduino could read to determine if logging should be running or paused. The bottom view shows the simple point to point solder connections I used.























Here is the schematic of the accelerometer shield.















In total the project has three boards, (clockwise from top left)
The Arduino, the Data Logger shield and the accelerometer shield.



















When assembled the unit looks like this

















Operation


Powering the Arduino with a 9V battery, I then put the sensor package into a small padded box and secured the box to the side of the trashcan with black duct tape.

I had two concerns about this part of the project. The first was that the sensor package would detach from the trashcan and my project would end up in the back of the trash truck, lost forever. Excessive use of duct tape was my attempt to prevent that from happening. My second concern was that the driver might see the sensor box as a “suspicious package” and call authorities. Fortunately neither fear was realized.






















And this image shows the X,Y and Z orientation of the final data collected by the experiment in relation to the trashcan.






















Knowing the truck would arrive at my location a few minutes after it entered the neighborhood I waited until the truck was close, activated the Arduino and retreated in order to video tape the experiment.




The truck and claw did their thing, the data logger and accelerometer did their thing and I was greatly relieved when my project survived intact and didn’t end up in some landfill.


Understanding the Data

An example of the data collected on the SD card is shown below. The first column is the current second of the Real Time Clock. I set up the software to record the X, Y and Z values eight times a second. The next three columns are the noise compensated voltage representations of the X, Y and Z outputs. The raw data is interesting but with a little post processing it can become more meaningful.

58 362.02 473.18 284.60
58 362.36 473.22 284.64
58 361.74 473.70 285.24
58 361.60 473.04 284.68
58 362.46 472.60 285.04
58 365.20 473.58 285.54
58 399.52 459.74 265.58
58 393.02 459.56 309.38
59 368.98 431.16 308.34
59 370.90 543.88 278.78
59 340.14 432.74 293.56

Noise compensation

I found that even just sitting stationary on my workbench the signals the accelerometer output were not noise free so I used a simple moving average algorithm in the Arduino code to compensate. It was simply a matter of taking 50 reading from each sensor and then averaging that value and writing it out to the card. (That is why the recorded values are a float numbers rather than the typical integer number the Arduino 10-bit analog to digital converter outputs.) This technique doesn’t remove all noise but it does smooth it out quite a bit.

All other post processing of the data was done by spreadsheet after the experiment was over.

Calibration

Since it was virtually impossible to orient the sensors to be exactly level in all three directions when attaching to the trashcan, it is important to use a calibration process to remove any tilt the sensors picked up as they sat quietly waiting for the truck.

To do this I averaged 1000 SD card readings for each axis as the sensor remained stationary. This value, converted into g-force (see formula description) when subtracted from each sample sample values (also converted into g-force) gave me a more accurate result of the forces on the trashcan.

Formula for Converting raw data to g-forces

I used the following formula to convert the raw data on the SD card to g force.

((Vref * (ADout / 1024)) – (Vdd / 2)) / Sensitivity

Vref = 5v and is the voltage reference used internally by the Arduino when doing analog to digital conversions.

ADout is the raw data (x, y or z) value recorded on the SD card.

1024 is the number of steps the Arduino 10-bit analog to digital converter splits a full voltage range into..

Vdd = 3.3v is the voltage input to the MMA7260QT accelerometer IC and it is divided by 2 because the sensor records both positive and negative forces. 3.3v/2 = 1.65v so values above 1.65v are positive force and values below 1.65v represent negative force.

Sensitivity is a value taken from the MMA7260QT data sheet. It represents how many mV/g the sensor will output based on the jumper settings inputs of the chip. I set my sensor to use a sensitivity of 2g so this value is 600 mV or 0.6v.

Formula Example

Say for example, from the SD card you find that the value on the X axis at some particular point in time is 602.64 Using the formula:

((5 * (602.62 / 1024)) – (3.3/2)) / 0.6 you get 2.15g the X axis.

The calibration value for the X axis (average of 1000 reading when the sensor was not moving) was 469.62 so using the same formula:

((5 * (469.62 / 1024)) - (3.3/2)) / 0.6 = 1.07 = X axis calibration value.

Subtracting the calibration value from the particular X reading gives the following 2.15g – 1.07g = 1.08g

This means that at that particular point in time, the trashcan was moved in a positive X direction with the force of 1.08g.

It is easy to setup a spreadsheet to list all the raw data, the calibration data for each axis and then have the spreadsheet run the conversion to g-force formula on each data value of raw input.

Finally, again using the spreadsheet, I graphed the g-forces on the trashcan in each of the X Y and Z directions as it was being emptied by the truck.




















Accelerometers are showing up in many devices this days; the Wii, iPhones, iPads, Droids, laptops etc. I hope this project encourages you to get your own accelerometer and perform other experiments.

Arduino Code



   


 /* --------------------------------------  


  MMA7260Q 3-axis accelerometer  


   


  Accelerometer and data collection.  


   


  code released as Open Source  


  feel free to use as you see fit.  


   


 */ --------------------------------------  


   


 // libraries from   


 // http://www.ladyada.net/make/logshield/download.html  


   


 #include <SdFat.h>  


 #include <Wire.h>  


 #include "RTClib.h"  


   


 #define ECHO_TO_SERIAL 0  // 1=echo is on, 0=echo is off  


   


 #define redLEDpin 9  


 #define greenLEDpin 8  


   


 #define x_axis 0  


 #define y_axis 1  


 #define z_axis 2  


 #define startStopSwitch 7  


   


   


 RTC_DS1307 RTC;   


 Sd2Card card;  


 SdVolume volume;  


 SdFile root;  


 SdFile file;  


   


 int sampleSize = 50; // used in moving average   


   


 //---------------------------------------------------------------  


 void error(char *str)  


 {  


  Serial.print("error: ");  


  Serial.println(str);  


  digitalWrite(greenLEDpin, LOW);   


  while(1)  


  {  


    digitalWrite(redLEDpin, HIGH);   


    delay(250);  


    digitalWrite(redLEDpin, LOW);   


    delay(250);     


  };  


 }  


   


 //---------------------------------------------------------------  


 void setup(void)  


 {  


  pinMode(redLEDpin, OUTPUT);  


  pinMode(greenLEDpin, OUTPUT);  


  pinMode(startStopSwitch, INPUT);  


    


  digitalWrite(redLEDpin, HIGH);  


  digitalWrite(greenLEDpin, HIGH);  


    


  Serial.begin(9600);  


   


  // initialize the SD card  


  if (!card.init()) error("card.init");  


    


  // initialize a FAT volume  


  if (!volume.init(card)) error("volume.init");  


    


  // open root directory  


  if (!root.openRoot(volume)) error("openRoot");  


    


  // create a new file  


  // starts with LOGGER00, and next one would be LOGGER01 if  


  // LOGGER00 already exists. THis preserves existing files and  


  // increments the new filename  


  char name[] = "XYZLOG00.CSV";  


  for (uint8_t i = 0; i < 100; i++)   


  {  


   name[6] = i/10 + '0';  


   name[7] = i%10 + '0';  


   //O_CREAT = create file, O_EXCL = only if file doesn't already exist  


   //O_WRITE = open for writing  


   if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;  


  }  


    


  if (!file.isOpen()) error ("file.create");  


  //Serial.print("Logging to: ");  


  //Serial.println(name);  


   


  // write header  


  file.writeError = 0;  


   


  Wire.begin();   


  if (!RTC.begin())   


  {  


   file.println("RTC failed");  


   #if ECHO_TO_SERIAL  


    Serial.println("RTC failed");  


   #endif //ECHO_TO_SERIAL  


  }  


    


   


  file.println("sec,x-axis,y-axis,z-axis");    


  #if ECHO_TO_SERIAL  


   Serial.println("sec,x-axis,y-axis,z-axis");  


  #endif //ECHO_TO_SERIAL  


   


  // attempt to write out the header to the file  


  if (file.writeError || !file.sync()) {  


   error("write header");  


  }  


    


  digitalWrite(redLEDpin, LOW);  


  digitalWrite(greenLEDpin, LOW);  


  delay(1000);  


   


 }  


   


 //----------------------------------------------------------------------  


 void loop(void)  


 {  


    


  if (digitalRead(startStopSwitch) == LOW)  


  {  


   // user feedback for errors and status  


   digitalWrite(redLEDpin, HIGH);  


   digitalWrite(greenLEDpin, LOW);  


  }  


  else  


  {  


   digitalWrite(redLEDpin, LOW);  


   digitalWrite(greenLEDpin, HIGH);  


   DateTime now;  


    


   // clear print error  


   file.writeError = 0;  


    


   // delay for the amount of time we want between readings  


   delay(100);  


    


   digitalWrite(greenLEDpin, LOW);  


   now = RTC.now();   


   float x = 0;   


   float y = 0;   


   float z = 0;  


     


   // moving average for noise compensation  


   for( int i = 1; i<=sampleSize; i++)  


   {  


    x+= analogRead(0);  


    y+= analogRead(1);   


    z+= analogRead(2);  


   }  


   x = x / sampleSize;  


   y = y / sampleSize;   


   z = z / sampleSize;  


   


   // output format for CSV data on SD card    


   file.print(now.second(), DEC);  


   file.print(", ");  


   file.print(x);  


   file.print(", ");  


   file.print(y);  


   file.print(", ");  


   file.println(z);   


   #if ECHO_TO_SERIAL   


    Serial.print(now.second(), DEC);  


    Serial.print(", ");  


    Serial.print(x);  


    Serial.print(", ");  


    Serial.print(y);  


    Serial.print(", ");  


    Serial.println(z);    


   #endif //ECHO_TO_SERIAL   


    


   if (file.writeError) error("write data");   


   if (!file.sync()) error("sync");  


  }  


   


 }  


   


   




Saturday, September 4, 2010

The emergence of "instant prototyping" vs. "rapid prototyping"

Wednesday, September 1, 2010

A couple days ago, I talked about why I liked using and programming modular Linux gadgets. Mike wrote me a long email in response to my comment about "rapid prototyping" vs. "instant prototyping" which I thought I'd share.

With the growing popularity of MakerBot, the reduced transaction costs of interfacing with sensors and digital circuits that the Arduino allows, and the emergence of modular prototyping platforms like Liquidware's Beagleboard-based gadget packs and Bug Labs, it feels like there's been a fairly dramatic increase in single-programmer productivity.


I re-read one of my favorite books of all time, "
The Mythical Man Month" by Frederick Brooks. Normally I don't get too excited about dense, heavy, cerebral books that don't have any practical advice unless they teach a new programming language (or algorithm). But in this case, I make an exception, because it's just a decent book that questions the process of engineering.

Well, lo and behold, I decided to amazon around for comparable books, and I discovered that the author has written a new book, which sounded even more cerebral and pie-in-the-sky, "The Design of Design". As an aside, I wonder how much more "meta" you can possibly go. How about: "The Process of Thinking about Writing about the Design of Design" ? I mean, even the Greek philosophers had a limit. (Actually, then you'd need to write a book about a "Formalized Grammar and Metaphysics to Document the Process of Thinking about Writing about the Design of Design.")

At some point, for the sake of humanity, I just hope someone remembers how to actually do something tangible! But I digress. Turns out, I enjoyed the book.

It got me thinking. The Matrix movie got me thinking, as did the movie Inception (actually the 13th Floor did too but fewer people saw that one). So the fact that a book held such high company in my mind as the Matrix, Inception, and 13th Floor is high praise coming from me. Much of the book was focused on the process of designing design processes.

How many designers are too many, how should they work together, how do you organize to solve problems? I had a thought while reading the book: design exists because planning for engineering is an important and valuable step in communication and preparing to optimize problems. This is largely because engineering takes time.


Engineering, or building, or solving problems takes
time.

But what happens if you break into a new plateau of productivity? What if that time is reduced significantly?


I've hit a personal plateau and breakthrough in productivity twice. Once in software, once in hardware. The software one happened a few years ago, and the hardware one happened about 2 weeks ago.


Software Productivity


My personal software productivity came when I moved from C programming to purely Perl. I realized that I could write an algorithm faster in Perl, and make a functional program faster, than I could in C. Because of that, I could iterate on the program faster, add new features, in less time. The next bump came when I moved from Perl to R. I could do almost everything I could in C in R, except that R also let me access tons of higher level math building blocks. I became really fast at writing code in R... although it took the code longer to execute, I focused on optimizing the algorithm or the way I wrote a function, as opposed to spending lots of time debugging Perl data structures, or C memory leaks.


The common thread was that R allowed a higher level of functional modularity, but still exposed the lower level functions and data types for me to use when I needed them.


Hardware Productivity


Recently, I've felt similarly faster at building hardware than I used to be. I used to have to write PIC chips into protoboards manually with wires that I stripped and cut myself. Then I got excited about Basic STAMP boards because they let me focus more on the code, and on a few simple digital IO pins. Then the Arduino completely changed the way I thought about accessing sensors, switches, and digital interfaces in general - it significantly lowered the "hardware access barrier" if such a thing exists. In practical words, it let me sit down, and hack the
E-Ink screen on the Esquire magazine cover in a matter of hours, rather than days. Now, I'm hacking away on Arduino gadget shields and BeagleBoard Gadget Packs... and the time it takes to go from "I have an idea for a gadget hardware that does XYZ" to actually having one in front of me is measured in minutes.

I think I've found the critical pattern... just like in software, the biggest productivity improvement came as the hardware allows a higher level of functional modularity. I'm interfacing with sensors now, as opposed to I2C buses, so I'm able to build a hardware device even faster using a new sensor, for instance. But the important part is that as the hardware gets higher and higher level, it still gives me access to the basic bit-banging serial and data IO ports and buses, just in case.



Open vs. Closed Design Philosophy


That's the biggest difference in my design philosophy and that of Apple. While Apple *hides* digital IO and obscures interfaces, everything I've ever built *opens* the digital raw interface, and keeps that exposed and really easy to access from Perl, R, and C, even as the modules higher level.


The result is much faster hardware and software development.


As this continues, the time it takes to prototype decreases.


At some point, the time it takes me to prototype a device might reach the time it actually takes for me to just build it anyway.


And maybe that's some new concept or field of "extreme" or "agile"
instant hardware prototyping.

...and naturally, this is accelerated by the existence of Open Source Hardware...


Why? Because Open Source Hardware is about lowering design barriers, exposing underlying schematics functional blocks, and the result is that prototyping with Open Source Hardware - in my experience - is orders of magnitude faster than traditional dev kits, and proprietary hardware.


...


Wow. Where did that come from? I suppose this is an example of the kind of high level, head-in-the-clouds type thoughts you walk away with after reading "
The Design of Design". I feel like the reading rainbow guy: I recommend that book for any design engineer. I think the kind of design discipline I learned will make me a better hardware hacker - or at least a more efficient one (I wonder if anyone's ever done a study on hacker efficiency?) And the honest-to-goodness truth is that I'm not paid to endorse it. I'm not getting any kick backs (ha), nothing. I simply enjoyed the book, and it made me realize something about my own design process I hadn't thought about before...


Ok, back to hacking hardware, I promise...

Monday, August 30, 2010

Why I like building with modular Linux Gadgets

With all the talk about iPhone vs. Android wars, it's easy to forget that Linux was once discussed as a popular platform for rapid prototyping gadget development. The more projects I do with the BeagleBoard, the more emails I seem to get from fellow engineers and programmers - many who work at embedded systems companies around the Boston, New York, (and California).

Oddly enough, a lot of programmers still favor Linux development over iPhone apps because of how many programming languages you have available, and the fact that you don't have to load up massive amounts of dev API's to start hacking, you can just pick it up with gcc or Perl and run. And Linux gadgets in general are a little different from Android too, because while Android focuses more on the GUI and user interface and experience, Linux is much lower level, and therefore tends to be more useful for industrial design, control, and engineering applications like sensor and motor control and industrial automation.



I suppose you could say Android is "consumer" focused, and Linux is "industrial" focused.



Anyway, I've been programming a number of apps for folks who have asked for help recently, and I've been learning a lot about the design process of building modular gadgets with the BeagleBoard from TI, and the BeagleTouch and BeagleJuice from Liquidware.






The first thing I've realized is that having raw exposed digital IO pins is a life-saver. I use these to hack in switches and LED's without having to completely reverse engineer schematics and pin diagrams. Literally I can just solder into the general purpose IO and I'm off and running. Alternatively, I use the Arduino to wire in a sensor like the Compass Sensor or Temp Sensor or Gyroscopic Sensor, and then plug it into the USB port (I'll blog about this soon).




Practically speaking, being able to disassemble the device and reassemble it on the fly in a modular way, is a pretty useful skill in making gadget or hardware demos. This is because I can change the form factor around on the fly. I was in a meeting earlier today (which inspired me to write this article), when the project manager guy asked how hard it would be to turn the Gadget Pack handheld into a terminal with a keyboard... so I unscrewed the demo and within 60 seconds, had something that looked like this:




Then, one of the engineers said, "yeah, that's cool, but we really ought to have an on-screen keyboard." So I clicked around twice, and using the fact that it's a touchscreen, I loaded up the Linux onscreen keyboard app that Will converted for the Beagle Gadget Pack, and then turned it into this:



That's pretty powerful, because it's *real time prototyping* not just rapid prototyping. As in, it happened instantly, almost as fast as it took for someone to finish the sentence, it was done. I've observed that "business guys" and "customers" that embedded design companies build devices for often like to change their mind in the middle of the project as they learn more about what they're trying to build, or the aesthetics, or design or interface needs. It's quite expensive to a project to have to re-engineer the whole thing from scratch every time the form factor needs to be changed. Making something 100% modular makes changes like this really fast. Plus, I've pretty much found a way to cut out the part of the prototyping process that involves making a "non-functional prototype" and just jumped right into making a functional prototype...




So I've been living with the Open SciCal and the Gadget Pack for 2.5 weeks now, and so far I've showed it to half a dozen folks, and gotten 3 assignments to build custom gadgets using the platform. I'm not going to become a millionaire by any means, but I'm at least getting paid to do what I love doing... which is hacking open source hardware into gadgets, and if you had asked me 3 years ago when I started this blog if that would ever be a possibility, I would have said fat chance...




So anyway, thanks to Will and Chris, Mike and Justin, and Matt, John for all the support and help along the way... and here's to some happy hacking over the next few days and very very late nights as I work on my top secret project...



"Project C".



Dun dun dun....



:-)




Sunday, August 29, 2010

Thanks Hackaday :-)

I must have totally missed this, but I looked back at my RSS reader, and noticed that the Open SciCal project got onto hackaday. Thanks a lot! It's definitely no secret that I have a nerd crush on hackaday, since I've read that blog since middle school, and aspire to recreate everything they mention and talk about.



Here's a link to the post, and thanks again, hackaday...