Category Archives: Lessons learned.

If it’s true that people learn from their mistakes, then I guess I qualify as ‘a life long learner’.

Drip Sensor Update: The Gamma Build

I suggested in the last post that a new build usually comes together on the third iteration, so I though I would post a few photos of the current drip sensor, to show how much they changed in that short series:

Alpha, Beta & Gamma builds

Alpha, Beta & Gamma builds of the Cave Pearl Drip Sensor

That Alpha would only detect drops in the very center of the housing, and often registered double hits because of the splash back from the complex surface topography, which also caused a buildup of water on the surface, further interfering with the signal. So I removed the pressure and temperature sensor wells from the Beta, and used a heat gun to bow the surface and shed water.  I hand sanded the pvc to make the strike surface thinner and more responsive, which increased the “reliable” sweet spot to the diameter of the circle you see on drawn there. This worked well, but as you might imagine removing that hour long fabrication step rose to the top of the priority list (if necessity is the mother of invention, laziness is surely the father…) I also did not want to penetrate the housing for those standoffs if I could avoid it because this device has to maintain integrity with constant water impact at exactly that spot.

JB Plasicweld bonds the accelerometer to the cap

Plastic-weld bonds the sensor, preserving the integrity of the housing

My solution to both problems was to solvent weld a four inch knock out cap to the top of the hard pvc shell.  The green color you see there is ABS to PVC transition cement, that I learned about back at the beginning of the project when I was mangling Leggo bricks for internal scaffolding. The ABS is translucent, so the LED no longer needs a portal of clear epoxy because the light passes right through.  The knockout is thin and stiff, which eliminates all that sanding and improves the response of the accelerometers so much that now the device even responds to loud noises, and almost the entire surface sensitive to the smallest drip.  As a result I now have to tweak the settings to reduce the sensitivity so we don’t get too many false positives.  But on the third build of a new sensor, that’s the kind of problem you want to have.  I though the flat surface might resurrect the water pooling problem we had on the Alpha, but in the end it just ended up being a lesson in how I still miss things that are really darned obvious, because simply setting the drip sensor up with a slight tilt will shed the water without affecting the operation at all.  (I am just glad I realized this before some three year old came along and pointed it out to me…)

These guys are only $1.5 each, and are much easier to work with than the plastic micro SD adapters

Much easier to solder those jumpers now.

Wirefold

The trickiest part of the build is routing the wires to reduce strain. Thin silicone 26awg wire helps quite a bit there.

There have been a few improvements to the logging platform as well.  I found these really inexpensive  raspberry pi SD card adapters that are mounted on their own pcb, which neatly solves the melting problem that the cheap plastic  adapters give you if you linger too long with your soldering iron.

Drip Sensor Gamma BuildSo this is the new baby, and I am now running burn tests on loggers using a few different clone boards, including a Rocket Scream Mini Ultra, as they have some very interesting power saving features that might significantly increase the operating time, while keeping the overall simplicity of the three component design.  I expect a few more issues will arise in testing, so I will hold off posting the code to Github, till I am sure that they are behaving properly.  I am still a bit stunned that these drip sensors came together so quickly, but perhaps the last six months of work on the flow meters had something to do with that. 🙂

<— Click here to continue reading the story—>  .

Addendum

Adafruit just posted a video from the National Science Foundation showing how water droplets move on various hydrophobic surfaces.  Way cool…

Addendum 2014-12-11:

We deployed our first batch of these drip sensors in August, and when we went back to get them in December, we were delighted to find that the first real world run was a resounding success.

Building your sensors & underwater housings from scratch

I reviewed my build journal recently, and found enough themes in there for another bit of bloggy catharsis.  No one should mistake this as the advice of an expert in anything, as I have a long way to go before I start collecting karma points at the playground. But at least I can claim that these ideas are well tested, because as the saying goes, I never make the same mistake twice – I make it 5 or 6 times… just to be sure.

Prototyping:

Only RTC & interrupt lines get soldered to the mcu.

Only RTC, SD, & interrupt lines soldered to the mcu.

Join the forums: Everyone says read the datasheets first….well from this beginners perspective that’s B.S.  Even when I started to understand all the terms I was reading, it was still a major leap of understanding to realize what the information in the data sheet implied… (and I still go through it with each new sensor)  If you want to get rolling on something start with the discussion forums, because it’s likely that someone there has already walked down your path, or one very close to it. Thirty minutes Goggling Sparkfun, Stack Exchange, or searching through places like the Arduino Playground, will get you farther than several hours reading the datasheet. Of course you will eventually end up doing that too...just don’t start there.  Often the forums lead you to some well commented GitHub code examples.  It is so much easier to understand the data sheet, when you have a piece of relevant code in front of you at the same time. Datasheets are written solely for corporate electronics engineers, because unless you represent the 10 to 100 thousand unit MOQ,  you simply don’t show up on company radar.

( Sometimes it even seems that a company deliberately tries to hide the functions built into their own ICs from the maker community.  For example: the mysterious Digital Motion Processor (DMP) functions of the invensense 9150. I have yet to find a single example of an Arduino script accessing these features though the 9150 is commonly used in quad copters. I’d have thought that having Euler angle & 9DOF quaternion calculations done for free, would have drawn some serious attention from those those guys.)

You need one completely “trusted” set of kit:  Which you will pay dearly for, but you need it to test out each new component you are thinking of adding to your project. (I still haul out my original Uno for this from time to time, because the darned thing is virtually indestructible…)

More than a few of the cheap eBay boards are D.O.A.

About 1 in 10 of the cheap eBay boards are D.O.A. This  ADXL345 board had a pretty typical alignment skew: X & Y axes were ok, Z did not read.

Connect new parts one at a time:  Do not add to your grief by connecting two new untested pieces of equipment to each other at the same time. (like, for example, a new FTDI board, and an Arduino clone of off eBay….grrrrr….) I am slowly learning what it is that you are paying for when a given sensor module sells for $20 from a trusted source like Sparkfun and $2 from China.  It’s probably not the components (although I hear there are fake IC’s out there) but something else that’s just as important.  If you watch the Tiny Circuits promo vid, around the 5 minute mark you see a person manually re-positioning the components that the pick and place machine laid down, and then around 7:15 you see someone testing each board before shipping. At this point I have seen enough of the eBay stuff that I am pretty sure that these two steps are never done on the clone boards. So If you go down that route, you are implicitly agreeing to do those jobs yourself (in addition to cleaning off all the excess flux left on the boards…)  This is not a problem when I am just hacking something together, and then testing it on the bench (or in the bathtub…) but not a risk I will take lightly for the fieldwork units.

And while we are on the topic of those cheap modules, they almost always arrive with connections broken out for both SPI and I2C, but you will likely use them as one or the other, meaning that you often need non adjacent pins soldered onto the breakout. I used to fiddle with crappy metal “helping hands” things (now replaced by a far more effective Panavise Jr)  to get those single pins soldered into place, but now I simply use a bread board to hold the pins in the correct locations before soldering:

Many thanks to my bother Mike for showing me this soldering technique!

Many thanks to my bother for showing me this soldering technique!

Modularize your designs:   Breadboards were never very practical for me because most of my projects get bashed around, and are supposed to run while the whole thing is in motion. But even after the prototype stage my sensors are not usually soldered directly to the data loggers. Yes, it’s a pain constantly making custom all those custom interconnect cables, especially since I color code everything – I2C bus, interrupt lines, …everything. And once you get an early prototype working, immediately build another one, and do all of your tests, etc., on the second unit, with the first working unit just sitting on the shelf.  Then if something stops working, you can use process of elimination with the known good modules to isolate the cause of the problem quickly. Often this technique helps me identify that the problem is actually in the software, and not with the hardware at all.  But I am still wading my way through the wonderful world of crimp connectors for ones that will prove robust enough for fieldwork. (note: I’ve adopted Deans Micro Plugs for my current builds…)

Coding:

Hit the verify button often, even when you make “simple” changes:  Don’t wait till you have been working for half an hour because humans can only remember 7±3 things (for this human, even less than that…)  You will be backtracking allot and error messages in the AVRc programming environment are usually about as helpful as a baby crying. You know something is wrong, but often you cant figure out what the problem is from the feedback it give you.  Something as simple as: “Hey man,  you left out a semicolon at the end of line 17” can be reported with anything from a one line “Expected X before Y” error to twenty (or more…) lines of cryptic compiler faults. Sometimes Google is your only friend when this happens.

The utility of a piece of code is directly proportional to how dangerous it is to use: For example: Global #define statements are tricky…especially when you are using libraries, because you never know when you have tried to “re-define” something hidden in one of those libraries. Interrupt handling is another example of something tremendously useful, and really easy to screw up when you have more than one sensor generating interrupts in the same piece of code, at the same time.

Software faults almost always show a repeating pattern of behavior: At least that’s been my experience so far. Bad wiring, or some other issue with the physical build, (like a v. regulator thermaling out…) hangs the system in a way that is much more unpredictable.  Of course, finding those patterns is a heck of a lot easier when your project is a data logger in the first place…

Physically putting “stuff” together:

Third time’s a charm:  If your alpha works at all; that’s a great success. The holes will be in the wrong place, you will use too much epoxy, and it will be a clunky octopus of dodgy wiring. But even if it only runs for a single day, it has done the job of showing if the idea will work. (and they make such stylish book-ends…right?) The second build lets you sort out the right physical locations for all the components, and eliminates that hour of laborious hand-sanding that you really did not need to do.  This is also the model that lets you work out most of the software bugs, because it is usually much easier to open & close without breaking fragile jumpers all the time.  But for me at least,  it’s the third build that usually comes together in a way that feels right.

This type of bench vise is worth finding. I picked this used one up for $10, and it has been fantastic for holding parts together while epoxies cure & solvents weld PVC parts.

This type of bench vise is handy. I picked this one up for $10, at a garage sale and it has been fantastic for holding parts together while epoxies cure & solvents weld.

Adhesives & epoxies can be one of the most expensive components in your physical build:  (I wasn’t expecting this one) I go through a fair bit of Loctite E30-CL  (or E00CL for better PVC bonding) for my hull pen-etrations, and I love the fine control of the applicator gun.  But the mixing nozzles alone are more than a buck each, and they are elegantly design to waste a large volume of that precious epoxy with every use, which then solidifies inside the nozzles turning them into expensive single use devices.  That irritated me enough to start experimenting, and it turns out that Goof-off  (mainly xylene, and 2-ethanol) cleans out those applicator nozzles relatively easily. (Acetone would also work) I usually buy my adhesives from Zoro Tools. (note: their product search function is terrible, I use Google Shopping to hunt for stuff on Zoro’s site)  There are plenty of cheap Loctite sellers on eBay, but many are hawking expired lots.  In a pinch, I fall back to good old JB weld, and I use PlasticWeld putty absolutely everywhere because it nicely adheres sensor boards to both PVC & ABS in a way that is strong, but still removable (sort of..) if you have to repair something. Be careful not to bridge contacts with your adhesives on really sensitive sensors.  Most of these epoxies do not conduct electricity, so I use JB weld to shore up weak jumpers on I2C lines all the time. I have had problems with some sensors not working after gluing, probably because the cured epoxy added capacitive effects to the circuits. I have also started experimenting with 3M’s VHB double sided tape (for low surface energy plastic & acrylic substrates) to see if that is easier to work with. (Note: after testing the VHB did not work as well on the pvc as the standard 5lb mounting tape)

(…and if paying an “arm and a leg” for your adhesives wasn’t bad enough, those cheerful, brightly colored labels hide some fairly dire warnings about skin contact literally causing cancer, or vapors so dangerous that use of the product anywhere other than a open field is guaranteed to give you brain damage & significantly harm your … uhhh … “reproductive capacity”. Don’t believe me? Get a 200x microscope and read that fine print for yourself… just make sure you do it some place far away from stoves, heaters, electric motors and all other sources of ignition…like soldering irons 🙂 )

The shop course that you only took in high school to boost your marks will finally start to come in handy:  Turns out that working with PVC is almost the same as working with wood, so I was surprised by how much time I spent scoping woodworking forums while figuring out how to cut weird angles and then re-assemble things.

BigIron

An angle grinder pulls the rust off of old school tools in short order.

You can build anything with three pieces of  “iron”: A good soldering iron, a drill press, and a 13″ bench top scroll saw (which cuts PVC and trims circuit boards beautifully).  I have not regretted for one second putting down $100 for my little Haiko from Adafruit. (Wish I had bought the thing at the very start of this adventure.) But my other two irons are vintage Sears Craftsman models which cost next to nothing because when I bought them, they looked like flea-market clunkers from the days before plastic was invented. Cleaning them up was worth the effort because they weigh a ton, and are rock solid stable. In fact, these days I actually go out of my way to get old tools for my workshop. So if you see me one morning, at yet another garage sale, don’t be surprised if my hands are full of weird drill bits,  strange clamps, and other rusty lumps of metal that are even older than I am.

And last but not least:

I know everyone has their own taste, but I find that Pandora’s “Chillout” channel (in the Dance/Electronic genre section) just has a really good vibe for working on the bench. Spacey electronica wallpaper-music smoothly delivers the hyper focus I need to sustain a long soldering session, especially when the clock ticks on into the wee hours… .

Addendum 2014-07-29 

I have another one to add to this list but it stands outside of any category because it seems to apply equally. I call it the ‘Principal of Equivalent Annoyance’, and it’s just the observation that the dumb little things on a project take up at least as much time as the big important things. For example: when you connect allot of parts together, the physical behavior of your wires matters more than you’d expect because the difference between good insulation and stiff hard plastic puts quite a bit of pressure on the wires when you fit everything into the housing. Once and a while I am left with some excess lead wire from a sensor and when I open up the left over multicore cable I sometimes find a meter or so of the perfect wire.  Soft silicone insulation, 12 or more strands, no tinning… the stuff is fantastic to work with and is so flexible that it doesn’t stress the connections. Of course it never has any identification marks on it that might lead me to the source.  So I am slowly working my way through every brand of hook-up wire on the market, searching for this holy grail, and wasting more time on it than I even want to think about.  I suspect this is kind of thing happens on every project.

Addendum 2014-09-13

There are a few contenders so far in my ongoing search for “the perfect wire”: 

Adafruit sells 26AWG in multiple colors. This is my current favorite wire because they sell it in easy to handle packages (~0.95/2m) and they have the only grey & orange colored stuff I have found so far. It probably sounds silly to mention the packaging, but from other vendors like Hobby king, or eBay, you can expect to spend at least an hour untangling the spaghetti when your wire arrives. Their 30AWG is 0.70/2m, and is very handy for running jumpers across the surface of a breakout board.

Sparkfun sells their red & black silicone hook up wire at a good price, I just wish they had more colors.

Cal Test Electronics CT2956 Test Lead Wire:  (24awg $9 for 10 m, green, white) It is soft multi-strand bare copper and there is some variability in the stiffness as they seem to use different stranding depending on the color you order, but all of it is much more flexible than pvc insulated wire.  The insulation is nice and thin, so it crimps well into the standard 0.1″ connectors, and it is a bit stiffer than the Turnigy, so it will hold a bend you put in the wire.

Turnigy Soft Silicone Wire: (24awg $.60-$1 per meter, red, black, yellow blue) which is popular in the RC plane/Quadcoper crowd. Multi-strand “tinned” copper, with lots of colors. The very soft insulation is about twice the thickness of the Cal Test, but it still crimps nicely. (note: Hobby King does not let you mix warehouses on orders…)

There are two drawbacks to to using really soft silicone wire: You can not push the female crimp connector ends into the housings as you normally would with jumper wire. You have to dig in and pull the connector through the enclosure with tweezers.  The other issue is that because the silicone conducts heat so much faster than pvc, you will burn your fingers more often while soldering if you are not careful. In return,  you can stuff as much spaghetti as you want into a very tight housing without putting pressure your the solder joints in the process.  The wire stripper from Pololu, works well on both types of wire.

Addendum 2016-03-11

More eBay vendors for silicone jacket wire are appearing over time, and they are a great place to find a wider selection of colors like brown, purple, & pink. With module & jumper builds like mine, you need as many different colors as you can get your hands on. 

Addendum 2015-01-09 

I received a 10″ craftsman 21400 band saw for Christmas this year. And just like the night & day transition that occurred when I went from a crummy soldering iron to the lovely Hakko, my cuts have now become more accurate and virtually effortless.  No more risking my fingers trying to cut pipe on the table saw! And free-handing with a band saw accomplishes 90% of what I could do with the the jig saw as well.  If you can only afford to own one cutting machine, then I am now convinced it should be a bench-top band saw. Wish I had it from the beginning…

Addendum 2015-01-16

Looks like I am not the only one who is irritated by the waste generated by the Loctite 50ml nozzles. The folks over at RCuniverse confirm that acetone makes a good solvent for cleaning out the mixing tubes, and that its easier to do if you remove the white plastic mixing baffles first. They also mention that putting the nozzles in bags in the freezer will prevent the epoxy from setting, so I might try this trick to see if I can get the tubes to “self clean” by gravity. Looks like All-Spec is the cheapest source for the nozzles, but I keep finding “generic” mixing nozzles on eBay that claim they work with both 3M and Loctite adhesives. Haven’t tried them yet though.

Addendum 2015-02-02

I bought some of the cheep MA5.4-17S 17 element mixing nozzles, and although the fit perfectly onto the 50ml dispenser, they were much shorter than the 15cm, 20 element, Loctite 98623 nozzles I usually use:

TopCheap_BottomLoctite

I thought this was a good thing, as I hate wasting all the epoxy that is left in the dispenser after every use and these smaller ones only retained 1.68ml in the barrel. I did some test pours under nearly identical conditions, and the smaller nozzles left a significant “swirly” pattern when the cured epoxy was examined close up a few days later:

Left side: Loctite Nozzle Right Side: Short Generic Nozzle

Left side: Loctite Nozzle                                                   Right Side: Short MA5.4-17s nozzle

I am interpreting this as a density gradient formed by inadequate mixing in the shorter nozzles. The epoxy has still set hard as a rock so I am not sure if this compromises the integrity too much. There are also listings for MA6.3-20S and MA6.3-21S nozzles, and I will try some of those next time.

(Note: the MA6.3’s worked great, as did the $10 applicator guns on eBay)

Buffering Logger Sensor Data to a 4K AT24C32 I²C EEprom

These MS5803 pressure sensors are my very first SMD reflow pieces. Hopefully I did not toast them on the kitchen skillet I was using...

These MS5803 pressure sensors are my first  attempt at diy SMD. Hopefully I did not toast them on the electric skillet I was using to reflow…

While I was waiting on the results of the week-long power consumption test of the SRAM buffering script, I continued thinking about other ways I might extend the operating lifespan of the Pearls. I had originally considered using the processors 1024 bytes of internal eeprom for temporary storage, but work over at the solar duino project showed me that using an external 24AA256 is faster and consumes less power than the internal eeprom.  AND the cheap DS3231 RTC boards I had just received from eBay had an AT24C32 eeprom chip: 4k of storage just sitting there waiting to be used…And the data sheets told me that the SD card could be drawing up to 80 ma for who knew how long, while the datasheet for the eeprom listed a paltry 2 ma per block write taking only 5 milliseconds…

Three days of heavy lifting later…I had cobbled together this script, using PSTRING to to dramatically simplify the concatenation of the sensor data into a 28 byte long char buffer (the wire library buffer is only 32 characters long and you need two bytes for the mem address + room for string termination characters, etc).  Pstring uses simple print statements, but more importantly, it never causes buffer overflows if you try to stuff in too much data, like a mishandled sprintf statement could. This also gives me some flexibility while I am still changing my sensors around, as I don’t quite know what the final data is going to look like yet.

So this code buffers each sensor read cycle to the I²C eeprom, using two page writes per cycle.  This simplifies the code a bit, as I have only one set of variables on the go. Then when the countlog = SamplesPerCycle, it does a reverse for loop to pull the data back out of the eeprom, and write it to the SD card. With a rated endurance of 1 million write cycles, I’m not worried about wearing the eeprom out either.

And the result? This script gives me ~700 sensor read cycles per 8mV drop on a 2 AA battery power supply. This is less than half the performance of the SRAM buffering code, which surprised me quite a bit, but I guess that *192 eeprom page writes (with the attendant I2C coms) +1 SD card write per day,  uses 2-3 times as much power as SRAM buffering with 8 SD card write cycles for that same days worth of records. On paper all that eeprom writing represents almost one second per day at 2 mA, which doesn’t seem like much. So either my tiny 128 mb SD cards are very quickly to going back into sleep mode, or keeping the CPU running during all that I2C traffic is using a significant amount of power…?

So what did I learn:  Well knowing that a fair bit of I²C & eeprom traffic will more than double the power drain is quite handy, as I now jump into connecting temperature, pressure, compass, and perhaps other sensors, to those same I2C lines. It will be interesting to see what the real world performance of these loggers is when the rubber meets the…ummm…cave diver.

Addendum 2015-04-18

I simply let the wires I am already using to tap the cascade port I2C lines poke up enough to give me solder points for the EEprom. Don't forget to remove the pullups on the EEprom board.

I simply let the wires I am already using to tap the cascade port I²C lines poke up enough to give me solder points for the EEprom. Don’t forget to remove the pullups on the EEprom board as you already have pullups on the RTC breakout.

The AT24c32 chip can only hold 4k of data –  if you write beyond 4096 bytes, it rewrites over the old data!  So once you have done 128 page writes, you need to flush to the sd card. In this code, I write two 32-byte pages per record. So I have a upper limit of 64 records before I hit that block limit and start to overwrite the data!  I could bump it up to 32k of external eeprom for only $1.50, so I will have to try a few experiments to see if that helps. That 32k eeprom is a code compatible, drop in replacement. All you have to do is change the I2C address for the eeprom for the new board.

Addendum 2014-07-16

The Code below has been posted to the projects GitHub. Look around as the more recent codebuilds are much more elegant than this crude early version, and include sensor support for an easy to build logger.

//Date, Time and Alarm functions using a DS3231 RTC connected via I2C and Wire lib by https://github.com/MrAlvin/RTClib 

// based largely on Jean-Claude Wippler from JeeLab’s excellent RTC library https://github.com/jcw
// clear alarm interupt from http://forum.arduino.cc/index.php?topic=109062.0
// get temp from http://forum.arduino.cc/index.php/topic,22301.0.html
// BMA250_I2C_Sketch.pde -BMA250 Accelerometer using I2C from http://www.dsscircuits.com/accelerometer-bma250.html
// internal Vcc reading trick //forum.arduino.cc/index.php/topic,15629.0.html
// and http://forum.arduino.cc/index.php?topic=88935.0
// free ram code trick: http://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory
// power saving during sleep from http://www.gammon.com.au/forum/?id=11497
// I2C routine based on http://playground.arduino.cc/Code/I2CEEPROM#.UwrbpPldUyI
// New file name routine from http://forums.adafruit.com/viewtopic.php?f=31&t=17964

#include <Wire.h> // 128 byte Serial buffer
#include <SPI.h> // not used here, but needed to prevent a RTClib compile error
#include <avr/sleep.h>
#include <RTClib.h>
#include <PString.h>
#include <SdFat.h>
SdFat sd; // Create the objects to talk to the SD card
SdFile file;
const byte chipSelect = 10; //sd card chip select

#define SampleInterval 1 // power-down time in minutes before interupt triggers the next sample
#define SamplesPerCycle 5 // # of sample cycles to buffer in eeprom before writing to the sd card: MAX of 64! (do not exceed 128 page writes or data will be lost)
unsigned int countLogs = 0; // how many records written to each file
unsigned int fileInterval = 10; // #of log records before new logfile is made
/* count each time a log is written into each file. Must be less than 65,535
counts per file. If the sampleinterval is 15min, and fileInterval is 2880
seconds, then 96samples/day * 30days/month = 30 day intervals */

#define ECHO_TO_SERIAL // echo data that we are logging to the serial monitor
// if you don’t want to echo the data to serial, comment out the above define
#ifdef ECHO_TO_SERIAL
//#define WAIT_TO_START
/* Wait for serial input in setup(), only if serial is enabled. You don’t want
to define WAIT_TO_START unless ECHO_TO_SERIAL is defined, because it would
wait forever to start if you aren’t using the serial monitor.
If you want echo to serial, but not wait to start,
just comment out the above define */
#endif

char FileName[] = “LOG00000.CSV”; //the first file name

#ifndef cbi //defs for stopping the ADC during sleep mode
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define DS3231_I2C_ADDRESS 104 //for the RTC temp reading function
#define EEPROM_ADDR 0x57 // I2C Buss address of AT24C32 32K EEPROM
#define EEPromPageSize 32 //32 bytes for the AT24c32 I am using

#define BMA250 0x18
#define BW 0x08 //7.81Hz bandwith
#define GSEL 0x03 // set range 0x03=2g, 0x05=4, 0x08=8g, 0x0C=16g

//I2C eeprom variables
unsigned int CurrentPageStartAddress = 0; //set to zero at the start of each cycle
char EEPROMBuffer[28]; //this buffer contains a string of ascii
//char EEPROMinBuffer[28]; // this buffer recieves numbers from the eeprom was an unsigned char
//note the data read from the eeprom is binary – not ascii characters!

RTC_DS3231 RTC;
byte Alarmhour = 1;
byte Alarmminute = 1;
byte dummyRegister;
byte INTERRUPT_PIN = 2;
volatile boolean clockInterrupt = false;
byte tMSB, tLSB; //for the RTC temp reading function
float RTCTempfloat;
char CycleTimeStamp[ ]= “0000/00/00,00:00:00”;
byte Cycle=0;

//variables for accellerometer reading
uint8_t dataArray[16];
int8_t BMAtemp;
float BMAtempfloat;
uint8_t wholeBMAtemp,fracBMAtemp;
int x,y,z; //acc readings range to negative values

int temp3231;
uint8_t wRTCtemp,fRTCtemp; //components for holding RTC temp as whole and fraction component integers
int Vcc;//the supply voltage via 1.1 internal band gap
byte ledpin = 13; //led indicator pin not used in this code
// the LED on pin 13 is also shared with the SPI SCLK clock, which is used by the microSD card TinyShield.
// So when you use a SPI device like the SD card, the LED will blink, and the SD library will override the digitalWrite() function call.
// If you need a LED for indication, you’ll need to hook up an external one to a different I/O pin.

void setup () {

pinMode(INTERRUPT_PIN, INPUT);
digitalWrite(INTERRUPT_PIN, HIGH);//pull up the interrupt pin
pinMode(13, OUTPUT); // initialize the LED pin as an output.

Serial.begin(9600);
Wire.begin();
RTC.begin();
clearClockTrigger(); //stops RTC from holding the interrupt low if system reset
// time for next alarm
RTC.turnOffAlarm(1);

#ifdef WAIT_TO_START // only triggered if WAIT_TO_START is defined at beging of code
Serial.println(F(“Type any character to start”));
while (!Serial.available());
#endif

delay(1000); //delay to prevent power stutters from writing header to the sd card
DateTime now = RTC.now();

DateTime compiled = DateTime(__DATE__, __TIME__);
if (now.unixtime() < compiled.unixtime()) { //checks if the RTC is not set yet
Serial.println(F(“RTC is older than compile time! Updating”));
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}

initializeBMA(); //initialize the accelerometer – do I have to do this on every wake cycle?

//get the SD card ready
pinMode(chipSelect, OUTPUT); //make sure that the default chip select pin is set to output, even if you don’t use it

#ifdef ECHO_TO_SERIAL
Serial.print(F(“Initializing SD card…”));
#endif

// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library. // change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
Serial.println(F(“Cound not Initialize Sd Card”));
error(“0”);}

#ifdef ECHO_TO_SERIAL
Serial.println(F(“card initialized.”));
Serial.print(F(“The sample interval for this series is: “));Serial.print(SampleInterval);Serial.println(F(” minutes”));
Serial.println(F(“Timestamp Y/M/D, HH:MM:SS,Time offset, Vcc = , X = , Y = , Z = , BMATemp (C) , RTC temp (C)”));
#endif

// open the file for write at end like the Native SD library
// O_CREAT – create the file if it does not exist
if (!file.open(FileName, O_RDWR | O_CREAT | O_AT_END)) {
Serial.println(F(“1st open LOG.CSV fail”));
error(“1”);
}

file.print(F(“The sample interval for this series is: “));file.print(SampleInterval);file.println(F(” minutes”));
file.println(F(“YYYY/MM/DD HH:MM:SS, Vcc(mV), X = , Y = , Z = , BMATemp (C) , RTC temp (C)”));
file.close();

digitalWrite(13, LOW);
}

void loop () {

// keep track of how many lines have been written to a file
// after so many lines, start a new file
if(countLogs >= fileInterval){
countLogs = 0; // reset our counter to zero
createLogFile(); // create a new file
}

CurrentPageStartAddress = 0;

for (int Cycle = 0; Cycle < SamplesPerCycle; Cycle++) { //this counts from 0 to (SamplesPerCycle-1)

if (clockInterrupt) {
clearClockTrigger();
}

read3AxisAcceleration(); //loads up the Acc data
DateTime now = RTC.now(); // Read the time and date from the RTC

sprintf(CycleTimeStamp, “%04d/%02d/%02d %02d:%02d:%02d”, now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());

wholeBMAtemp = (int)BMAtempfloat; fracBMAtemp= (BMAtempfloat – wholeBMAtemp) * 100; // Float split into 2 intergers
//can use sprintf(BMATempHolder, “%2d.%2d”, wholeBMAtemp[Cycle], fracBMAtemp[Cycle]) if we need to recompose that float
RTCTempfloat= get3231Temp(); wRTCtemp = (int)RTCTempfloat; fRTCtemp= (RTCTempfloat – wRTCtemp) * 100; // Float split into 2 intergers
Vcc = (readVcc());
if (Vcc < 2800){Serial.println(F(“Voltage too LOW”));error (“L”);}

//serial output for debugging – comment out ECHO_TO_SERIAL to eliminate
#ifdef ECHO_TO_SERIAL
Serial.print(CycleTimeStamp); Serial.print(F(” Cycle “)); Serial.print(Cycle);Serial.print(F(“,”)); Serial.print(Vcc); Serial.print(F(“,”));
Serial.print(x); Serial.print(F(“,”));Serial.print(y); Serial.print(F(“,”)); ;Serial.print(z); Serial.print(F(“,”));
Serial.print(wholeBMAtemp);Serial.print(F(“.”));Serial.print(fracBMAtemp);Serial.print(F(“,”));
Serial.print(wRTCtemp);Serial.print(F(“.”));Serial.print(fRTCtemp);
Serial.print(F(“, Ram:”));Serial.print(freeRam());
delay(40); //short delay to clear com lines
#endif

//Construct first char string of 28 bytes – end of buffer is filled with blank spaces flexibly with pstring
//but could contruct the buffer with sprintf if I wasn’t changing my sensors so often!

PString str(EEPROMBuffer, sizeof(EEPROMBuffer));
str = CycleTimeStamp;str.print(F(“,”));str.print(Vcc);str.print(F(” “));

Write_i2c_eeprom_page(EEPROM_ADDR, CurrentPageStartAddress, EEPROMBuffer); // whole page is written at once here
CurrentPageStartAddress += EEPromPageSize;

//Construct second char string of 28 bytes to complete the record
str = “,”; str.print(x);str.print(F(“,”));str.print(y);str.print(F(“,”));str.print(z);str.print(F(“,”));
str.print(wholeBMAtemp);str.print(F(“.”));str.print(fracBMAtemp);str.print(F(“,”));
str.print(wRTCtemp);str.print(F(“.”));str.print(fRTCtemp);str.print(F(“,”));str.print(F(” “));

Write_i2c_eeprom_page(EEPROM_ADDR, CurrentPageStartAddress, EEPROMBuffer); // 28 bytes/page is max whole page is written at once here
CurrentPageStartAddress += EEPromPageSize;

// IF full set of sample cycles is complete, run a loop to dump data to the sd card
// BUT only if Vcc is above 2.85 volts so we have enough juice!
if (Cycle==(SamplesPerCycle-1) && Vcc >= 2850){

#ifdef ECHO_TO_SERIAL
Serial.print(F(” –Writing to SDcard –“)); delay (10);// this line for debugging only
#endif

CurrentPageStartAddress=0; //reset the page counter back to the beginning

file.open(FileName, O_RDWR | O_AT_END);
// open the file for write at end like the Native SD library
//if (!file.open(FileName, O_RDWR | O_AT_END)) {
// error(“L open file fail”);
//}

for (int i = 0; i < SamplesPerCycle; i++) { //loop to read from I2C ee and write to SD card

Read_i2c_eeprom_page(EEPROM_ADDR, CurrentPageStartAddress, EEPROMBuffer, sizeof(EEPROMBuffer) ); //there will be a few blank spaces
CurrentPageStartAddress += EEPromPageSize;
file.write(EEPROMBuffer,sizeof(EEPROMBuffer));

Read_i2c_eeprom_page(EEPROM_ADDR, CurrentPageStartAddress, EEPROMBuffer, sizeof(EEPROMBuffer) );
CurrentPageStartAddress += EEPromPageSize;
file.write(EEPROMBuffer,sizeof(EEPROMBuffer));
file.println(F(” “));

countLogs++;
// An application which writes to a file using print(), println() or write() must call sync()
// at the appropriate time to force data and directory information to be written to the SD Card.
// every 8 cycles we have dumped approximately 512 bytes to the card
// note only going to buffer 96 cycles to eeprom (one day at 15 min samples)
if(i==8){syncTheFile;}
if(i==16){syncTheFile;}
if(i==24){syncTheFile;}
if(i==32){syncTheFile;}
if(i==40){syncTheFile;}
if(i==48){syncTheFile;}
if(i==56){syncTheFile;}
if(i==64){syncTheFile;}
if(i==72){syncTheFile;}
if(i==80){syncTheFile;}
if(i==88){syncTheFile;}
}
file.close();
}
// setNextAlarmTime();
Alarmhour = now.hour(); Alarmminute = now.minute()+SampleInterval;
if (Alarmminute > 59) { //error catch – if alarmminute=60 the interrupt never triggers due to rollover!
Alarmminute =0; Alarmhour = Alarmhour+1; if (Alarmhour > 23) {Alarmhour =0;}
}
RTC.setAlarm1Simple(Alarmhour, Alarmminute);
RTC.turnOnAlarm(1);

#ifdef ECHO_TO_SERIAL
Serial.print(F(” Alarm Set:”)); Serial.print(now.hour(), DEC); Serial.print(‘:’); Serial.print(now.minute(), DEC);
Serial.print(F(” Sleep:”)); Serial.print(SampleInterval);Serial.println(F(” min.”));
delay(100); //a delay long enought to boot out the serial coms
#endif

sleepNow(); //the sleep call is inside the main cycle counter loop

} //samples per cycle loop terminator
} //the main void loop terminator

void createLogFile(void) {
// create a new file, up to 100,000 files allowed
// we will create a new file every time this routine is called
// If we are creating another file after fileInterval, then we must
// close the open file first.
if (file.isOpen()) {
file.close();
}
for (uint16_t i = 0; i < 100000; i++) {
FileName[3] = i/10000 + ‘0’;
FileName[4] = i/1000 + ‘0’;
FileName[5] = i/100 + ‘0’;
FileName[6] = i/10 + ‘0’;
FileName[7] = i%10 + ‘0’;
// O_CREAT – create the file if it does not exist
// O_EXCL – fail if the file exists O_WRITE – open for write
if (file.open(FileName, O_CREAT | O_EXCL | O_WRITE)) break;
//if you can open a file with the new name, break out of the loop
}

// clear the writeError flags generated when we broke the new name loop
file.writeError = 0;

if (!file.isOpen()) error (“diskful?”);
Serial.print(F(“Logging to: “));
Serial.println(FileName);

// fetch the time
DateTime now = RTC.now();
// set creation date time
if (!file.timestamp(T_CREATE,now.year(),now.month(),now.day(),now.hour(),
now.minute(),now.second() )) {
error(“cr t”);
}
// set write/modification date time
if (!file.timestamp(T_WRITE,now.year(),now.month(),now.day(),now.hour(),
now.minute(),now.second() )) {
error(“wr t”);
}
// set access date
if (!file.timestamp(T_ACCESS,now.year(),now.month(),now.day(),now.hour(),
now.minute(),now.second() )) {
error(“ac t”);
}
file.sync();
//file.close();
//file.open(FileName, O_RDWR | O_AT_END);

// write the file as a header:
file.print(F(“The sample interval for this series is:”)); ;Serial.print(SampleInterval);Serial.println(F(” minutes”));
file.println(F(“YYYY/MM/DD HH:MM:SS, Vcc(mV), X = , Y = , Z = , BMATemp (C) , RTC temp (C)”));
file.close();

#ifdef ECHO_TO_SERIAL
Serial.println(F(“New log file created on the SD card!”));
#endif // ECHO_TO_SERIAL

// write out the header to the file, only upon creating a new file
if (file.writeError) {
// check if error writing
error(“write header”);
}

// if (!file.sync()) {
// check if error writing
// error(“fsync er”);
// }

}
void syncTheFile(void) {
/* don’t sync too often – requires 2048 bytes of I/O to SD card.
512 bytes of I/O if using Fat16 library */
/* blink LED to show we are syncing data to the card & updating FAT!
but cant use LED on pin 13, because chipselect */
// digitalWrite(LEDpin, HIGH);
if (!file.sync()) { error(“sync error”);}
// digitalWrite(greenLEDpin, LOW);
}

// Address is a page address
// But data can be maximum of 28 bytes, because the Wire library has a buffer of 32 bytes
void Write_i2c_eeprom_page( int deviceaddress, unsigned int eeaddress, char* data) {
unsigned char i=0;
unsigned int address;
address=eeaddress;
Wire.beginTransmission(deviceaddress);
Wire.write((int)((address) >> 8)); // MSB
Wire.write((int)((address) & 0xFF)); // LSB
do{
Wire.write((byte) data[i]);i++;
} while(data[i]);
Wire.endTransmission();
delay(10); // data sheet says 5ms for page write
}

// should not read more than 28 bytes at a time!
void Read_i2c_eeprom_page( int deviceaddress, unsigned int eeaddress,char* data, unsigned int num_chars) {
unsigned char i=0;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress,(num_chars-1));
while(Wire.available()) data[i++] = Wire.read();
}

void sleepNow() {
// can set the unused digital pins to output low – BUT only worth 1-2 µA during sleep
// if you have an LED or something like that on an output pin, you will draw more current.
// for (byte i = 0; i <= number of digital pins; i++)
// {
// pinMode (i, OUTPUT);
// digitalWrite (i, LOW);
// }

cbi(ADCSRA,ADEN); // Switch ADC OFF: worth 334 µA during sleep
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0,clockTrigger, LOW);
// turn off brown-out enable in software: worth 25 µA during sleep
// BODS must be set to one and BODSE must be set to zero within four clock cycles
// BUT http://learn.adafruit.com/low-power-coin-cell-voltage-logger/other-lessons
// MCUCR = bit (BODS) | bit (BODSE); // turn on brown-out enable select
// MCUCR = bit (BODS); // The BODS bit is automatically cleared after three clock cycles
sleep_mode();
//HERE AFTER WAKING UP
sleep_disable();
detachInterrupt(0);
sbi(ADCSRA,ADEN); // Switch ADC converter back ON
//digitalWrite(13, HIGH); this doesnt work because of conflict with sd card chip select
}

void clockTrigger() {
clockInterrupt = true; //do something quick, flip a flag, and handle in loop();
}

void clearClockTrigger()
{
Wire.beginTransmission(0x68); //Tell devices on the bus we are talking to the DS3231
Wire.write(0x0F); //Tell the device which address we want to read or write
Wire.endTransmission(); //Before you can write to and clear the alarm flag you have to read the flag first!
Wire.requestFrom(0x68,1); // Read one byte
dummyRegister=Wire.read(); // In this example we are not interest in actually using the bye
Wire.beginTransmission(0x68); //Tell devices on the bus we are talking to the DS3231
Wire.write(0x0F); //Tell the device which address we want to read or write
Wire.write(0b00000000); //Write the byte. The last 0 bit resets Alarm 1
Wire.endTransmission();
clockInterrupt=false; //Finally clear the flag we use to indicate the trigger occurred
}

// could also use RTC.getTemperature() from the library here as in:
// RTC.convertTemperature(); //convert current temperature into registers
// Serial.print(RTC.getTemperature()); //read registers and display the temperature

float get3231Temp()
{
//temp registers (11h-12h) get updated automatically every 64s
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0x11);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 2);

if(Wire.available()) {
tMSB = Wire.read(); //2’s complement int portion
tLSB = Wire.read(); //fraction portion

temp3231 = ((((short)tMSB << 8 | (short)tLSB) >> 6) / 4.0);
// Allows for readings below freezing – Thanks to Coding Badly
//temp3231 = (temp3231 * 1.8 + 32.0); // Convert Celcius to Fahrenheit
return temp3231;

}
else {
temp3231 = 255.0; //Use a value of 255 as error flag
}

return temp3231;
}
byte read3AxisAcceleration()
{
Wire.beginTransmission(BMA250);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(BMA250,7);
for(int j = 0; j < 7;j++)
{
dataArray[j] = Wire.read();
}
if(!bitRead(dataArray[0],0)){return(0);}

BMAtemp = dataArray[6];
x = dataArray[1] << 8;
x |= dataArray[0];
x >>= 6;
y = dataArray[3] << 8;
y |= dataArray[2];
y >>= 6;
z = dataArray[5] << 8;
z |= dataArray[4];
z >>= 6;

BMAtempfloat = (BMAtemp*0.5)+24.0;
}
byte initializeBMA()
{
Wire.beginTransmission(BMA250);
Wire.write(0x0F); //set g
Wire.write(GSEL);
Wire.endTransmission();
Wire.beginTransmission(BMA250);
Wire.write(0x10); //set bandwith
Wire.write(BW);
Wire.endTransmission();
return(0);
}

long readVcc() { //trick to read the Vin using internal 1.1 v as a refrence
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(3); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}

int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v – (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

void error(char *str) {
// always write error messages to the serial monitor but this routine wastes
// everything passed to the string from the original call is in sram!
Serial.print(F(“error in: “));Serial.println(str);
/* this next statement will start an endless loop, basically stopping all
operation upon any error. Change this behavior if you want. */
while (1);
}

Walkin’ the walk…

I still have a long road ahead of me when it comes programming. But I figure that I since I started pretty near zero at the beginning of this project, I could share some thoughts on the process; before I forget what it was like. There were real benchmarks along the way, which made me feel pretty good when I achieved them, even if the goal posts seemed to move every single time.

Stage 1: Ummm, Is this thing on?

Initially, I was just reading the data from the sensors and sending that to the serial monitor to see what kind of numbers were being produced.  With the original Uno, and analog sensors like the MMA7260 this was just a few analogRead() statements. With a few simple lines of code, you know if you connected the wires properly. Still, it was cool to (carefully) move my little contraption around, see the numbers changing, and start thinking about how to calibrate the sensor, and whether I should  change AREF to get more juice out of the ADC. Also, to wonder if I should massage that data to get rid of all the jitter I was seeing in those numbers.

Stage 2: Going to the library.

Then I tackled writing the to the SD cards, copying code directly from the Adafruit datalogger shield tutorials. This introduced me to the concept of libraries: mysterious extra bits of code that I had to go find, and then #include with the program, to get the Arduino sketch to work. This was true for the SD cards, the RTC, and basically anything else that sent information to the microprocessor, rather than just putting a voltage on a pin.  These libraries are like the “killer apps” of the Arduino world. Without them, the best chip in the world remains unusable, hiding up in the rarefied atmosphere of embedded system engineers.  But as soon as one of those boffins decides to “release the library” he came up with for chip “IC-123”, then suddenly the forums light up, and all the lesser mortals start using that device in a big way.  Being one of those humbler people myself, my first step when wondering whether I can use a new widget, is to see if I can find libraries for it on github. And even though part suppliers like Adafruit, Sparkfun et. al. have turned this phenomenon into a thriving business model, the actual chip makers themselves almost never make the special sauce; leaving you to chew on the dry, salty, datasheets.

Stage 3: Can you I2C me?

Pullup resistors added to the chronodot RTC

Getting different two wire interface chips to share the same data “party line”, has benchmark status for me, because it was the first time software issues really forced me to go back and learn about the electronics seriously enough to raise my game. I spent days trying to figure out what pullup resistors were really doing, and whether the different boards I was cobbling together had put just the right amount on the lines. This was an important issue to resolve before moving on to the next stage of the game, but it also changed my understanding from “It either works or it doesn’t”, to the realization that there are many shades of grey in the way circuits are designed. Generally speaking, you get what you pay for.

Stage 4: Does this thing run on batteries?

Once all the chips were on speaking terms, and the data was being recorded on the SD card, it was time to cut the umbilical.  From a benchmark point of view, this is were all the software power management strategies come into play: the sleep codes really had to work, and the SQW alarm pulse had to wake the whole thing up again.  I also had to think about what would happen to all the circuits as the voltage started dropping. I had to learn about things like voltage regulators & level shifters, trying to find the weakest link in the chain, and then dug further into the forums to find out how far outside the specs you could actually go before you got into trouble.  In my project for example, I had prevent memory card writing if the voltage got too low or I would toast the memory cards, and loose all the data.

Stage 5: To infinity and beyond…

So this where I am now, and I am sure that there are many more “stages” ahead of me. The units are working for a reasonable length of time on batteries, but I still need to multiply that by a factor of two or three, to reach my year+ run time target. Preserving every last micro amp raises issues like data buffering to reduce the power hungry SD writes. This takes me even further into programming issues like variable optimization, because the code I cobbled together is now so large, that memory management is has become crucial. Or, if i work on my chops, I might be able to eliminate the SD cards entirely, and use eeproms for storage. Of course, each time I add a new chip or sensor into the mix, it sends me right back to stage 1 again.

The real take home message, for the people thinking about their first Arduino project is this: At each step of the way, getting a piece of  hardware to work required me to learn more programming, and each software problem I faced, forced me to learn more about the devices I was trying to connect. It’s sort of like climbing a ladder, by lifting one leg, and then the other. And as I passed each stage, the previous code folded into one small corner of the next version, adding layers of complexity like an onion. But I had no idea this was what the process would actually be like when I started out, because almost every thing I read at the time seemed to be written by technical geniuses that don’t have time for this kind of retrospective stuff.

 

A note on using the TinyDuino platform

_IGP9121I thought it might be good to put a few words in here on working with the Tinyduino system, because, although I really love the small footprint, and power optimization, you could say they were a “trial by fire” for someone with basic soldering skills.  Initially, I took one of their protoboards and added three rows of jumper pins to connect my RTC. This appeared to go ok so I painstakingly did this to all the proto-boards I had on hand.

But while it all seemed to go pretty well at first, I just could not get the darned RTC to work reliably.  I labored long under the chrondotassumption that I was making mistakes in the code (which hey, I probably was), or I had not pulled up the I2C bus properly, or there was something else I just had not learned yet. I eventually discovered that the tiny protoboard was slowly bending under the force of the jumper wires themselves, loosing contact with the stack, or shorting out on the layer below ( I did not have spacers in place to prevent this). And even when I fixed that, I still had weird intermittent faults occurring. Nothing is more frustrating than something that works fine most of the time, but then randomly cuts out on you.

_IGP9129In the end it turned out to be bridging between those really small contacts. I must have done it when I was soldering the pins on, but even after really close inspection, I could not see the bridge anywhere.  I ordered more boards, and started soldering thinner wires directly on, but then the wires themselves started breaking, because they were so fragile. I eventually figured out how to add some extra “support solder” by folding the wires over into a bit of ‘J’ hook, but even then they still couldn’t take much jostling around.  Now, I know there’s plenty of people out there just waiting to post a comment like: “If you are not already working with surface mount, just go home rookie”.

But I made this project blog in the hope that it might help other folks get rolling, so if, unlike me, you still have all your hair: do yourself a favor and buy a really good temperature controlled soldering iron, with ultra fine points in ‘mint’ condition. And I would recommend a fair bit of soldering practice, with a solder wick, before you jump in on those 0.1 inch Tinyduino proto-boards. Even then, buy extras, because you are probably going to go through them much faster than you think. I know I did.

Addendum 2014-02-10
And you don’t need to replicate my errors here any more because Tiny-Circuits has released an extended protoboard that you can buy naked for $5, or with terminal blocks!  These let you place the extension board in the middle of the tinyduino stack &  with all that extra space, I have soldered of riser pins on dozens of those new “double-wide” proto boards without any problems.  Also I now use soft multi-strand test lead wire with silicone insulation (instead of stiff PVC), which dramatically reduces strain on the solder joints.