Category Archives: DIY Build a Pro Mini Logger

… from a few inexpensive components …

For an in-depth description of the Cave Pearl loggers and their performance
see: http://www.mdpi.com/1424-8220/18/2/530

Pro Mini Classroom Datalogger [2020 update]

2020 update to the Cave Pearl Classroom logger. This is a combination of inexpensive pre-made modules from the open-source Arduino ecosystem, and can usually be assembled by beginners in 1-2 hours.

(Last Updated: Oct 26, 2020)

Covid has thrown a spanner into the works with hands-on learning because even if you have enough space to run a ‘socially distanced’ course, the students could still be sent home at any time.  With that in mind, we’ve divided the tutorial from 2019 into separate stages that make it easier to restructure the labs:

1) Component prep:  requires the equipment you  normally have access to in the lab space like soldering irons, heat guns, drills, etc.

2) Logger assembly: can be done remotely with scissors, wire strippers & a screwdriver. Connections are made by clamping stripped wire ends under screw terminals.

The complete tutorial can be run F2F, or if students are ‘distance learning’, the instructor can do the soldering steps (~15 minutes per set) and send out kits ready for assembly. Even that will be challenging through a zoom window, so you might want to add USB isolators to protect  tethered student laptops from accidental shorts. 

This is variation of the logger described in our 2018 paper but we’ve removed the regulator/ voltage divider and added screw terminals + breadboards for faster prototyping.  Bridging the I2C bus over the A2 & A3 pins leaves only two analog inputs, but A6 & A7 are still available if you add jumpers. However for ~$1 you can add a 16-bit ADS1115 which provides far more analog sensor capability, and uses a fixed internal reference independent of the supply rail.

The main components:

 (NOTE: complete parts list with supplier links can be found at the end of this post) You don’t necessarily need the cable glands if you are using sensors that will work inside the housing (light, temp, acceleration, magnetic, etc.)

Component Prep.  Part 1:   Pro Mini   ( 3.3v 8Mhz )                       (click any image to enlarge)

Solder the UART pins & test ProMini board with the blink sketch:  Set the IDE to (1) TOOLS> Board: Arduino Pro or Pro Mini (2)TOOLS> ATmega328(3.3v, 8mhz) in addition to the (3)TOOLS> COM port to match the # that appears when you plug in the serial adapter board.

Remove Limit Resistor to disable power indicator

With a known good Promini: Remove the power LED [in red square].                               SPI bus clock pulses will flash the pin 13 LED – so  leaving the pin13 LED connected will show you when data is being saved to the SD card.

Remove the voltage regulator with snips. Your system voltage will vary over time, but our starter script records that rail voltage without a voltage divider by comparing it to the 328p’s internal bandgap voltage.

Add header pins to the sides of the Pro Mini, but do not solder the two RESET pins.

Bridge the two I2C bus connections with the wire leg of a resistor. Connect A4->A2 & A5->A3.

A4 & A5 I2C bus bridged to side rails

Adding:   DIDR0 = 0x0F;  in Setup disables digital I/O on pins A0-A3 so they can’t interfere with I2C bus.

Lithium AA batteries are preferred because the slope of an alkaline discharge curve will reach the ProMini’s 2.7v brown-out with >50% of the battery capacity unused. (note that SD cards are safe down to ~1.8v) While the voltage of a ‘brand new’ Lithium AA is usually 1.8v/cell, that upper plateau usually settles at ~1.7 v/cell within an hour or two of starting the logger. That briefly dips below 1.6v/cell during >100mA SD card save events. At temps near 5°C (in my refrigerator) the SD write battery-droop reached about 1.5 v/cell while on the upper plateau. Lithium cells deliver ~50% of their rated capacity at temps below freezing, but that’s still a vast improvement over alkaline batteries.

The MIC5205 regulator is not efficient at low currents, so removing it extends your operating life by 30~50%. But it also forces you to deal with a constantly changing rail voltage. Thermal variation from 15 to 45°C will raise your rail voltage by about 100millivolts (on lithium cells that have been in service for several months)You will need to compensate for this in your calculations if your analog sensor circuits are not ratio-metric. Battery thermal mass can also cause hysteresis unless you read the reference resistor under the same conditions. Regulated promini’s usually see the rail vary by only 10-20 millivolts over a similar range of temperatures however the regs on cheap eBay modules are subject to other problems such as noise which can be even more problematic wrt the quality of your data. 

So making students deal with deal with supply  issues right from the start will save them from making more serious mistakes later on because every component in your logger is a temperature sensor.  It’s also worth noting that most chip based sensor modules carry their own regulators (usually a 662k LDO) and use internal bandgap reference voltages that are independent of the rail/supply.

Component Prep. Part 2:     Screw-Terminal Board & SD adapter

Reset terminals repurposed with jumpers under the board

At the UART end of the board: Use a tinned resistor leg to repurpose the RESET terminals: Join RST & GND pins on the digital side and link the pins labeled RST, 5v and Vin for the positive rail.

Label the repurposed screw terminals with red & black markers.

Gently rock the Pro Mini back to front (holding the two short sides) until the pins are fully inserted. Some ST shields have slightly misaligned headers so this insertion can be tricky.

Remove the last three ‘unused’ female headers to make room for the SD adapter

…which fits perfectly into that pocket

Remove the bottom 3 resistors from the SD adapter – leave the top resistor near the C1 label in place!

Connection map for analog side of Nano S-Terminal board

NOTE: The Screw Terminal board we use in this build was designed for the 5v Arduino NANO, so the shield labels don’t match the actual 3.3v Pro Mini pins on the ‘analog’ side. (the digital side does match) To avoid confusion may want to tape over those incorrect labels and hand write new labels to match the pattern above. Wire connections in this tutorial will usually be specified by ProMini pin labels:  D10-13 are used for the SD card, A4/A2 is the I2C Data line, and A5/A3 is the I2C clock line.

Technically speaking, bridging the I2C bus (A4=data & A5=clock) over top of A2 & A3 subjects those lines to more capacitance and pin leakage. (regardless of whether that channel is selected as input for the ADC p257).  However in practice, the 4K7 pull-up resistors on the RTC module handle that well at the 100 kHz default bus speed.

Adding DIDR0 = 0x0F; in setup disables digital I/O on pins A0-A3 to prevent interference with the I2C bus. If you want to disable only the digital IO on A2 & A3 add bitSet (DIDR0, ADC2D); bitSet (DIDR0, ADC3D); to your code.

Also note: On the UART adapter shown in the first image, the pins are in the reverse order to those on the Pro Mini board. This is a fairly common issue and if your sketches won’t upload flip the adapter around and try again. I have connected these oggers to UART modules the wrong way round many, many times, and not one of them has been harmed by the temporary reversal.

Component Prep.  Part 3:     RTC Module,  RGB  LED  &  Plano 3440 Housing

Remove two SMD resistors from the RTC board with the tip of your soldering iron. Note that this module includes 4k7 pullup resistors on SQW, SCL & SDA

Cut the Vcc leg on DS3231 chip (this optional step disables 32kHz output)

Add 90 degree header pins to the I2C cascade port

Clean away soldering flux residue from both the main & cascade header pins

Use a coin cell to determine the (negative) GND leg of a diffused common cathode RGB LED

Solder ~1k ohm limit resistor on the common GND. The precise value is not critical.

Add heat shrink, bend & trim the pins for connection to the screw terminal board.

Holes in the rear struts of the Plano 3440 Stowaway housing provide secure tie-down points.

Stepped drill bits make nice clean holes in the plastic  housing and accommodate thread diameter variations.

Only add cable glands if they match your planned lab exercises. We use them with waterproof DS18b20 sensors on 1m cables.

Add rubber washers to both the inside and the outside surfaces. PG7 size washers fit M12 cable glands.

A 3440 Plano Box configured for two external sensors with nylon M12 cable glands for 3-6mm cables. After threading the sensor cables I often seal the outside of the glands with a layer of silicone goop.

As with the ProMini, it’s worth testing the RTC modules  before you continue with the assembly. I usually keep a breadboard version of the logger handy for this step so I can test several modules at the same time time. You could even set the clocks at this point if the coin-cell is already in place.

Forcing the RTC to run from the backup coin cell reduces overall current by 0.09mA, bringing a “no-reg & noRTCvcc” build below 0.15 mA when the logger sleeps between readings. (with well behaved SD cards)  As a rough estimate, Lithium AA’s provide ~7 million milliamp-seconds of power, and your logger will burn about 12,960 mAs/day at 0.15mA. So you should approach a year before you fall off the ‘upper plateau’.  The clock will reset to Jan 1st, 2000 if you disconnect the RTC battery contact  with a hard bump. (note: the time stamps will be wrong after that kind of reset, the logger will continue running once the clock rolls around to the previous hour/minute alarm)   A CR2032 can power the RTC about four years but you have to set bit six of the DS3231_CONTROL_REG to 1 to enable alarms when running from the coin-cell. (and our starter code does this by default)

All of the soldering steps are now completed, and the components are ready for assembly.

Cutting the Vcc leg is optional: if you leave the RTC power leg attached you’ll see typical sleep sleep currents in the 0.25 mA range, which usually provides 4-6 months of operation before you trigger the low voltage shutdown. I’m being conservative here because run time also depends on sensors and other additions you make to the base configuration.

Visit our RTC page for more detailed information on this DS3231 module.


Assembly Part 1:  The Screw-Terminal Stack

Add 2-3 layers of double sided foam tape to the sides & center of the screw terminal shield. The tape needs to extend beyond the height of the solder points.

Add single wires from the 20cm Dupont cable.     Black =GND,   Purple=MISO,   Brown=CLocK,   Orange=MOSI,   Grey=CableSelect,         Red=3v3

A layer of double sided foam tape secures the individual  connectors & should extend over the solder pins to prevent accidental contact

Tape the SD adapter into place on the areas that’s been cleared at the back of  the screw terminal board

Bend the jumper wires into place, mark the length & trim the wires.

Score the wire insulation about 1cm back from the wire end but do not remove the insulation.

Gently ‘pull & twist’ the  scored insulation away from the wire to wind the thin strands together.

‘Fold-back’ about half of the stripped wire to provide more copper surface for the screw terminals to bite on to.

 

 

SD Connection pattern:    Grey (CS) to ProMini D10Orange (MOSI) -> pm D11,      Purple (MISO) ->pm D12,        Brown (CLK) -> pm D13  (NOTE the shield labels say A0-A3 which do not match the D10-13 pattern of the Pro Mini pins)

Bring the red SD wire over to the re-purposed RST power connection

and the black wire to GND on the digital side. At this point you can test the  connections by inserting an SD card & running the CardInfo utility.

 

 

Connect the legs of the indicator LED at: D3=red, D4=GND, D5=green, D6=blue

Strip & connect the male ends of the wires you trimmed from the SD jumper wires. Brown to A1, Grey to A0, Orange to D7, Purple to D8.

Add a layer of double sided tape to the back of the 2xAA battery holder

Attach battery holder wires to RED>Vin & black>GND

Connect Dupont jumper wires so that the metal & plastic retainer clips are facing upwards after the logger is assembled. That way you can diagnose connection issues with the tip of a meter probe and, if necessary, pull out & replace a single bad wire without taking everything apart. We’ve used the hardware interrupt port at D3 for the red LED channel, but if you have sensors that need that just shift the LED over by one. Any I/O pins can be used for the LED, but 3,5 & 6 have PWM so you can do some color tricks with the LED using AnalogWrite.

Assembly Part 2: RTC Module Jumpers

Attach Dupont jumper wires to the RTC module using White=I2C Data, Yellow = I2C Clock. Blue is the SQR alarm output line. Nothing is attached to the 32k output pin.

Use 20cm M-F jumpers on the input side and shorter 10cm M-F wires on the smaller cascade port.

 

Add a layer of double sided tape to secure the jumper shrouds, and provide housing attachment points for the module.

Add as small piece of soft heat shrink tubing to reinforce the modules contact spring. This spring connection can be bumped loose if the logger is dropped.

Write the installation date on the coin cell with a marker. A new coin cell should power the RTC for several years.          To avoid accidentally disconnecting the coin cell battery after the logger is assembled ->

Always check the backup voltage by placing the positive probe tip between the spring plates rather than on the surface of the cell.

Assembly Part 3:    Connect modules inside the housing:

Attach the screw terminal stack onto the upper left corner of the housing, and the 2xAA battery holder in the lower right corner.

Add the first mini breadboard so that it’s rear right edge aligns with the second rear support strut on the housing.

Connect the stack jumpers to that breadboard to keep them out of the way & tape the RTC module to the lower left side, just below the screw terminal stack.

Measure, mark and trim:  Red=3.3v, Yellow=A3/A5 I2C clock, & White=A4/A2 I2C data with enough wire to twist & fold the stripped ends under the terminals

RTC module power & I2C bus connections:  All ports on analog side of the Pro Mini / Shield combination  now have some kind of wire connection.

Connect the black wire to the re-purposed RST=GND, and the blue alarm wire to the D2 with some extra wire length in a loop for strain relief.

Use the other side of the trimmed blue jumper wire  to extend the D9 connection over to the breadboard.

Attach a 3/4 inch cable mount to the back of the housing, low enough that it does not interfere with closing the housing lid.

Loosely tie the long dupont wires to the rear mount. Add another cable mount near the center of the housing and attach the 2nd mini breadboard.


Your Logger is now ready for testing!

A typical sensor configuration with: BMP280 pressure, BH1750 lux & 0.96″ I2C OLED display – connected by short jumper wires made with a crimping tool. The combination shown above averages ~10mA with screen & cpu running, and a sleep current of 0.147 mA with a 1Gb Sandisk SD card. Without the SD, the sleep current on this unit was 37µA; with the sensor modules needing 2-3µA each & the sleeping 0.96″ OLED drawing ~7µA.  A 25µA sleep current from the ProMini clone hints that the MCU might be fake but with a AA power supply it doesn’t really matter.

(Note: Most of the time the tests listed below go well, however if you run into trouble at any point read through the steps suggested for Diagnosing Connection Problems at the end of this page.)

Install the Arduino IDE into whatever default directory it wants – we’ve had several issues where students tried to install the IDE into some other custom sub-directory, and then code wouldn’t verify without errors because the IDE could not find the libraries. The programming environment is written in Java, and the IDE installer comes with its own bundled Java runtime so there should be no need for an extra Java installation. However we have seen machines in the past which would not compile known-good code until Java was updated on those machines; but this problem is rare.

If you have not already done so, there are three things you need to set under the IDE>TOOLS menu to enable communication with the logger:

Note: that the “COM’ setting will be different for each computer, so you will have to look for the one that appears on your system AFTER you plug in the UART module.

This is the connection pattern inside the mini breadboard. Don’t accidentally connect jumper wires by plugging them into the same row. NEVER CONNECT the black GND & red 3.3v wires together or the short circuit may kill your logger, and possibly the USB port they are connected to . . .

The one that’s easy to forget is choosing the 328P 3.3v 8Mhz clock speed. If you leave the 328p 5v 16mhz (default), the programs will upload OK, but any text displayed on the serial monitor will be random garbled characters because of the clock speed mismatch.  Also be sure to disconnect battery power (by removing one of the AA batteries) whenever you connect your logger to a computer.  There is no power switch on the loggers, which are turned on or off via the battery insertion. Use a screwdriver when removing the batteries so that you don’t accidentally cause a series of disconnect-reconnect voltage spikes which might hurt the SD card.

1. Test the LED – the default blink sketch uses the pin13 LED, but because that pin is shared with the SD card’s clock line it’s recommended that you test the RGB indicator instead by adding commands in setup which set the digital pin 4 act as the ground line for the LED:
     pinMode(4, OUTPUT);   digitalWrite(4, LOW); 
You will also need to change LED_BUILTIN variable in the blink code example to one of the pins connected to your led module – either Red=3, Green=5, or Blue=6.

2. Scan the I2C bus with the scanner from the Arduino playgound. The RTC module has a 4K eeprom at address 0x56 (or 57) and the DS3231 RTC chip should show up at address 0x68.

The address of the eeprom can be changed via solder pads on the board, so it may have a different address. If you don’t see at least these two devices listed in the serial monitor when you run the scan, there is something wrong with your RTC module or the way it’s connected: It’s very common for a beginner to get some of the wire connections switched around during assembly but with the screw terminals this takes only a few moments to fix.

3. Set the RTC time, and check that the time was set – The easiest method would be to use the SetTime / Gettime scripts from our Github repository, but you first you need to download & install this RTC control library  The SetTime script automatically updates the RTC to the moment the code was compiled (just before uploading) so only run SetTime once, and then upload the GetTime sketch to remove SetTime from memory. Otherwise SetTime will keep setting the RTC to the old ‘code compile time’ every time it runs – and one of the quirks of the Arduino environment is that it restarts the processor EVERY TIME you open a serial window.

Note:  the RTClib by Mr. Alvin that we use has the same name as the Adafruit library for this RTC and this will give you compiler errors with our logger script if somehow the Adafruit library is already installed on your computer. You may have to uninstall the Adafruit library ‘manually’ before installing Alvin’s RTClib. This problem of ‘two different libraries with the same name’ was common back when this project started many years ago, but is rare today.

Typical Cardinfo output when the connections are correct                                  (click to enlarge)

4. Check the SD card with Cardinfo
Note that the SDfat library we use to communicate with SD cards prefers them to be formatted as fat16, so 4GB or larger cards may not work because they often get formatted as fat32. With a 15 minute sampling interval, most loggers generate ~ 5Mb of CSV format text files per year. Older, smaller SD cards in the 256-512Mb range often use less power. Note that we apply internal pullup resistors on some of the SD card lines in setup to help the SD cards go into low power sleep modes more reliably.

5. Calibrate your internal voltage reference with CalVref from OpenEnergyMonitor.

This logger uses an advanced code trick to read the positive rail voltage to ~11mv resolution by comparing it to an internal 1.1v bandgap reference inside the processor. That internal ref. can vary by ±10% from one chip to another, and CalVref gives you a numerical constant which usually brings the starter script’s rail=battery readings within ±20mv of actual. An accurate rail reading is more important when you are using ANALOG sensors where the positive rail directly affects the ADC output, but you can skip this procedure if you are only using digital sensors because they use their own internal reference voltages.

Typical CalVref output          (click to enlarge)

Load CalVref while the logger is running from USB power and then measure the voltage between GND and the positive rail with a  voltmeter. (this voltage will vary depending on your computer’s USB output, and the UART adapter you are using) Then type that voltage into the entry line at the top of the serial monitor window & press the enter key. Write down the reference voltage & constant which is then output to the serial monitor window. I write these ‘chip-specific’ numbers inside the logger with a black marker as they are related only to the 328p processor on the ProMini board used to make that particular logger. You then need to change the line #define InternalReferenceConstant 1126400L in our starter code to match the long number returned by CalVref. Alternatively you could just tweak the value of the reference constant ‘by hand’, increasing or decreasing the value till the reported rail readings match what you measure with a voltmeter. After you’ve done this once or twice you can usually reach the correct value with about 10 successive guesses.

6. Find a script to run your on logger. For test runs on a USB tether, the simplest bare-bones logger code is probably Tom Igoe’s 1-pager at the Arduino playground. It’s not really deploy-able because it never sleeps the processor, but it is still a useful ‘1-pager’ for teaching exercises and testing sensor libraries.  In 2016 we posted an extended version of Tom’s code for UNO based loggers that included sleeping the logger with RTC wakeup alarms. Our current logging “Starter Script” has grown since then to ~750 lines, but it should still be understandable once you have a few basic Arduino programming concepts under your belt.


Using the logger for experiments:

One positive aspect of the relatively loose fit of the Plano box lid is that it lets you run sensor tests quickly if you jumper your sensor module with thin 28-30 gauge wires:

A BMP280 pressure sensing module on long wires with crimped male dupont ends in the breadboard.

~1″ square of foam mounting tape with wires spaced evenly

 

Leave the red backing facing up as you fold the tape & wires over the corner edge.

The front corners of the box exert less pressure than the back corner shown here.

The sharp inner edge of the lid would cut the wire insulation if the tape was not there to protect, and even then you can only use this trick a few times.

The tape over the wires has to be replaced every time.

This gives you a chance to do some test runs before you commit to modifying the housing with holes or cable glands. For some indoor experiments this might be all you actually need, though I would still coat the ‘non-sensing’ parts of that dangling breakout with either conformal coating or clear nail polish.

After 1-2 minutes of kneading to mix the epoxy you have ~ 1 minute to work the putty into place. (it will become rock-hard within ~10 minutes). Be sure to leave yourself enough extra wire/space inside the housing so that you can open and close the lid easily without disconnecting anything after the putty hardens. This seal is not strong enough for underwater deployments, but it should easily withstand exposure to rain-storm events.

For a classroom project you could simply drill small a hole through the lid and stick the sensor/module on top of the housing, sealing the hole with double-sided tape. Thicker pass-through cables can be also be sealed reasonably well with plumbers epoxy putty which is non-conductive, and adheres quite well to  metal, glass & plastic surfaces->  This putty is also a quick way to make custom mounting brackets, or even threaded fittings if you wrap it around a bolt (which you carefully remove before the putty hardens completely) 

Breadboard connections are very easy to bump loose, so once you have your prototype working, it’s usually best to re-connect the sensors directly to the screw terminals before deploying a logger where it could get knocked around. In a pinch you can secure breadboard pins with a small drop of hot glue to keep them from wiggling.  Also remember that there are six ‘unused’ screw terminals on the back of the shield and these can be use to connect wires together securely.

2019 Logger mounted on a south-facing window. The top surface was covered with  white label-maker tape to act as a diffuser. 

[Click HERE] to read about the many types of sensors can be added to this logger The transparent enclosure makes it easy to do light-based experiments. Grounding the indicator LED through a digital pin allows it to be used as both a status indicator, and as a light sensorThe code we are using for this is from the Arduino playground. This polarity reversal technique relies on the very tiny parasitic capacitance inside the LED. (~50-300pF) This technique works better when the LED is connected directly to input pins because breadboards can add random capacitance at the same scale. Another thing to watch out for is moisture condensation inside your logger housing: this provides an alternate discharge path for the reverse-charge on the LED, which effectively shorts out the light level reading.

We have integrated this technique into the starter script on GitHub. I’ve tweaked the playground version with port commands so the loop execution takes about 100 clock cycles instead of the default of about 400 clock cycles.  The faster version was used to generate the following light exposure graph with a generic 5mm RGB LED, with a 4k7Ω limiter on the common ground.

Red, Green & Blue channel readings over the course of one day from the indicator LED in the logger photo above.  The yellow line is from an LDR sensor the same unit, that was over-sampled to 16-bit resolution. The LED sensor has a logarithmic response and the left axis on the graph is a time- based measurement where more light hitting the LED sensor results in a lower number. Note how the RED signal changes before/after Blue & Green at sunrise & sunset.  LED’s work well with natural full-spectrum light, but their limited frequency bands can give you trouble with the odd spectral distribution of indoor light sources. The peak response of LED’s is usually 30–50nm lower than their peak emission wavelength So the blue channel is actually recording in the near-UV range, the Green channel is responding at ~ 420nm (blue) and the red channel is actually responding to a wide band of yellow-green light. 

You can read more about LED based sensing techniques in the post about our leaf testing experiments which used two LEDs for a transmission-based variant of the NDVI ratio.

While the LED sensor idea is fun to work with, it’s a relatively slow method that can keep the logger running for many seconds when light levels are low. Figuring out how to take those light readings only during the day is a good coding exercise for students.

Note: VERY FEW light sensors can withstand exposure to direct sunlight. PTFE is an excellent light diffusing material which available in different sheet thicknesses.  The ‘divot’ on the lid of the Plano box is just a bit larger than 55mm x 130mm x 3mm (depth). The “teflon” tape that plumbers use to seal threaded joints can also be used. PTFE introduces fewer absorbance artifacts than other DIY diffusers like ping-pong balls, or hot melt glue. Most light sensors like the TSL2561 need 3-5mm of that PTFE sheeting to prevent the sensors from saturating in full sun. LED’s don’t saturate that badly, but you still lose all the useful detail in your data at peak brightness > 80,000 lux unless you add a diffusion layer to attenuate.

Full sun exposure can also cook your logger. Internal temps above 80°C may cause batteries to leak or damage the SD card.  So if you are leaving the logger in full sun, add a bit of reflective film or some aluminum foil around the outside to protect the electronics. Of course if you have a light sensor you’ll need to leave an un-covered ‘window area’ for it to take a reading. 

The RTC has a built-in temperature register which automatically gets saved with our starter script however that record only resolves 0.25°C, so we’ve also added support for the DS18b20 temperature sensor to the base code. A genuine DS18b20 (yes, fake sensors are a thing) draws very little power between readings and you can add many DS18b’s to the same logger.


Addendum: Diagnosing Connection Problems

If you successfully loaded the blink sketch to test the ProMini during your initial assembly, then issues during the testing stage are often due to incomplete connections to the I/O pins.

If you see only “Scanning I2C….. ” but nothing else appears when running the bus scanner, then it means that the ProMini can not establish communication with the RTC module. One common cause of this problem is that the white & yellow wires have been switched around at one end or the other. It’s also easy to not quite remove enough insulation from the wires to provide a good electrical connection under the screw terminals, so undo those connection and check that the wires were stripped, cleaned & wrapped together before being put under the terminals.

Scanner lockup can also happen if one of the I2C devices on the bus is simply not working: usually about 1 in 6 logger builds ends up with some bad component that you have to identify by process of elimination. (These are 99¢ parts from eBay…right?) It only takes a moment to swap in a new RTC board via the black Dupont connector and re-run the scan. If the replacement RTC also does not show up with the I2C scanner then it’s likely that one of the four bus lines does not provide a complete connection between the ProMini & the RTC module.

On this unit I measured 1 ohm of resistance on the I2C clock line between the ProMini A5 pin (on top of the board) and the SCL header pin on the RTC module. So this electrical connection path is good. It’s not unusual for each ‘dry’ connection to add 0.5-1 ohm of resistance to a signal path.

To diagnose: Unplug any power sources to the logger. Set a multi-meter to measure resistance and put one probe lead on the topmost point of the promini header pins, and the other probe on the corresponding header pin of the RTC module. If there is a continuous electrical connection between the two points then the meter should read one ohm or less. Higher resistances mean that you don’t have a good electrical path between those points even if they look connected:

1) the ground (black) wire should provide a continuous path from the ground pin on the digital side of the Promini board to the GND pin on the RTC module
2) the positive power (red) wire should provide a continuous path from the Promini positive rail pin (the one with the bundle of 4 red wires) to the VCC pin on the RTC
3) A4 (I2C data) near the 328P chip on the Promini must connect all the way through the screw terminal board and through the white Dupont wires to the SDA post on the RTC
4) A5 (I2C clock) nearest the UART end on the Promini must connect through through the yellow Dupont wire to the SCL header on the RTC .

You occasionally get a bad Dupont wire where the silver metal end is not in contact with the  copper wire inside because the crimp ‘wings’ did not fold properly. With a pair of tweezers, you can ‘gently’ lift the little plastic tab on the black shrouds holding the female Dupont ends in place, and then replace any single bad wire. Be careful not to break the little black tab or you will have to replace the entire shroud.

Also look at the little jumpers used to bridge the A4>A2 and A5>A3. If you have a ‘cold’ solder join, or an accidental bridge connection to something else, it could stop the bus from working. Remelt each connection point one at a time, holding the iron long enough to make sure the solder melts into a nice ‘liquid flow’ shape for each solder point.

The connection diagnosis procedures described above also apply to the connections for the SD adapter board. Sometimes you end up with an adapter that has a defective spring contact inside the SD module, but the only way to figure that out is to swap it with another one.

Here a jumper wire from the Promini pins is by-passing a bad connection.  This is also how you would break out A6 & A7 connections if you need them.

Sometimes those screw terminal boards have a poor connection inside the black female headers below the Promini. It’s also possible to accidentally over-tighten a terminal and ‘crack’ the solder connection below the board – or there may simply be a cold solder joint on one of the terminal posts. If you have only one bad connection, you can jumper from the Promini header pins on top, down to the other wires under the corresponding screw terminal. If you accidentally strip the threads on a screw terminal, you can use this same approach but move that set of wires over to one of the three ‘unused’ screw terminals at the far end of the board. (beside the SD card adapter) If you’ve gotten through all of the above steps and still have not fixed the problem, then it might be time to simply rebuild the logger with a different screw terminal adapter board.

 

If you do accidentally kill the ProMini by shorting a pin, etc, you can carefully lever it up away from the screw terminal shield and replace it without having to rebuild the whole logger.

I recommend that you build two loggers at a time, because that lets you determine whether problems are code related (which will affect both machines the same way) or hardware related. (which will only affect one of your two units) At any given time I usually have 2-3 units running overnight tests so that I can compare the effect of two different code/hardware changes the next morning.  As a general rule you want to run a new build for at least a week before deploying to get beyond any ‘infant mortality’, and reach the good part of the bathtub curve.

 


An I2C OLED is quite readable through the lid of the housing. I use Griemans text-only SSD1306Ascii library because it has a low memory footprint and sleeps well. While few loggers need output screens when they are actually deployed, it’s nice to have them when you are testing a new sensor configuration because they give you a way to view diagnostic messages when the logger is running on battery power.

Addendum:  A note about I2C sensors
The I²C bus is slow, so topology (star, daisy-chain, etc.) doesn’t matter much, but capacitance does. Length and number of devices increase capacitance. If you find that the devices work when you switch to a slower speed (e.g. 50 kHz), then this is probably your issue, and you need to minimise bus length and/or maybe decrease the combined resistance of the pull-ups to 2 kΩ or less. The DS3231 RTC module has 4k7 ohm pull-up resistors on the SDA & SCL lines & the Pro Mini adds internal 50k pull ups when the wire library is enabled. Typical I2C sensor modules usually add another set of 10k pullups so your ‘net pullup resistance’ on the I2C bus wires is usually:  50k // 4k7 // 10k = ~3k. With a 3.3v rail that means the devices draw 3.3v / 3k = 1 mA during communication which is fairly normal ( 3mA is max allowed) for total wire lengths below 1m. It’s common for pre-packaged sensors to arrive with housings at the end of about 1m of wire. If each sensor also adds another set of 10k pullups, the resistance generally compensates for the extra wire length, so the combination still works OK. But that depends on the cable too. A very bad cable might not even get to 0.5 meters and a very good cable (little capacitance to ground, no crosstalk between the wires) can go up to 6 meters.

For most sensor types there will be some options that draw much less power than others, and it’s always worth a look at the data sheet to make sure you are using one that will run longer.  The best chip based sensors automatically go into low current modes whenever the bus has been inactive, but more often you need to ‘manually’ put the sensors to sleep via specific commands. So it’s also important to check if your sensor library supports those ‘goto sleep’ & ‘wake up’ commands –  many common Arduino libraries do not.


Addendum:  The importance of moisture protection

I was noodling around in the garden recently and installed a few loggers without desiccants because it was only a short experiment. It rained immediately afterward and I noticed a small amount of moisture condensed inside the plano-box housing. While this didn’t prevent the logger from functioning, it completely disrupted the LED light sensors because it provided an alternate discharge path for the reverse bias charge:

Green channel data from a 5mm diffused RGB LED used as light level sensor. This logger was under some leaf cover, so there was considerable variability from the dappled light crossing over the sensor. An arbitrary cutoff of 200,000 was set in the code at low light levels.

After examining the O-ring I decided to add a little silicone to the channel holding the o-ring to improve the seal:

Gently pry the O-ring loose and apply sealant in the groove before replacing.

Bead only needs to be 3-4mm in diameter.

Close the housing & let the sealant set for a few days. The improved seal is especially visible at the corners

If you already have your logger assembled, try to find a silicone sealant that does not off-gas acetic acid (smells like vinegar) which could harm your circuits. If you are simply preparing empty boxes before assembly, then any regular bathroom sealant will do provided you give it about a week to finish curing.

Attach a mounting base to the lid so that a dessicant pack can be secured above the battery holder without interfering with any breadboard jumpers. Use a desiccant pack with color indicator beads, so you can check whether they are still working simply by looking through the transparent lid.

 


Addendum:  If you want to leave the original regulator in place

There are only a few of modifications to the tutorial above if you wish to leave the ProMini’s default MIC5205 regulator in place on your logger:

Use straight header pins on the RTC modules cascade port

Only bridge the unused RST terminals to the rail connections – Leave the Vin terminal separate for the raw battery input.

 

Add a 10/3.3 Meg voltage divider to read the raw battery voltage on A0

…and of course you will need more space for the extra batteries.

An alternative would be to add a better regulator to an intermediate battery connector. The the photo on the right shows two ceramic 105’s stabilizing an MCP1702-3302E/TO, while the 10/3.3M ohm divider provides a third output so an ADC channel can monitor the raw battery voltage. This is the simplest way to retro-fit a unit that was built without a reg, with the added benefit that the new regulator is far more efficient than the original MIC5205 on the ProMini.


Addendum:  Things to keep in mind when ordering parts

When a finished module arrives at your doorstep for less than you’d pay for any of its sub-components individually it’s because  you are doing the quality control.

My advice is to order at least 5-6 of each of the core components (Promini, RTC, SD module, screw terminal board, etc) with the expectation that about 10% of any cheap eBay modules will be DOA or have some other problem. I build loggers in batches of six, and one unit typically ends up with a bad part somewhere. Having replacement bits on hand is your #1 way to diagnose and fix these issues. I’ve noted over the years that bad parts tend to come “in bunches”, so if you scale up to ordering in quantities of 10’s & 20’s then spread those orders to a few different suppliers so you don’t end up with all your parts coming from the same flakey production run. 

 

The other thing I can’t stress enough is CLEAN ALL THE PARTS as soon as they arrive. Leftover flux is very hygroscopic, and pretty much guarantees that solder points will start to corrode the moment your logger gets exposed to atmospheric moisture. I usually give everything about 10 minutes in a cheap sonic bath with 90% isopropyl alcohol, rinse with water, and then dry the parts out in front of a strong fan for an hour. Clean parts that can’t take the sonic vibration (RTC modules, humidity sensors, accelerometers, etc) by hand with a cotton swab. Then store parts in a sealed container with a dessicant pack till you need them.  I also coat the non-sensing/non-contact surfaces with a layer of MG Chemicals 422B Silicone Conformal Coating and let that dry for a day before assembling the loggers.  One hint that you may have moisture issues is that the sensors seem to run fine in the house but start to act strangely when you deploy the unit outside.

Used nut containers make excellent “dry storage” once the parts have been cleaned – but any air-tight container will do.

Another insight I can offer is that the quality of a sensor component is often related to the current it draws – if your ‘cheap module’ is pulling significantly more power than the data sheet indicates, then theres a good chance it’s a junk part. Usually if the sleep current is on spec, then the sensor is probably going to work. It is much easier to check low currents with a µCurrent or a Current Ranger. (I prefer the CR for it’s auto-ranging feature) Sensors which automatically go into low current sleep modes take time to do – so you might need to watch the loggers sleep current for several seconds  before they enter their quiescent state. With SD cards, if the freshly formatted throughput drops too far below rated write speeds when tested with H2testw, then find another card to use with your logger. I avoid cards bigger than 2Gb because they draw too much current, and it’s rare to need that much space on a datalogger.

TransparentSinglePixl
Bill of Materials: ~$22.00
Plano 3440-10 Waterproof Stowaway Box
Sometimes cheaper at Amazon. $4.96 at Walmart and there are a selection of larger size boxes in the series. 6″ Husky storage bins are an alternate option.
$5.00
Pro Mini Style clone 3.3v 8mHz
Get the ones with A6 & A7 broken out at the back edge of the board. Just make sure its the 3.3v version because you can’t direct-connect the SD cards to a 5v board.
$2.20
‘Pre-assembled’ Nano V1.O Screw Terminal Expansion Board
by Deek Robot, Keyes, & Gravitech (CHECK: some of them have the GND terminals interconnected)  You will also need to have a few small flat head screw drivers to tighten those terminals down.  Since this shield is was originally designed for an Arduino Nano many of the labels on ST board will not agree with the pins on the ‘analog side’ of the ProMini.
$1.85
DS3231 IIC RTC with 4K AT24C32 EEprom (zs-042)
Some ship with CR2032 batteries already installed.  These will pop if you don’t disable the charging circuit!  
$1.25
CR2032 lithium battery  $0.40
SPI Mini SD card Module for Arduino AVR
Buy the ones with four ‘separate’ pull-up resistors so that you can remove three of them.
$0.50
Sandisk or Nokia Micro SD card 256mb-512mb 
 Test used cards from eBay before putting them in service. Older Nokia 256 & 512mb cards have lower write currents in the 50-75mA range. This is less than half the current draw on most cards 1gb or larger.
$2.00
Small White 170 Tie-Points Prototype Breadboard
These mini breadboards for inside the logger are also available in other colors.
$0.60
20cm Dupont 2.54mm M2F 40wire ribbon cable
Dupont connector hook-up wires might be expected to add an ohm or two of resistance and carry at most 100mA reliably with their thin 28-30 gauge wires.  Each 40-wire cable will let you make at least 2 loggers.
$1.55
10cm Dupont 2.54mm M2F ribbon cable
Sometimes these 10cm cables are harder to find, so you can just use the longer 20cm wires in a pinch. 
$1.00
2×1.5V AA Battery Batteries Holder w Wire Leads
If you are running an unregulated system on 2 lithium batteries, then you can use a 2x AA battery holder. If you need to keep the regulator in place to stabilize the rail voltage for particularly picky sensors, use alkaline batteries and a 4xAA battery holder.
$0.50
5mm Common cathode RGB LED  $0.10
M12 Nylon Cable Glands (pack of 20 pcs) 
You will also need some extra rubber washers.
$0.70 /2pcs
3.3V 5V FT232 Module
  *set the UART module to 3.3v before using it!* and you will also need a few USB 2.0 A Male to Mini B cables. You may need to install drivers from the FTDI website depending on your OS. Get at least 2-3 of these as they do wear out and you can kill them instantly with a short circuit. These boards can only supply ~50mA which can be tricky if your sensors need more for sustained periods.
$2.75
3M Double-side Foam Tape, 22awg silicone wireheader pins, 3/4 inch zip Tie Mounts, etc… $1.00
Some extra tools you may need to get started:                (not included in the total above)
2in1 862D+ Soldering Iron & Hot Air station Combination
a combination unit which you can sometimes find as low as $40 on eBay.
Or you can get the Yihua 936 soldering iron alone for about $25. While the Yihua is a so-so iron, replacement handles and soldering tips cost very little, and that’s very important in a classroom situation where you can count on replacing at least 1-2 tips per student, per course, because they let them run dry till they oxidize and won’t hold solder any more.  Smaller hand-held heat-shrink guns are available for ~$15 and $5 USB soldering irons are surprisingly useable.
$50.00
SYB-46 270 breadboards (used ONLY for soldering header pins )
Soldering the header pins on the pro-mini is MUCH easier if you use a scrap breadboard to hold everything in place while you work. I use white plastic breadboards that only have one power rail on the side since I won’t mistake them for my regular breadboards. I also write ‘for soldering only’ on them with a black marker.
$1.30
SN-01BM Crimp Plier Tool 2.0mm 2.54mm 28-20 AWG Crimper Dupont JST
I use my crimping pliers almost as often as my soldering iron –  usually to add male pins to component lead wires for connection on a breadboard. But making good crimp ends takes some practice.  But once you get the hang of it,  Jumper wires that you make yourself are always better quality than the cheap premade ones.
$16.00
Micro SD TF Flash Memory Card Reader
Get several, as these things are lost easily. My preferred model at the moment is the SanDisk MobileMate SD+ SDDR-103 or 104 which can usually be found on the ‘bay for ~$6.
$1.00
Side Shear Flush Wire Cutters & Precision Wire Stripper AWG 30-20
HAKKO is the brand name I use most often for these, but there are much cheaper versions.
$5-10
Dt380 Multimeter
Dirt Cheap & good enough for most classroom uses.
$3.50
Syba SY-ACC65018 Precision Screwdriver Set
A good precision screwdriver set makes it so much easier to work with the screw terminal boards. But there are many cheaper options.
$12.00
Donation to Arduino.cc
If you don’t use a ‘real’ Pro Mini from Sparkfun to build your logger, you should at least consider sending a buck or two back to the mother-ship to keep the open source hardware movement going…
$1.00

.. and the required lithium AA batteries are also somewhat expensive, so a realistic estimate is about $25-30 for each logger when you add a couple of sensors.


Addendum:  Using a more advanced processor

After you’ve built a few ProMini based loggers, you might want to try a processor upgrade. The 1284p CPU has twice the speed & 4x the memory, but still delivers comparable sleep current / longevity.

Building an ATmega 1284p based Data Logger

In this tutorial, a logger is built using a 3.3v Moteino MEGA with a 1284p CPU @ 16Mhz, w 4K eeprom,16K SRAM for variables & 128K program space. Considerably more than the 328’s 1K eeprom, 2K ram & 32K progmem. Also has a spare serial port for GPS/NEMA sensors.

In the 2018 paper we tried to convey that it doesn’t matter which processor you use with our system as long as it’s supported by the Arduino IDE. The ATmega family includes several CPUs more capable than the humble 328p in the Pro Mini / UNO. In fact, some have suggested that the 1284 would have been a better choice right from the start, with full code compatibility once you account for the different port / pin mapping.  We built several loggers around that chip early in the project, but at the time I was mostly just leaning on the extra memory to compensate for some fairly crude programming. As my skills improved, and I stopped using bloated sensor libraries, that problem went away.  So it’s been a while since I needed anything more than the 328p. But we have a new project spinning up this year that calls for burst sampling of high-bit ADC channels, and we’ll need more SRAM to juggle that data with some fairly large buffer-arrays.

Dave’s protoboard build

For those who build from scratch, Dave Cheney shows one approach to starting with the raw chip.  At the opposite end of the spectrum, Stroud Research Center’s Mayfly is a good combination if you’d prefer something ready-made.  But I still have a a few Moteino MEGAs lying around, and this project has always followed the ‘middle path’ to enlightenment.  So we’ll use one of those boards to demonstrate how easy it is to give our classroom logger a processor upgrade:

Add Screw Terminals to the Moteino:   (click images to enlarge)

Raspberry Pi expansion terminal boards are about $1 each, use 3mm pitch blocks from Nano kits. SPLIT Nano shields also work in a pinch, but you loose A4-A7 & D19-23

20 screw terminal ports per side, OR you could solder 2.54mm blocks directly to the MEGA. But they are not as robust for multiple reconnects during prototype experiments.

The Moteno MEGA from ‘just fits’ between the rails on the Raspberry Pi adapter. The ProMini XL fits on a Nano shield – but I like having all those extra I/O pins on the MEGA to play with.

Pins on the MEGA board need to be bent ‘slightly’ to align with the header holes on the Rpi shield.

10 / 3 Meg divider to track battery voltage

This is the basic version of the MEGA, but it’s also available with flash & radio transceiver options. LowPowerLabs also sells the Current Rangeran extremely useful tool for checking the sleep current on my loggers.   The shiny surface is due to the conformal coating we put on all our components. Clear nail polish also works once you’ve cleaned all the flux.

At the time of this writing there are a few 1284  boards on the market: the Moteino MEGA , the Megabrick, the Dwee, and the ultra compact Pro Mini XL. Other projects sporting the chip seem to pop up regularly, though few  seem to last very long.  This is a shame because 1284 has enough juice to do single-chip emulation of early 8-bit computers.  But perhaps the chip never really caught on in Arduino-land because few beginners need that much capability. Sustained interest from dedicated makers means that some version, or at least DIY instructions, will will be available as long as the chip is in production. If I had to, the terminal expansion board I’ve used here would let me build one of those from the raw chip & a few passives. The trick would be making templates for the boards.txt and pins_arduino.h, and finding a bootloader that matches the system clock.

Component Prep & Logger Assembly:

Black =GND,
Purple=MISO,
Brown=CLocK,
Orange=MOSI,
Grey=CSelect,
Red=3v3

Foam tape holds the  Dupont jumpers together & provides accidental contact protection on the header pins. 3.3v system lets you connect the SD card directly

Place the SD module to one side, leaving room for wire pass-through under MEGA Board. Note:a 10k pullup on the CLocK line was removed because mode0 sleeps low

Route all but the GND wire  under the main board

Score the insulation at ~15mm, and ROLL THE INSULATION between your fingers to TWIST the thin 30AWG strands together.

Add a 5mm ‘hook’ to provide more wire under the screw terminal contacts

SD card connections:
Grey= (CS) -> D4,
Orange= (MOSI) ->  D5,
Purple= (MISO) -> D6,
Brown= (CLK) ->  D7,
Vcc 3.3v

SD power is controlled by switching the GND line with a TN0702 logic level mosfet on D0 -> After <- SPI peripheral is disabled & all SPI bus lines are pulled up.

 

 

 

Diffused common cathode RGB w GND pin bent to identify. No limit resistor is needed if you use INPUT_PULLUP to light each color channel.

Any 4 unused pins would work for the  indicator.

We add NTC thermistors to all of our builds & read them with the Input Capture unit on D14.

 

 

Attach the GND wires before putting the MEGA into the Plano 3440 stowaway box being use as a housing.

Here using 3xAA to supply the MCP1700 reg. on the MEGA. For unregulated builds, I use 2x Lithium AAs with flat discharge curves.

Blk(GND), Red(3.3v), White(SDA), Yellow(SCL), Blue(SQW)  with Dupont pin headers added to the cascade port. 32K is not used as our power-mod disables that output.

The DS3231 Vcc pin is clipped to force battery power & 1N1418 isolates the coin-cell (see end of the RTC post for details on this power-saving modification)

SCL=>D16 (yellow), SDA=>D17 (white), &
SQW =>D10 = Int0 (blue)

170 tie point breadboard completes assembly. I2C bus is tapped from the RTC modules 4-pin cascade port.

For comparison, here’s a Pro-Mini based build from 2019 . The pass-thru also provides rail & GND points.

The Moteino MEGA also makes Aref available (purple). Setting that to the internal1.1v bandgap gives you a reference voltage with thermal stability similar to a T431 provided you leave the ADC running long enough to stabilize the cap on aref & account for the internal resistance.

Now all I have is a bit of code tweaking to change the I/O in the codebase so those commands match the Moteino’s pinmap.

To complete the trim on this prototype I’ve added a 16-Bit ADS1115 (I’ll be giving that ADC a serious workout soon & will post any interesting results). Pinning the add-on module vertically preserves space on that tiny breadboard. With the ADS I won’t be using the internal ADC for much other than battery tracking. However analog pins will safely tolerate mid-range voltages which cause serious leakage problems on normal digital I/O pins. This lets you use a resistor bridge for scaled ranging techniques.

With all that extra memory to play with I’ll finally get to try some graphing libraries with that OLED – a luxury I can’t usually afford with ProMini based builds (though tiny plotter works in a pinch). And rumor has it that you can bit-bang I2C on ‘any’ GPIO pins, driving SSD1306 displays up to 10 frames per second. We have plenty of I/O lines to spare now for those experiments.

All of Atmels ‘-P’ variants have low power modes, and the logger shown here sleeps below 20μA (without the OLED, which draws ~25uA while sleeping) – that’s the about the same as I usually get with the 328p based units.  The 1284 draws more runtime current (~17mA), but you can reduce that considerably by throttling the system with a prescaler.  If you then accelerate the I2C bus by the same factor with TWBR, your sensors are  none the wiser.  In fact I’ve had no problem polling the 1115  with the system clock brought all the way down to 62.5 Khz with clock_prescale_set(clock_div_256); 

I guess the last thing on my list is a name for this beast. I had been thinking of calling it the ‘MEGA pearl’, but a quick google search convinced me otherwise. So I’m open to suggestions.

Addendum 2020-05-12:

There are also 2650 (not-P) based options between $10-$20. The board shown above has double rows, so you’re stuck using straight pin headers unless you put 0.1” terminal blocks both above AND below. Plenty of ports there for hexapods, gigantic LED displays, musical instruments, or perhaps a game of chess. It is somewhat hard to find these boards at 3.3v 8mhz.

Well that didn’t take long: a few have already pointed out that I missed the Microduino Core + in the ‘currently available’ list. I’m sure there’s more so I’ll add them if I hear about others with a physical footprint that’s small enough to work as a drop-in replacement with the student build. I skipped the 644p in the preamble, but it’s another good low-power option if you are looking for more program memory.  The 1284 is pin compatible with the 644, ATmega16, ATmega32 and probably a lot more.

Now that I’m playing with the 1284 again, I’ll also post any interesting projects I come across using these more powerful processors, such as this acoustic impulse marker or this body fat analyzer.

 


Addendum 2020-05-21:   Using the ADS1115 in Continuous Mode for Burst Sampling

As promised, here’s a first look at that ADS1115 ADC module.  For day to day tasks, it’s already something of a work-horse for Makers. But I wanted to push it out to the max settings to see if it’s ready for some typical research level applications. The answer is a tentative yes, but only at the fastest 860 sample per second speed. And with small signals EMI is more of a problem than the limitations of the ADC itself. I’m sure that’s not news to the analog hardware hackers out there, but I’m kind of a digital kid who’s still learning as I go along.

Easy 1-hour Pro Mini Classroom Datalogger [Feb 2019]

Dupont jumper variant of the “fully soldered’ Classroom Data Logger from the Cave Pearl project: This version uses dupont jumpers to reduce assembly time to about 1 hour

Note: An updated version of the classroom logger was released in 2020:  CLICK THIS LINK to view the newest build tutorial.

It’s only been a couple of weeks since the release of the 2019 EDU logger, and we’re already getting feedback saying all the soldering that we added to that tutorial creates a resource bottleneck which could prevent some instructors from using it:

“Our classroom has just two soldering stations, and the only reason there are two is I donated my old one from home. So we simply don’t have the equipment to build the logger you described. And even if we did, some of my students have physical / visual challenges that prevent them from working with a soldering iron safely…”

Or goal with that design was to give students their first opportunity to practice soldering skills that are needed when repairing kit in the field. However helping people do science on a budget is also important – so that feedback sent us back to the drawing board.  After a little head scratching we came up with a new version that combines the Dupont jumper approach we used in 2016, with this flat-box layout. In the following video, I assemble one of these ‘minimum builds’ in about one hour.  To put that in perspective, the fully soldered version takes 2 – 2.5 hours for someone with experience.

Note: After you’ve seen the video to get a sense of where you are headed, it’s usually much better to work from the photos (below) when assembling your logger. Youtube videos make it look easier than it actually is when you are just starting out. So the first one you build could take several hours as you figure out what you are doing, the second will take half as long, and the third one you make usually takes less than two hours. With some practice you can easily make 4-5 of these things a day.

This variation of the basic 3-component logger is optimized for quick assembly, so the soldering has been reduced to adding header pins and bridging the A4/A5 I2C bus to the outer terminals.  An instructor could easily do that ahead of time with about 15 minutes of prep per unit, leaving only the solder-less steps for their students. After the header pins are in place, connections to the central Pro Mini are made by simply twisting stripped wire ends together and clamping them under screw terminals.

You should use Lithium AA batteries with a 2-cell unregulated supply because the slope of an alkaline batteries discharge would bring the system down to  ProMini’s brown-out of ~2.7v when only 40% of the battery capacity has been used. (note the SD card safe down to 1.8v) While the voltage of a ‘brand new’ Lithium AA is usually 1.8v/cell, that upper plateau provides a sleeping logger voltage of ~1.76 v/cell once the batteries settle, and that briefly dips to about 1.625v/cell under load during data saves. At low temps of about 5°C (in my refrigerator) those SD card voltage dips go down to about 1.525 v/cell. Unloaded readings of 1.5v on a Li AA = battery is dead.

This time reduction involves a few trade-offs, and bringing the I2C bus over to A2 & A3 leaves only two analog ports readily accessible ( although A6 & A7 are still available if you add some jumpers). Removing the regulator & battery voltage divider adds ~30% more operating life, but it also forces you to deal with a changing rail voltage as the Lithium AA batteries wear down. The daily variation is usually quite small, but for quantitative comparisons on monthly scales you will need to correct for the change in rail voltage over time if your sensor circuits are not ratio-metric. To do this voltage compensation multiply your raw sensor readings by the the ratio of (3300mv) / (current rail voltage).  Here 3300mv is just an arbitrary comparison point, which you could replace with any rail voltage reading from the data saved by your logger. Batteries have a lot of mass, so thermal lag in battery voltage can also cause hysteresis for analog temperature sensors unless you read the reference under the same conditions.

 (NOTE: complete parts list with supplier links are located at the end of this post)

Pro Mini Prep:

Solder the UART pins & test ProMini board with the blink sketch:  Set the IDE to (1) TOOLS> Board: Arduino Pro or Pro Mini (2)TOOLS> ATmega328(3.3v, 8mhz) in addition to the (3)TOOLS> COM port to match the # that appears when you plug in the serial adapter board.

Once you know you have a working Promini board: Remove the power LED [in red]. Removing the pin13 LED [yellow square above] is optional. Leaving the pin13 LED in place lets you know when data is being saved to the SD card because the SPI bus SClocK signal flashes the LED.

Remove the voltage regulator with snips. Your system voltage will vary over time, but our starter script records that rail voltage without a voltage divider.

Add pin headers to the sides & Serial input end of the Pro Mini.

Bridge the two I2C bus connections for side access with the leg of a resistor. Connect A4->A2 & A5->A3.

Adding DIDR0 = 0x0F; in Setup disables digital I/O on pins A0-A3 so they don’t interfere with I2C bus coms.

NOTE: The Screw Terminal board we use in this build was designed for the 5v Arduino NANO, so the shield labels don’t match the actual 3.3v Pro Mini pins on the ‘analog’ side. (the digital side does match) To avoid confusion may want to tape over those incorrect labels and hand write new labels to match the pattern above. Wire connections in this tutorial will be specified by ProMini pin labels:  D10-13 are used for the SD card, A4=A2 is the I2C Data line, and A5=A3 is the I2C clock line, A0 & A1 are not used.

Technically speaking, bridging the I2C bus (A4=data & A5=clock) over to A2 & A3 subjects those lines to the pin capacitance and input leakage of those analog pins (regardless of whether that channel is selected as input for the ADC p257). But in practice, the 4K7 pull-up resistors on the RTC module can easily handle that at the 100 kHz default bus speed. Adding DIDR0 = 0x0F; in setup disables digital I/O on pins A0-A3 to prevent interference with the I2C bus. If you want to disable the IO on A2 & A3 ‘only’ add bitSet (DIDR0, ADC2D); bitSet (DIDR0, ADC3D); to your code.

Also note: On the UART adapter in the picture above, the USB to TTL adapter pins are in the reverse order to the Pro Mini board. This is a fairly common issue with clones and if the blink sketch never uploads flip the adapter around and try again. I have connected 3.3v ProMinis to UART modules the wrong way round many, many times, and not one of them has been harmed by the temporary reversal.

Screw-Terminal Component Stack:

Add 3 layers of double sided tape so the tape is thicker than the solder pins.

Align RX&TX corner pins before inserting. The GND points on the screw terminal board may be interconnected (via the back-plane) & must match the ProMini’s GND pins.

Gently rock the Pro Mini back to front (holding the two short sides) until the pins are fully inserted. Some ST shields have mis-aligned headers so this insertion can be tricky.

Remove the last three ‘unused’ pin headers to make room for the SD adapter

Note: Screw-terminal board labels do not match the ProMini pins on the ‘analog’ side

Remove bottom 3 resistors from the adapter – leave the top one in place!

Separate Dupont Cable wires & click them into a 6-pin shroud.

Cable Color Pattern:     Black =GND,   Purple=MISO,   Brown=CLocK,   Orange=MOSI,   Grey=CSelect,      and   Red=3v3

 

 

 

Use foam tape to attach SD module to the Screw Terminal board. Metal tabs should be visible on top surface.

Measure, cut & strip the 4 SPI bus wires (NOTE the ‘Nano’ ST board labels say A0-A3 which does not match the D10-13 Pro Mini pins on this side of the board)

Grey (CS) to ProMini D10Orange (MOSI) -> pm D11,      Purple (MISO) ->pm D12,        Brown (CLK) -> pm D13    

 

 

Add three jumper wires to the red power line from the SD module, one with a male end pin. I often add Dupont ends with a crimping tool, rather than using a pre-made jumper.

Strip & twist the 4 red power wires together & add heat-shrink for strain relief. Bundling wires like this is easier if you make the stripped area a bit longer.

A short red jumper goes to RAW(pm)=VIN(st) to recruit the orphan capacitor.

Long red jumper bridges power to ‘unused’ screws on other side of the Terminal board, and the wire with the Dupont male end will go to the breadboard.

Add 2 extra wires to the black GND wire from the SD module (1 with a male Dupont end ). Jumper one black wire across the Promini to an unused terminal beside the red power wire.

The GND bundle completes Pro Mini / ST board / SD module stack. The ‘pinned’ Red & Black ‘pinned’ jumpers shown here are about 1 inch too short to reach the breadboard easily… make yours longer.

Note: You could connect the battery holder lead wires directly into the multi-wire Vcc & GND bundles: skipping the 2 jumpers crossing over to the other side of the ST shield.  But adding those jumpers provide extra Vcc/GND connection points & the ability to easily replace the battery holder later if you have a battery leak.

I always try to make my Dupont connectors so that the metal & plastic retainer clips are accessible (in this case facing upwards) after the logger is assembled. That way you can diagnose bad wire connection with the tip of a meter probe, and if necessary, pull out & replace a single bad wire in the Dupont connector without taking everything apart.

RTC module:

Remove two SMD resistors from the RTC board with the tip of your soldering iron.

The DS3231 modules often have flux residue – clean this off with 90% isopropyl.

 

Cable: Blk(gnd), Red(vcc), White(sda), Yellow(scl), Blue(sqw).  Shroud retainer clips face up & there is no wire on 32K output.

First tape layer

Next two tape layers

OPTIONAL: adding header pins to the cascade port provides a convenient attachment point for I2C sensors later.

Optional: After removing the two SMD resistors on the module, you can clip the Vcc leg on the RTC chip which forces the clock to run entirely from the backup coin-cell battery. This reduces the loggers overall power use by 0.09mA bringing a “no-reg & noRTCvcc” build below 0.1mA when the logger sleeps between sensor readings (this should run for more than 2 years on fresh lithium AA cells) . But the risk is that if you bump the RTC backup battery loose, that disconnection resets the clock time to Jan 1st, 2000. (note: while the time stamps will be wrong after that kind of reset, the logger will continue running after the next hour/min alignment occurs with the ‘old’ alarm time)   A couple of pieces of soft 1.6mm heat shrink tubing under the spring makes the negative coin-cell connection stronger, an a touch of hot melt glue will secure the battery on the top edges.  A CR2032 can power the RTC about four years but you have to set bit six of the DS3231_CONTROL_REG to 1 to enable alarms when running from the coin-cell. (our starter code does this by default) This modification also disables the 32.768 kHz output pin on the RTC.  Visit our RTC page for more detailed information on this clock module.

Final Assembly:
(Note: references here are to pin numbers/labels on the ProMini which do not match ST board labels on the analog side)

Attach the Pro Mini stack & RTC to housing with the double-sided tape.

Trim white & yellow I2C wires from the RTC & add 1 extra wire with dupont ends for each I2C line to bring the bus over to the breadboard

Attach yellow SCL line from the RTC beside the red 3v rail (ie to A3=A5 on the ProMini) then the white SDA line from the RTC to A2=A4.

The four extra jumper wires with male Dupont ends on Vcc, GND, & both I2C lines. These get patched over to the breadboard so you can add I2C sensors.

Each wire must be plugged into its own separate vertical column on the breadboard. Add a 2nd layer of foam tape to the bottom of the bread-board before attaching.

The RTC power line joins that short red jumper on RAW(pm)=VIN(st) at the end of the screw-terminal board.

Some of the box bottoms have slight bowing. If any component doesn’t stick well enough: add another layer of foam tape.

Attach the RTC’s black ground wire to GND & the blue SQW alarm line to ProMini pin D2

Attach 2xAA battery holder with 2 layers of foam tape. Trim wires to length. Use black 30lb Mounting Tape for extra strength.

Battery wires join the black & red jumpers from other side of the terminal board. All six of the ‘unused’ screw terminals we clipped earlier can be used to make secure ‘dry wire’ connections in this way.

Connections complete except the indicator. 5050 LED modules often come with pre-installed limit resistors which make them safer for the classroom. But you can use a raw 5mm LED if you only light the LED  with the INPUT_PULLUP command.

A ‘common cathode’ RGB LED module on pins  Red=D6, Green=D5,   Blue=D4, &  GND=D3.

Your Logger is ready for testing!

(Note: Most of the time the tests listed below go well, however if you run into trouble at any point read through the steps suggested for Diagnosing Connection Problems at the end of this page.)

Install the Arduino IDE into whatever default directory it wants to be in – we’ve had several issues where students tried to install the IDE into some other custom sub-directory, and then code will not verify without errors because it doesn’t know where to look for libraries. If you have not already done so, there are three things you need to set under the IDE>TOOLS menu to enable communication with the logger:

Note: that the “COM’ setting will be different for each computer, so you will have to look for the one that appears on your system AFTER you plug in the UART module.

The one that’s easy to forget is choosing the 328P 3.3v 8Mhz clock speed. If you leave the 328p 5v 16mhz (default), the programs will upload OK, but any text displayed on the serial monitor will just be a random bunch of garbled characters because of the clock speed mismatch.  Also be sure to disconnect battery power (by removing one of the AA batteries) whenever you connect your logger to a computer.

1. Test the LED – Edit the default blink sketch, adding commands in setup which set the digital pin 3 connected to the ground line of the LED to “OUTPUT” and “LOW”
      pinMode(3, OUTPUT);   digitalWrite(3, LOW); 
Since we removed the ‘default’ indicator led on the Pro Mini board, you will also need to change LED_BUILTIN variable in the blink code example to one of the pins connected to one of the color channels on your led module. (in this example change LED_BUILTIN to either 4, 5, or 6)

2. Scan the I2C bus with the scanner from the Arduino playgound. The RTC module has a 4K eeprom at address 0x56 (or 57) and the DS3231 RTC should show up at address 0x68.

The address of the eeprom can be changed via solder pads on the board, so sometimes it moves around. If you don’t see at least these two devices listed in the serial monitor when you run the scan, there is something wrong with your RTC module or the way it’s connected: It’s very common for a beginner to get at least one set of wire connections switched around during the assembly. With the screw terminals this takes only a few moments to fix. Also have a spare RTC module on hand in case you get a defective module…which is fairly common.

NOTE: Some sensors really need the stability provided by the on-board voltage regulator. Here is an alternative arrangement of parts for the classroom logger that leaves the 3.3v regulator in place on the ProMini and powers the logger from 4xAAA alkaline batteries (NOTE: regulated builds also leave out the short red jumper that was used to recruit the orphan capacitor after the reg was clipped.  The RTC & added sensors now get connected ONLY to the Pro-Mini’s regulated 3.3v rail )   We’ve designed the Cave Pearl Logger for maximum flexibility, so you can easily change components and positions like this to suit the needs of your design / experiment.

3. Set the RTC time, and check that the time was set – The easiest method would be to use the SetTime / Gettime scripts from our Github repository, but first you need to download & install this RTC control library  The SetTime script, automatically updates the RTC to the time the code was compiled (just before uploading) so you only run SetTime once, and then immediately upload the GetTime sketch to get the SetTime code out of memory after it’s done it’s job. Otherwise SetTime will reset the RTC to the ‘code compile time’  every time the Arduino restarts (and the Arduino restarts EVERY TIME you open the serial window…) 

There are dozens of other good Arduino libraries you could use to control the DS3231, and there is also a script over at TronixLabs.com that lets you set the clock without installing a library. [ in 24-hour time, & year with two digits eg: setDS3231time(30,42,21,4,26,11,14);  ] The trick with Tronix’s “manual” method is to change the parameters in the line: setDS3231time(second, minute, hour, dayOfWeek, dayOfMonth, month, year);  to about 2-3 minutes in the future, and then upload that code until about 20 seconds before your computers clock reaches that time (this compensates for delay caused by the compilers processing & upload time). Open the serial window immediately after the upload finishes, and when you see the time being displayed (and it’s not too far off actual…) upload the examples>blink sketch to remove the clock setting program from memory.

Another option would be to try setting the clock’s time using one of the serial window input utilities from Github.

4. Check the SD card is working with CardinfoChanging chipSelect = 4; in that code to chipSelect = 10;  Note that this logger requires the SD card to be formatted as fat16, so most 4GB or larger High Density cards will not work because they get formatted as fat32. Most loggers only generate 5 Kb of CSV format data per year when they are running, so you don’t need a big SD card. In fact older, smaller SD cards in the 256-512mb range often use less power if it’s a good name brand like Sandisk or Nokia.

Zip-Tie Mounting Bases are an easy way to add attachment points inside your logger to secure sensor cables, or desiccant packs. These adhesive cable tie mounts come in many varieties, and cost about 10¢ each at most hardware stores.

5. Optional: If you are running with no regulator & using analog sensors: Calibrate your internal voltage reference with CalVref from OpenEnergyMonitor.

This logger uses an advanced code trick to read the positive rail voltage to ~11mv resolution by comparing it to an internal 1.1v reference  inside the processor. That internal ref. can vary by ±10% from one chip to another, and CalVref gives you a constant which will make the rail=battery voltage reading more accurate. Load CalVref while the logger is running from USB power and then measure the voltage between GND and the positive rail with a good quality voltmeter. (this voltage will vary depending on your computer’s USB output, and the UART adapter you are using) Then type that voltage into the serial monitor window entry line & hit enter. Write down the reference voltage & constant which is output to the serial monitor window. I usually write these ‘chip-specific’ numbers inside the logger with a black sharpie. You will need to add that info to the core data logger code later by changing the line #define InternalReferenceConstant 1126400L to match the long number returned from CalVref. Alternatively you could just tweak the value of the constant ‘by hand’, increasing or decreasing the value till the reported rail readings match what you see with a voltmeter. After you’ve done this once or twice you can usually get within 15mv of actual with about 10 trials.

This calibration brings the starter script’s battery readings within ±15mv of actual but you can skip the CalVref procedure if you are only using digital sensors, as the script will still produce reasonably good battery readings with the default 1126400L value. Increasing the rail reading accuracy is more important when you are using ANALOG sensors which use that rail voltage to drive your sensors – so the +ive rail directly affects their output if you are not reading a ratiometric circuit.

6. Find a script to run your on logger. For test runs on a USB tether, the simplest bare-bones logger code is probably Tom Igoe’s 1-pager at the Arduino playground. It’s not really deploy-able because it never sleeps the processor, but it is still useful for teaching exercises and testing sensors after you set chipSelect = 10;  In 2016 we posted an extended version of Tom’s code for UNO based loggers that included sleeping the logger with RTC wakeup alarms. Our latest logging “Starter Script” has grown in complexity to ~750 lines, but it should still be understandable once you have a few basic Arduino programming concepts under your belt.

After 1-2 minutes of kneading to mix the epoxy you have ~ 60 seconds to work the putty into place. (it will become rock-hard within ~5-10 minutes). Be sure to leave yourself enough extra wire/space inside the housing so that you can open and close the lid easily without disconnecting anything after the putty hardens. This seal is not strong enough for underwater deployments, but it should easily withstand exposure to rain-storm events. This putty is also a quick way to make custom mounting brackets, or even threaded fittings if you wrap it around a bolt (which you carefully remove before the putty hardens completely)

In the previous tutorial we attached external sensors with a cable gland passing through the housing and epoxying them into a pvc cap.  Cheap cable glands are notoriously unreliable and I always add a second rubber oring on the inside – and often over-seal the outside with  conformal coating. But for a simpler classroom project you could simply drill small a hole through the lid and stick the sensor/module on top of the housing, seal the hole with double-sided tape. Thicker pass-through wires can be sealed reasonably well with plumbers epoxy putty from the hardware store. This putty is non-conductive, and adheres quite well to both metal & plastic surfaces. 

Remember that breadboard connections are very easy to bump loose, so once you have your prototype circuits  working, its usually best to re-connect the sensors directly to the screw terminals before deploying a logger where it could get knocked about. In a pinch you can secure breadboard pins with a ‘tiny’ drop of hot glue to keep them from wiggling around.

There is no power switch on the loggers, which are turned on or off via the battery insertion. Use a screwdriver, or some other tool, when removing the batteries so that you don’t accidentally cause a series of disconnect-reconnect voltage spikes which might hurt the SD card.

Using the logger for experiments:

Logger mounted on a south-facing window and held in place with double sided tape. Here the top surface of the housing was covered with two layers of white label-maker tape to act as a light diffuser. PTFE is another excellent light diffusing material available in different sheet thicknesses.  The ‘divot’ on the lid of the Plano box is just a bit larger than 55mm x 130mm x 3mm (depth). The “teflon” tape that plumbers use to seal threaded joints can also be used in a pinch. PTFE introduces fewer absorbance artifacts than other diy diffusers like ping-pong balls, or hot melt glue. Most light sensors like the TSL2561 need 3-5mm of that PTFE sheeting to prevent the sensors from saturating in full daylight. LED’s don’t saturate that badly, but you still lose all the useful detail in your data at peak brightnesses > 80,000 lux unless you add a diffusion layer to attenuate the light.

Many types of sensors can be added to this logger and the RTC has a built-in temperature register which automatically gets saved with our starter script. The transparent enclosure makes it easy to do light-based experiments. Diodes, LED’s & solar panels are basically the same device. So grounding the indicator LED through a digital pin allows it to be used as both a status light, and as a light sensor.   The human eye is maximally sensitive to green light so readings made with that LED channel approximate a persons impression of overall light levels.  Photosynthesis depends on blue and red light, so measurements using LED’s that detect those two colors can be combined for readings that compare well to the photosynthetically active radiation measurements made with “professional grade” sensors. In fact Forest Mimms (the man who discovered the light sensing capability of LEDs in the first place) has shown the readings from red LED’s can be used as a reasonable proxy for total PAR.  Photoperiod measurements have important implications for plant productivity, as do  measurements of transmittance through the plant canopy. Chlorophyll fluorescence is another potential application, and the response of plants to UV is fascinating.

The original code for using LEDs as sensors is from the Arduino playground. This polarity reversal technique does not require the op-amps that people typically use to amplify the light sensing response but it does rely on the very tiny parasitic capacitance inside the LED. (~50-300pF) This means that the technique works better when the LED is connected directly to the logger input pins rather that through the protoboard (because breadboards add random capacitance) . Another thing to watch out for is moisture condensation inside your logger housing: this provides an alternate discharge path for the reverse-charge on the LED, which effectively shorts out the light level reading.

We have integrated this into the starter script which you can download from GITHUB. I’ve tweaked the playground version with port commands so the loop execution takes about 100 clock cycles instead of the default of about 400 clock cycles.  The faster version was used to generate this light exposure graph with a generic 5mm RGB LED, with a 4k7Ω limiter on the common ground which was connected to pin D3:

Red, Green & Blue channel readings over the course of one day from the indicator LED in the logger photo above.  The yellow line is from an LDR sensor the same unit, that was over-sampled to 16-bit resolution. The LED sensor has a logarithmic response and the left axis on the graph is a time- based measurement where more light hitting the LED sensor results in a lower number. Note how the RED signal changes more quickly than Blue & Green at sunrise & sunset.  LED’s work well with natural full-spectrum light, but their limited frequency sensing bands can give you trouble with the spectral distribution of  indoor light sources. The peak spectral response of LED’s is usually around 30–50nm lower than their peak emission wavelength So the blue channel is actually recording in the near-UV range, the Green channel is responding at ~ 420nm (blue) and the red channel is actually responding to a wide band of yellow-green light. 

Characterizing light absorption and re-emission is also a primary technique in climate science . For example, measuring light intensity just after sunset with LEDs inside a heat-shrink tube pointed straight up can provide a measure of suspended particles in the stratosphere. An “ultra bright” LED has more than enough sensitivity to make these columnated readings, in fact on bright sunny days you usually have to place the LED/sensor beneath a fair thickness of white diffusing material (like PTFE tape) to prevent it from being completely saturated.  Older LEDs that emit less light can sometimes be easier to work with because they are less sensitive, so the discharge time does not go to zero in high-light situations. Other sensor experiments are possible with LED’s in the IR spectrum which can be used to detect total atmospheric water vapor. A light transmission-based variant of the NDVI ratio can be used to determine plant health after adding an IR LED to the logger.

Of course, full sun exposure can also cook your little logger: temps above 80°C may cause batteries to leak or damage the SD card. If you have to leave the logger in full sun, add a bit of reflective film or a layer of aluminum foil around the outside to protect the electronics. Though if use a light sensor you’ll need to leave a little un-covered window for it to take a reading. 

You might also find it handy to add a few holes to the Plano box as tie-down points:

and it’s always a good idea to add desiccant packs inside the box to prevent condensation. If you use a desiccant with color indicator beads, you can check whether they are still good simply by looking through the transparent housing.

If you clipped the RTC leg, your logger should pull less than 0.1mA while sleeping. Back of the envelope for Lithium AA’s is about 7 million milliamp-seconds of power, with your logger burning about 8600 mAs/day at 0.1mA.  So clipping the voltage regulator and cutting the vcc leg on the RTC should easily get you out to about a year before you fall off the “upper plateau” of the lithium burn-down curve, and more likely to ~two years if your sensors don’t use much power (…and you have a well behaved SD card).  With the RTC power leg still attached you’ll see sleep currents in the 0.18-0.22 mA range, so at least 6 months of operation before you come close to triggering the low voltage shutdown (which is embedded in the logger code). I’m being conservative here because it all depends on your sensors and other additions you make to the base configuration. For every type of sensor the market, there will be some brands that draw much less power than others, and it’s always worth a look at the data sheet to make sure you are buying one that will run longer on a given set of batteries. Good sensors automatically go into a low current sleep mode whenever the bus has been inactive for a period of time.

While the LED sensor idea is fun to work with, it’s a very slow method that keeps the logger running for many seconds per reading when light levels are low -> so reading all three color channels will probably cut your operating life in half again. Figuring out how to only take those light readings during the day is a good coding exercise for students that saves quite a bit of power. The RTC’s temperature record is pretty crude, so we’ve also added support for the DS18b20 temperature sensor in the base code. If you have a genuine DS18b20 (yes, crummy fake knock-off sensors are a thing) , these venerable old temperature sensors draw virtually no power between readings.


TransparentSinglePixl
Bill of Materials: $20.50
Plano 3440-10 Waterproof Stowaway Box
Sometimes cheaper at Amazon. $4.96 at Walmart and there are a selection of larger size boxes in the series. 6″ Husky storage bins are an alternate option.
$5.00
Pro Mini Style clone 3.3v 8mHz
Get the ones with A6 & A7 broken out at the back edge of the board. Just make sure its the 3.3v version because you can’t direct-connect the SD cards to a 5v board.
$2.20
‘Pre-assembled’ Nano V1.O Screw Terminal Expansion Board
by Deek Robot, Keyes, & Gravitech (CHECK: some of them have the GND terminals interconnected)  You will also need to have a few small flat head screw drivers to tighten those terminals down.  Since this shield is was originally designed for an Arduino Nano many of the labels on ST board will not agree with the pins on the ‘analog side’ of the ProMini.
$1.85
DS3231 IIC RTC with 4K AT24C32 EEprom (zs-042)
Some ship with CR2032 batteries already installed.  These will pop if you don’t disable the charging circuit!  
$1.25
CR2032 lithium battery  $0.40
SPI Mini SD card Module for Arduino AVR
Buy the ones with four ‘separate’ pull-up resistors so that you can remove three of them.
$0.50
Sandisk or Nokia Micro SD card 256mb-512mb 
 Test used cards from eBay before putting them in service. Older Nokia 256 & 512mb cards have lower write currents in the 50-75mA range. This is less than half the current draw on most cards 1gb or larger.
$2.00
Small White 170 Tie-Points Prototype Breadboard
These mini breadboards for inside the logger are also available in other colors.
$0.60
Dupont 2.54mm F2F 40wire ribbon cable Without Housing
Cheaper if you get the ones with the black plastic shrouds on the ends. Dupont connector hook-up wires might be expected to add an ohm or two of resistance and carry at most 100mA reliably with their thin 28-30 gauge wires. Poorer quality crimped ends can add significant contact resistance. Each 40-wire cable will let you make at least 2 loggers, and you”l need a couple of  6-pin connector shrouds.
$1.55
2×1.5V AA Battery Batteries Holder w Wire Leads
If you are running an unregulated system on 2 lithium batteries, then you can use a 2x AA battery holder. If you need to keep the regulator in place to stabilize the rail voltage for particularly picky sensors, use alkaline batteries and a 4xAA battery holder.
$0.50
5050 LED module (with built-in limit resistors) 
(Alternatively, you can also use cheaper 5mm diffused LEDs with a  4K7 limit resistor on the GND line – that you solder into place on the LED yourself)  
$0.75
3.3V 5V FT232 Module
  *set the UART module to 3.3v before using it!* and you will also need a few USB 2.0 A Male to Mini B cables. You may need to install drivers from the FTDI website depending on your OS. Get at least 2-3 of these as they do wear out and you can kill them with a short circuit. These boards can only supply about 50mA which can be tricky with sensors that draw more than that.
$2.75
3M Dside Mounting Tape, 22awg silicone wireheader pins, etc… $1.00
You might need some extra tools to get started:                (not included in the total above)
2in1 862D+ Soldering Iron & Hot Air station Combination
a combination unit which you can sometimes find as low as $40 on eBay.
Or you can get the Yihua 936 soldering iron alone for about $25. While the Yihua is a so-so iron, replacement handles and soldering tips cost very little, and that’s very important in a classroom situation where you can count on replacing at least 1-2 tips per student, per course, because they let them run dry till they oxidize and won’t hold solder any more.  Smaller hand-held heat-shrink guns are also available for ~$15.
$50.00
SYB-46 270 breadboards (used ONLY for soldering header pins )
Soldering the header pins on the pro-mini is MUCH easier if you use a scrap breadboard to hold everything in place while you work. I use white plastic breadboards that they only have one power rail on the side since they do not look like regular breadboards &  I write ‘for soldering only’ on them with a black sharpie to make sure I don’t get the heat-damaged boards mixed up with the good ones.
$1.30
SN-01BM Crimp Plier Tool 2.0mm 2.54mm 28-20 AWG Crimper Dupont JST
I use my crimping pliers almost as often as my soldering iron –  usually to add male pins to component lead wires for connection on a breadboard. But making good crimp ends takes some practice.  Once you get the hang of it,  Jumper wires that you make yourself are always better quality than the cheap premade ones.
$16.00
Micro SD TF Flash Memory Card Reader
Get several, as these things are lost easily. My preferred model at the moment is the SanDisk MobileMate SD+ SDDR-103 or 104 which can usually be found on the ‘bay for ~$6.
$1.00
Side Shear Flush Wire Cutters & Precision Wire Stripper AWG 30-20
HAKKO is the brand name I use most often for these, but there are much cheaper versions.
$5-10
Syba SY-ACC65018 Precision Screwdriver Set
A good precision screwdriver set makes it so much easier to work with the screw terminal boards.
$12.00
Donation to Arduino.cc
If you don’t use a ‘real’ Pro Mini from Sparkfun to build your logger, you should at least consider sending a buck or two back to the mother-ship to keep the open source hardware movement going…so more cool stuff like this can happen!
$1.00

When a finished module with 20 sub-components arrives at your doorstep for less than you’d pay for any one of those components individually, then the tradeoff is that you are the quality control.

.. and the required lithium AA batteries are also somewhat expensive, so a realistic estimate is about $25 for each logger before you add sensors & tools.

My advice is to order at least 5-6 of each of the core components (Promini, RTC, SD module, screw terminal board, etc) with the expectation that about 10-20% of any cheap eBay modules will be DOA due to some quality control problem. I build loggers in batches of six, and one unit typically ends up with a bad part somewhere. Having replacement parts on hand is your #1 way to diagnose and fix these issues. I’ve noted over the years that bad parts tend to come “in bunches”, so if you scale up to ordering in quantities of 10’s & 20’s then spread those orders to a few different suppliers so you don’t end up with all your parts coming from the same flakey production run. 

The other thin I can’t stress enough is CLEAN ALL THE PARTS as soon as they arrive. Leftover flux is very hygroscopic, and pretty much guarantees that solder joints will start to corrode the moment your logger gets exposed to any atmospheric moisture. So I usually give everything about 10 minutes in a cheap sonic bath with 90% isopropyl alcohol, rinse with water, and then dry the parts out in front of a strong fan for an hour. Store parts in a sealed container with a dessicant pack till you need them.  I clean parts that can’t take the sonic vibration (like RTC modules, humidity sensors, accelerometers, etc) by hand with cotton swabs. Then I coat everything I can with a layer of MG Chemicals 422B Silicone Conformal Coating and let that dry for a day before assembling the loggers.  One hint that you have moisture issues is that the sensors seem to run fine in the house but start to act weird when you deploy the unit outside.

Used nut containers make excellent “dry storage” once the parts have been cleaned – but any air-tight container will do.

Another insight I can offer is that the quality of a sensor component is often related to the current it draws – if your ‘cheap module’ is pulling much more power than the data sheet for that sensor indicates, then it’s probably a junk part. If the sleep current is on spec, then your part is probably going to work OK. It is much easier to check low current devices with at Ucurrent or a Current Ranger.  Keep in mind that sensors which automatically go into low current sleep modes usually take some time to do so after the bus has gone quiet – so you might need to watch the sleep current for 30 seconds or more before they fall down into their quiescent state. With SD cards, if the throughput drops below the typical write speed for that model with H2testw, then you should just find another card to use with your logger.

I strongly recommend that you build at least two loggers at a time, because that lets you isolate whether problems you run into during testing are code related (which will always affect both machines the same way) or hardware related. (which will usually only affect one of your two units) At any given time I usually have 2-3 units running overnight tests so that I can compare the effect of two different code/hardware changes the next morning.  As a general rule you want to run a new build for at least a week before deploying it to make sure you’ve made it past any ‘infant mortality’, and moved onto the good part of the bathtub curve.


Addendum: Diagnosing Connection Problems

If you loaded the blink sketch to test the Prominin during your initial assembly, you know that part of the logger is working, so issues during the testing stage are due to incomplete connections from the outside to the Promini I/O ports. Before you start your troubleshooting it’s worth remembering that after you’ve built a few of these units you can simply rebuild the whole logger in about a hour. So it really doesn’t make sense to spend much more time than that – especially when a few five-minute part swaps are likely to fix the problem. The  components are only worth a couple of bucks each, and your time is more valuable than that!

This is the connection pattern inside the white breadboard. Take care that you don’t connect the breadboard jumper wires together by accidentally plugging them in to the same row or – the I2C bus will stop working. NEVER CONNECT the GND & 3.3v wires or the short circuit will likely kill your logger, and possibly even the computer they are connected to . . .

If you see only “Scanning I2C….. ” but nothing else appears when running the bus scanner, then it means that the ProMini can not establish communication with the RTC module. The most common cause of this problem is that the white & yellow wires were switched around at one end or the other. It’s also easy to not quite remove enough insulation from the wires to provide a good electrical connection under the screw terminals, so undo those connection and check that the wires were stripped, cleaned & wrapped together ‘clean’ before being put under the  terminals. Those screws need to be clamped down relatively tight on the thin Dupont wires and if you are not careful, you might have accidentally cut away some of the thin copper wires inside the Dupont cable when you stripped the insulation.

Scanner lockup can also happen if one of the I2C devices on the bus is simply not working: usually about 1 in 6 logger builds ends up with some bad component that you have to identify by process of elimination. (These are 99¢ parts from eBay…right?) It only takes a moment to swap in a new RTC board via the black Dupont connector and re-run the scan. If the replacement RTC also does not show up with the I2C scanner then it’s likely that one of the four bus lines does not have a complete connection between the ProMini & the RTC module.

On this unit I measured 1 ohm of resistance on the I2C clock line between the ProMini A5 pin (on top of the board) and the SCL header pin on the RTC module. So this electrical connection path is good. It’s not unusual for each ‘dry’ connection to add 0.5-1 ohm of resistance to a signal path.

To diagnose this: set a multi-meter to measure resistance and put one probe lead on the topmost point of the promini header pins, and the other probe on the corresponding header pin of the RTC module. If there is a continuous electrical connection between the two points then the meter should read one ohm or less. Higher resistances mean that you don’t have a good electrical path between those points even if they look connected:

1) the ground (black) wire should provide a continuous path from the ground pin on the digital side of the Promini board to the GND pin on the RTC module
2) the positive power (red) wire should provide a continuous path from the Promini positive rail pin (the one with the bundle of 4 red wires) to the VCC pin on the RTC
3) A4 (I2C data) near the 328P chip on the Promini must connect all the way through the screw terminal board and through the white Dupont wires to the SDA post on the RTC
4) A5 (I2C clock) beside A4 on the Promini must connect through through the yellow Dupont wire to the SCL header pin on the RTC .

For ‘single-wire’ connections under the screw terminal with those thin dupont wires, strip enough insulation that you can ‘fold-back’ some extra wire to give the terminal more wire to bite onto.

You occasionally get a bad Dupont wire where the silver metal end is not in contact with the  copper wire inside because the crimp ‘wings’ folded over plastic insulation. With a pair of tweezers, you can ‘gently’ lift the little plastic tab on the black shroud holding the female Dupont ends in place, and then replace any single bad wire. Be careful not to break the little black tab or you will have to replace the entire shroud.

Also look at the little jumpers used to bridge the A4>A2 and A5>A3. If you have a ‘cold’ solder join, or an accidental bridge connection to something else, it could stop the bus from working. Remelt each connection point one at a time, holding the iron long enough to make sure the solder melts into a nice ‘liquid flow’ shape for each solder point.

A note about I2C sensors: The I²C bus is slow, so topology (star, daisy-chain, etc.) doesn’t matter much, but capacitance does. Length and number of devices increase capacitance. If you find that the devices work when you switch to a slower speed (e.g. 50 kHz), then this is probably your issue, and you need to minimise bus length and/or maybe decrease the combined resistance of the pull-ups to 2 kΩ or less. The DS3231 RTC module has 4k7 ohm pull-up resistors on the SDA & SCL lines & the Pro Mini adds internal 50k pull ups when the wire library is enabled. Typical I2C sensor modules usually add another 10k so your ‘net pullup resistance’ on the I2C bus wires is usually:  50k // 4k7 // 10k = ~3k. With a 3.3v rail that means the devices draw 3.3v / 3k = 1 mA during communication which is fairly normal ( 3mA is max) for total wire lengths below 1m. It’s  common for pre-packaged sensors to arrive with housings at the end of about 1m of wire. If each sensor also adds another set of 10k pullups, the resistance generally compensates for the extra wire length, so the combination still works OK. But that depends on the cable too. A very bad cable might not even get to 0.5 meters and a very good cable (little capacitance to ground, no crosstalk between the wires) can go up to 6 meters.

The connection diagnosis procedures described above also apply to the connections for the SD adapter board. Sometimes you end up with an adapter that has a defective spring contact inside the SD module, but the only way to figure that out is to swap it with another one.

Here a jumper wire from the Promini pins is by-passing a bad connection.  This is also how you would break out A6 & A7 connections if you need them.

Sometimes those screw terminal boards have a a poor connection inside the black female headers below the Promini. It’s also possible to accidentally over-tighten a terminal and ‘crack’ the solder connection below the board – or there may simply be a cold solder joint on one of the terminal posts. If you have only one bad connection, you can jumper from the Promini header pins on top, down to the other wires under the corresponding screw terminal. If you accidentally strip the threads on a screw terminal, you can use this same approach but move that set of wires over to one of the three ‘unused’ screw terminals at the far end of the board. (beside the SD card adapter) If you’ve gotten through all of the above steps and still have not fixed the problem, then it might be time to simply rebuild the logger with a different screw terminal adapter board.

 

Also note: The environment is written in Java, and the IDE installer comes with its own bundled Java runtime, so there should be no need for an extra Java installation. However we have seen machines in the past which would not compile working code due until Java was updated on those machines; but this problem is rare. More likely some permission limitation meant that you’ve ended up installing the IDE in a directory other than the default, and now it can’t find its libraries.


Addendum 2020-02-02:  Refining the build

The ‘solderless’ classroom build includes a breadboard for flexibility, but if you are building a logger for a single sensor application you can leave out the breadboard, and add some under board jumpers to avoid those finicky multi-wire bundles:

Using the tined leg of a resistor to add some under-board connections to give you more 3.3v & GND attachment points. Clean any residual solder flux thoroughly!

To repurpose those  screw terminals, leave the corresponding pins un-soldered so they can be  removed.

 

Here, we are repurposing the TX, RX, & RST terminals as GND connections. DO not repurpose TX & RX if you need serial comms with NEMA sensors like GPS.

Use a Black marker to label the repurposed GND points. NOTE: The GND-labeled terminals can not be repurposed because they are bridged via the back plane of the screw terminal board itself.

Label the connections with red. NOTE: ONLY join the Vraw & Vcc like this if you have removed the regulator. If you are keeping the reg. in your build then Vraw must remain separate, & you can only repurpose the reset pin for one extra 3.3v rail.

In a no-regulator build, you now have three (+)ive rail connections. This is handy if you accidentally strip one of the terminals by over-tightening.

Adding header pins to the RTC module’s cascade port provides a more convenient attachment point for I2C sensors, and removing the breadboard leaves room for a desiccant pack:

Example of a typical “dedicated sensor” build  without the breadboard, and with the under-board jumpers to provide extra (+)ive & GND terminals. This photo also shows a mosfet controlling the SD ground line, and a thermistor is tucked under the Promini board – but it’s probably better to tackle those additions when you have a few successful logger builds under your belt.

‘Single shroud’ 40-wire 20cm FF Dupont cables are ~$1 each – 1/3 the cost of the ones without housings.

We deliberately put students through the creation of custom sized Dupont connectors because it’s a useful thing to know about, however single shroud wires also work on the RTC and SD module because you are using the double sided tape to hold everything in place. I also tend to use RAW diffused LEDs as indicators, and simply light the individual channels with INPUT_PULLUP mode which uses the internal pullup resistor to limit current. However a single mistaken OUTPUT-HIGH can kill your Arduino if your not careful with that approach. I also leave one of my battery leads long enough that I can tap in to that line & measure sleep currents later on with a Current Ranger.

MCP1702-3302E/TO dead-bug hanging off a Deans style T-plug connector.

The unit pictured above has had its regulator removed so it can run more efficiently on 2x AA lithium batteries. But if you later find out that your sensors need strict voltage regulation, you can always replace the battery holder with a 4xAA, and add a regulator in-line on a battery connector. In the photo (right) two ceramic 105’s stabilize the MCP1700, while a 10/3.3M ohm divider provides a third output line so the ADC can monitor the raw battery status. This is the simplest way to retro-fit a regulator onto a unit that was built without one.

You occasionally get a plano box where the plastic ridges of the housing don’t mate well with the red rubber o-ring. In those cases it’s relatively easy to pull the o-ring out of its groove in the lid, and add some gasket compound to the recessed trough before carefully putting the o-ring back in. The additional height then compensates for casting error in the housings, though don’t add to much or you won’t be able to close the lid. One positive aspect of the relatively loose fit on that lid is that it lets you run prototype tests quickly if you jumper to your sensor module with thin 28-30 gauge wires:

This is a BMP280 pressure sensing module. Wires must extend beyond the edge

~1″ square of foam mounting tape with wires spaced evenly

 

Leave the red backing facing up as you fold the tape & wires over the corner edge.

The front corners of the box exert less pressure than the back

The sharp inner edge of the lid would cut the wires insulation if the tape was not there to protect

The tape has to be replaced every time.

This gives you a chance to do overnight run tests before you commit to modifying the housing with holes, putty, or pass-throughs with cable glands. And for indoor sensor deployments this might be all you actually need to do, though I would still coat the exposed solder joints on that dangling breakout module with either conformal coating or clear nail polish to prevent oxidation.


Addendum 2020-07-29:  Better moisture protection

I was noodling around in the garden recently and installed a few loggers without desiccants because it was only a short experiment. It rained immediately afterward and I noticed a small amount of moisture condensed inside the plano-box housing. While this didn’t prevent the logger from functioning, it completely disrupted the LED light sensors because it provided an alternate discharge path for the reverse bias charge:

Green channel data from a 5mm diffused RGB LED used as light level sensor. This logger was under some leaf cover, so there was considerable variability from the dappled light crossing over the sensor. An arbitrary cutoff of 200,000 was set in the code at low light levels.

After examining the O-ring I decided to add a little silicone to the channel holding the red o-ring to improve the seal:

 

Gently pry the O-ring loose and apply sealant in the groove before replacing.

Bead only needs to be 3-4mm in diameter.

Close the housing & let the sealant set for a few days. The improved seal is especially visible at the corners

If you already have your logger assembled, try to find a silicone sealant that does not off-gas acetic acid (smells like vinegar) which could harm your circuits. If you are simply preparing empty boxes before assembly, then any regular bathroom sealant will do provided you give it about a week to finish curing.


Addendum 2020-05-11:  Using a more advanced processor

After you’ve built a few ProMini based loggers, you might want to try a processor upgrade. The 1284p CPU has twice the speed & 4x the memory, but still delivers comparable sleep current / longevity.

Pro Mini Logger Project for the Classroom [ EDU Jan: 2019 ]

Note: An updated tutorial was released in 2020:  CLICK THIS LINK to view that version


“Instrumentation is a central facet of student, amateur and professional participation in science. STEM education, recruitment of scientists and experimental research are thus all hampered by lack of access to appropriate scientific hardware. Access restrictions occur because of: 1) lack of capital to purchase or maintain high-cost equipment, and/or 2) the nature of proprietary ‘black box’ instrumentation, which cannot be fully inspected, understood or customised…
…In addition to reducing opportunities for people to engage with science, this lack of access to appropriate hardware restricts scientist’s creativity in experimental designs.”

From: Journal of Open Hardware
Expanding Equitable Access to Experimental Research and STEM Education

by Supporting Open Source Hardware Development


Last year’s intense deployment schedule focused on getting more sensors into the field, which left little time for development of new approaches to the logger itself.  Now that everything is settling into the school term routine, it’s time to update the “classroom edition” of the Cave Pearl Logger with feedback from three years in the trenches: 

The 2016 build achieved it’s goal reducing construction time, but it was low on important skills like soldering. Limited lab time meant that something had to give if we want students to “pay the iron price” for their data, so we’ve added a pre-made enclosure box. Though it’s not as robust as the PVC housings, it provides more room inside the housing. Past student projects have required things like 555’s, ADS1115 modules, display screens, etc. and the proto-board will make it easier to integrate those additional components.

PARTS & MATERIALS

TransparentSinglePixl
Bill of Materials: $18.35
Plano 3440-10 Waterproof Stowaway Box
Usually cheaper at Amazon as “add-on” items.  $4.96 at Walmart and there are a selection of larger size boxes in the stowaway series. 6″ Husky storage bins are an alternative option.
$5.00
4Pin 24AWG IP65 Black Waterproof Cable Connector OD 4mm
Better quality version is available at Adafruit for $2.50 each, wBL-RED-Wht-Yel colors used here for the I2C bus.
$1.00
M12 IP68 Nylon Cable Gland
Adjustable for 3mm-6mm diameter. You need two for the build. Make sure they include O-rings.
$1.00
3/4″ Schedule 40 PVC Cap
Diameter will depend on the size of your sensor breakout board. Get ones with FLAT ends.
$1.00
White 170 Tie-Points Prototype Breadboard
Available in other colors.
$0.60
Pro Mini Style clone 3.3v 8mHz
Get the ones with A6 & A7 broken out at the back edge of the board.
$2.20
Nano V1.O Screw Terminal Expansion Board
Note: To save time, you can spend an extra $1 for pre-assembled boards by Deek Robot, Keyes, & Gravitech (CHECK: some of them have the GND terminals interconnected)  Have a few small flat head screw drivers handy.  
$1.05
DS3231 IIC RTC with 4K AT24C32 EEprom (zs-042)
Some ship with CR2032 batteries already installed.  These will pop if you don’t disable the charging circuit!  
$1.25
CR2032 lithium battery  $0.40
4 poles/4 Pin 2.54mm 0.1” PCB Universal Screw Terminal Block Connector
These things look “open” when they are “closed”, and you need a very small screw driver to open them.
$0.40
SPI Mini SD card Module for Arduino AVR
Buy the ones with four ‘separate’ pull-up resistors so that you can remove them.
$0.50
Sandisk or Nokia Micro SD card 256mb-512mb 
 Test used cards from eBay before putting them in service. Older Nokia cards have much lower write currents in the 50-75mA range. This is less than half the current you see on more common larger sized cards.
$2.00
3×1.5V AAA Battery Batteries Holder w Wire Leads
The Pro Mini regulator will handle battery packs holding from 3 to 8 AA or AAA batteries. If you are using alkaline AAA batteries, changing this to a 4xAA battery holder doubles the run time.
$0.40
Common Cathode Bright RGB LED 5mm 
( & 4k7 limit resistor) 
$0.05
3M Dside Mounting Tape10MΩ resistors & 3MΩ resistors, 22awg silicone wireheader pins, etc… $0.50
Donation to Arduino.cc
If you don’t use a ‘real’ Pro Mini from Sparkfun to build your logger, you should at least consider sending a buck or two back to the mothership to keep the open source hardware movement going…so more cool stuff like this can happen!
$1.00
Comment:   You might need some extra parts to get started:                (not included in the total above)
2in1 862D+ Soldering Iron & Hot Air station Combination
a combination unit which you can sometimes find as low as $40 on eBay.
Or get the Yihua 936 iron alone for about $25.
$50.00
3.3V 5V FT232 Module
  ***Be sure to set the UART module jumpers to 3.3v before using it!*** and you will also need a USB 2.0 A Male to Mini B cable.
$2.75
Micro SD TF Flash Memory Card Reader
Get several, as these things get lost easily. My preferred at the moment is the SanDisk MobileMate SD+ SDDR-103 which can usually be found on the ‘bay for ~$5.
$1.00

Connection Diagram:

This logger uses the same three components described in the paper from 2018, but we now connect those core modules via a screw-terminal expansion shield, rather than soldering them directly to the pins:
 
COMPONENT PREPARATION

Watch through the videos as a complete set first so you know where you are going, and then use the images below the videos to remind you of the key steps while you do the assembly; It usually goes much faster working from a photo where you can see all the connections at once. The times listed are estimates for people with soldering experience. If you’ve never built a circuit before, then taking 3-4x that long is completely normal. Don’t worry about it – you will be surprised how much faster you get with a little practice!

Screw Terminal board:  (~40min)  or ( 5min with pre-assembled board)

Don’t forget to measure the values of the resistors before soldering that voltage divider. You will need those values to calculate the battery voltage based on the ADC readings from pin A6.

These screw terminal boards are designed for an Arduino Nano, but if you orient the board to the Tx/Rx pins, the labels on digital side of the shield will be correctly aligned with the Pro Mini:

The most common beginner errors at this stage are crooked headers & not heating the pad/pins long enough for solder to flow properly.  This is often because students are trying to use an iron tip that has “gone dry” so the heat is not transferring properly to the pins. You must protect soldering iron tips with fresh solder every time you put it in the stand to prevent oxidation. Tip Tinner can sometimes restore those burnt tips.   {Click images for larger versions}

Common soldering errors – which are easily fixed by re-heating with more solder & flux.

Divider runs between GND & RAW Vin, with output to A6 pin.

Always apply conformal coating in a well ventilated space, such as a fume hood.

It is better to err on the side of using a little too much heat, because partial connections to the screw terminals will cause you no end of debugging grief later: Cold solder joins can “sort of” work “sometimes”, but cause mysterious voltage drops over those points because they can act like randomly variable resistors in your circuit.  Note: This voltage divider uses meg-Ω size resistors and takes >1 second to charge the capacitor when the unit is first powered on – so you can’t take the first battery reading until that much time has passed.

The Pro Mini Board:   (~40 min)

~5-10% of the cheap Pro Mini clones from eBay are flaky, and it is quite annoying to discover one of those that after you have assembled a logger. So test your board with the blink sketch before you remove pin13 LED resistor.  These limit resistors move around from one manufacturer to the next, so you might have to go hunting for them on your particular board.  You also need to remove the RESET switch from the board, or that button will be compressed when you put the SD card adapter in place:

Test w blink sketch!

You can skip the reset pins at this stage, or you can pull those pins out of the plastic rails later with pliers, or simply cut them off.

SCL & SDA jumpers to the 2 extra pins on the digital side.

Connect A6-7 & GND to analog side pins with the leg of a scrap resistor.

(Note: Credit goes to Brian Davis for the idea of using “extra header pins” when patching to the unused to screw terminals.)    

The SD Card Adapter:   (~15 min)

This SD card adapter comes with small surface mount pull-up resistors on the MOSI, MISO & SCK (clock) lines (removed from the dashed red line area photo 2 below).  The Arduino SDfat library uses SPI mode 0 communication, which sets the SCK line low when the logger is sleeping. This would cause a constant drain (~0.33mA) through the 10k SCK pullup on the module if we did not remove it.  I prefer to pull MOSI & MISO high using the internal pull-ups on the Atmel328P processor, so those physical resistors on the breakout board can also be removed. Leave the top-most resistor of the four in place to pull up the unused DAT1 & DAT2 lines.  This keeps those unused pins on the SD card from floating, which can draw excess current.

Only remove the bottom three pullup resistors. keep the top one
The SPI connections:
RED:           3.3v regulated
Grey:          Cable select (to D10)
Orange:     MOSI   (to D11)
Brown:      SClocK (to D13)
Purple:      MISO   (to D12)
BLACK:     Ground

Attach SD adapter & Pro mini to the Screw Terminal Board:  (~20 min)

Label the Vcc & GND connections with a colored marker, then insert the Pro Mini into the headers on the screw-terminal shield. Be careful not to bend the pins – especially the “extension” pins at the back of the board. It’s easy to connect the board in the wrong orientation at this step. The voltage divider on the bottom of the screw terminal shield aligns with the ANALOG side of the Promini board. 

Label the Vcc & GND connections.

Then affix the SD adapter board to the top of the Pro Mini with a slight overhang, so that the jumper wires align with the screw terminals below. Trim the wires about 1cm past the edge of the board to provide enough stripped wire for the terminal connection.

The limit resistor for the common cathode RGB can range from 4k7 to > 30kΩ

LED on pins D4-D6, & GND. NOTE: Grounding the LED through D3 lets you use the LED as a sensor and support for this is included in the base code.  Also see: multiplexing wD9 GND

Add layers until the tape extends beyond the pins. This might require 3 layers of tape.

The RTC Module:  (~15min)

The simplest modification to these DS3231 RTC boards is to remove the charging circuit resistor and power LED limit resistor from the circuit board (the red squares in the first picture).  A non-rechargeable CR2032 coin cell battery will supply the RTC with power for many years of operation.  Note: The 32K pin is not connected, and does not get a jumper wire. The four screw terminals go on the same side as the battery holder.

rtc1

An alternative to the 4-pin 0.1” screw-terminal block is to solder the I2C pass-through wires directly to the module.

Cutting the RTCs Vcc pin reduces sleep current by ~40% – this step is completely OPTIONAL!

Add an extra layer of foam tape over the smaller 4K eeprom chip, so that the thickness matches the top surface of the DS3231 chip.  The RTC board already has 4.7kΩ pull-ups on the SDA (data) and SCL (clock) lines so you will not need to add them to the bus.  This module also has a 4.7k pull-up on the SQW alarm line. Adding the screw terminals to the small cascade port on the RTC module is another creative idea from Brian D, but you could just add straight pin headers: If you don’t want to make your own crimp ends,  4-pin JST XH series connectors have a pitch of 2.5 mm which is effectively identical to the 0.1″ pitch of those Dupont pins. 

The Plano Stowaway housing: (~10 min)

In these photos, I’ve melted threads into the housing for a pass-through with a cable gland, but that is entirely optional. This trick works with many different housing materials, but it takes a bit of practice to figure out what the right temperature is for any given one. The plastic in the plano boxes melts quite easily, so be gentle with the heat gun. Glands much larger than PG7 (12mm) will not fit in the available space in that corner.

These two cable glands have matching thread specifications

Heat only the threads from the metal cable gland with your heat-shrink gun & a pair of pliers

Gently twist the threads into the plastic of the Plano-box & as soon as it’s through blow on the metal until it completely cools

After cooling,  unscrew the metal threads

Cut away excess plastic burs with a sharp knife and thread the plastic cable gland into place.

You may need two washers due to the curvature of the box. The cable gland shown above is an M12 x 1.5 IP68 for 3-6mm dia. cables (also desc. as PG7 12mm)

Strategically placed holes in the clips provide zip-tie locations to secure your logger.

Holes for Zip-tie securing

ASSEMBLING THE LOGGER PLATFORM:  (~30 min)

Using double sided tape to hold the parts inside the housing (rather than traditional stand-offs) makes this stage of the build remarkably quick.  Adding male Dupont pins allows you to join internal and external wires via the breadboard.  Be sure to use wires that are long enough to reach the mini breadboard. 

Bowing on some boxes can reduce the contact patch on the battery holder, if so try adding another layer of  tape, or upgrade to 30LB.

You can “reactivate” spent desiccant packs with a few zaps in the microwave – if they have indicator beads.

Connecting external sensors to the housing:

It’s worth mentioning the breadboard contacts are notoriously sensitive to vibration, etc. Once your testing stage is complete, and your prototype is working as it should, bring those  sensor wires directly over to the screw terminal connections for a more secure connection.  Also remember to put protective tape over any sensor ports that need to remain open before potting those sensor boards in epoxy. Otherwise you might clog the sensor by accidentally letting a drop fall into it.

Your Logger is ready!    (~2 to 2.5 hours)

Now you can test your new logger to confirm all the connections are working:

1. Test the LED – Edit & upload the default blink sketch, changing the pin numbers each time to match your RGB LED connections.

2. Scan the I2C bus – with the scanner from the Arduino playgound. The eeprom on the RTC module is at address 0x56 or 57 and the DS3231 should show up at address 0x68. If you don’t see those two devices when you run the scan, there is something wrong with your RTC or the way it’s connected.

3. Test the EEprom on the RTC module – We’ve updated BroHogan’s original code from the playground to this tester script. You may have to change the I2C address at the start of the code based on the numbers shown during your I2C bus scan. The AT24C32 will store 4Kbytes, and has a 32-byte Page Write mode which accommodates the maximum of 30 bytes you can transport the wire libraries I2C coms buffer.  Make sure you don’t do eeprom page-writes that pass over the physical page boundaries set by that eeproms 32 byte block size. If you are ready for the added code complexity, buffering data to the eeprom can dramatically cut down on the number of SD card saves, however the eeprom communications are so slow that sometimes it ends up using the same amount of power as simply writing your data directly to the SD card directly.

An alternative parts arrangement for the classroom logger that makes room for a larger 4xAAA battery holder and DUPONT style connectors. It’s easy to move things around to suit your own projects, and rotating the breadboard gives you room for larger battery holders & longer operating times. Note: For most 1.5V alkaline batteries, (voltage-1)*200 will give you the approximate percentage of total capacity remaining.

4. Set the RTC time, and check that the time was set – There are dozens of good Arduino libraries you could use to control the DS3231, and there is a script over at TronixLabs.com that lets you set the clock without a library. The trick with Tronix’s “manual” method is to change the parameters in setDS3231time(second, minute, hour, dayOfWeek, dayOfMonth, month, year);  to about 1-2 minutes before the actual time, and then wait to upload that code till about 10-15 seconds before your computers clock reaches that time (to compensate for the compiler delay). Open the serial window immediately after the upload finishes, and when you see the time being displayed, upload the examples>blink sketch to remove the clock setting program from memory – otherwise it will keep resetting the RTC every time the Arduino re-starts.  [ Note: hour  in 24-hour time, & year with two digits eg: setDS3231time(30,42,21,4,26,11,14);  ]

5. Check the SD card is working with Cardinfo – Changing chipSelect = 4; to chipSelect = 10;
Note that this logger requires the SD card to be formatted as fat16, so most 4GB or larger High Density cards will not work. Most loggers only generate 5 Kb of data per year anyway.

These breadboard connections are really vulnerable to vibration, so for quick back-yard tests of a rough prototype I sometimes add a tiny spot of hot-melt glue to stabilize the components. Breadboards add about 2-4pF of capacitance for side by side rows so the rule of thumb is you shouldn’t run protoboard circuits much faster than 1 MHz.

6. Check the sleep current – With an SD card inserted in the logger, upload this Pro Mini datalogger starter script with no changes (note: that code requires you to install three libraries as well). Then connect an ammeter between the positive battery connection and the Vin screw terminal (you will need an extra wire to do this) and run the logger from the AAA or AA battery pack.  After the initialization sequence has finished, the reading on the screen (in milliamps) is your loggers sleep current.

AAA cells usually provide about 1000 milliamp-hours of power to their rated 0.8v, but we are only using half of that from alkaline batteries with a regulator input cutoff up at 3.6v.  So dividing 500 by your loggers sleep current gives you a rough estimate of your loggers operating life (in hours).  For a more accurate estimate, you can use one of the Battery Life Calculators on the web with 250ms @5mA for your sample time.  Changing the power supply to 4xAAA cells lets you bring alkalines down to 0.9v/cell, extracting almost the entire 1000 mAh. Lithium AAAs deliver almost their entire capacity above 1.2v/cell so 3xAAA lithiums yield almost 1000 mAh capacity even with the 3.6v input cut-off.

Thermal response of 3x AAA’s (mV left axis) vs Temp (°C right axis) in the standard voltage-regulated classroom build running the starter code from GithubThe 90mv drops caused by SD card “controller housekeeping events” at 20°C  increase to ~220mV as temps near -15°C. These periodic high drain (100-200mA) events would likely trigger the low-voltage shutdown before anything else in the loggers normal duty cycle. (Note: Battery readings taken AFTER SD save, Sample interval: 1 min, sleep current for this test unit: 0.22mA )

Its worth noting that the starter program we’ve provided captures an ambient temperature record from the RTC in 0.25°C increments (example right).  New sensor readings can be added to the log file by inserting:
file.print(YourSensorVariableName);
followed by a separator file.print(“,”);
in the main loop before you close the datafile on the SD card. Then change the text in the dataCollumnLabels[] declaration to add headers to match your new data. This starter script automatically generates required data files on the SD card at startup, and tracks the rail voltage for those adventurous enough to run without a regulator. SD memory is electrically more complex than the Pro Mini processor, with some using a 32 bit arm core.

Once you have your logger running, you might want to review our tutorial on adding sensors to your data logger. And after that you’ll find a few more advanced I2C sensor guides on this site as well (…and the list is constantly growing) We’ve also developed methods to add 5110 LCD & OLED screens to the Cave Pearl Loggers using the fewest system resources. These screens are easily accommodated on the proto-board in this build.

For people wanting to take their skills farther, you can explore the gritty details of how we optimize these loggers for multi-year deployments in the 2018 Sensors article (free to download). The research loggers are a more challenging build, that fits inside an underwater housing made from PVC pipe

Addendum: Power Management (Optional)

On the standard build described above, the Pro-Mini’s MIC5205 power regulator should deliver  sleep currents below 0.25 mA (Pro Mini ~0.05 mA + sleeping SDcard ~0.05-0.09 mA + RTC ~0.09 mA). That should reach several months operation on 3 AAA cells before the batteries reach the regulators 3.4v input cut-off.  I usually have regulated loggers go into shutdown mode at ~3.6v to reduce the chance of leaks, because alkaline batteries often spill their guts when they reach 1v/cell.

There are a couple of relatively simple modifications to the basic logger that more than double the operational time – but they both come with important implications you should understand fully before adding them to your project. The RTC mod is relatively safe, but running a datalogger from a raw battery supply is not for the faint of heart. 

1) Cutting the VCC leg on the DS3231 chip forces the RTC to run from the coin-cell. >Set Bit 6 of CONTROL_REG 0x0E to enable wake alarms from the backup battery!

2) Remove the regulator: few LDO’s have reverse current protection & most regs leach 30-90 uA if the voltage on output line is  higher than on their input

2) Then connect the positive wire from a 2X LITHIUM AA battery pack directly to the Vcc rail on the Pro Mini

The DS3231 RTC was designed to handle power supply failures by switching over to the backup coin-cell battery, and it enters a special 3uA “timekeeping mode” to use less power in that situation. However the chip is still fully capable of generating alarms (provided you set the Battery-Backed Square-Wave Enable bit of CONTROL_REG 0x0E to 1) , and of responding to the I2C bus at 400 mHz. So if you cut the main power leg on the RTC you reduce the loggers sleep current by almost 0.1mA (~40%). The trade-off is that your loggers operation is now entirely dependent on the 200mAh CR2032 coincell to keep the clock delivering wake-up alarms when you are also asking it to deal with pulsed loads in the 80 uA range every time you communicate over the I2C bus. The RTC also can not generate temp-corrected frequency outputs on the 32kHz pin when operating from the coin cell.

Here drops of hot glue secure the RTC coin cell battery against accidental resets. It’s worth noting that even with this precaution, we still see 1-2 units out of 10 loose their time when they have to be transported in airline luggage.

Another quid pro quo here is that coin-cell holders occasionally lose contact very briefly under vibration, so if you cut the Vcc input leg – add  a  0.1 μF capacitor (ceramic 104) across the coin-cell holder pins. That will give you about 80 ms coverage, which should be longer than the holder will lose contact. Otherwise a hard bump can reset the RTC back to its Jan 01 2000 default.  The wake-up alarms usually continue after that kind of reset, however fixing an entire years worth of time series data based on your field notes is a pain in the backside.  Real world installations often involve this kind of rough handling, so I prefer a more advanced RTC modification that keeps two power lines feeding the RTC.  But for more “gentle” deployments, simply cutting the chip’s vcc leg & adding a couple of drops of hot glue OK. Write the installation date on the coin cell with a black marker. I do this to all of my batteries now…

For loads in the 0.1mA range, the MIC5205 is less than 60% efficient. So the other modification is to remove the voltage regulator and run the entire system from 2x LITHIUM AA batteries.  Lithium batteries (like the Energizer L91) have two characteristics that make them well suited to this approach: 1) they have an extremely flat discharge curve, yielding >75% of their power before the voltage falls below 1.5v/cell on the lower plateau and 2) a pair of brand new lithium cells gives a combined voltage right at 3.6 volts. If you look at any of the SD card manufacturers’ specifications, they all specify a voltage range of 2.7v to 3.6v.  At 8 MHz the ATmega328P processor on the ProMini supports voltage levels between 2.7 V and 5.5 V. Both of these ranges overlap beautifully with the lithium cell’s discharge curve. If you are using ratio-metric analog circuits then the voltage fluctuation over time will not affect your readings, but if you need absolute measurements then use the internal voltage reference as Aref.  Digital sensor levels are based on a percentage of Vcc, so they are relatively insensitive to voltage variations.

Here I’ve done both modifications to the basic build, and brought the sleep current (with no sensors) from an unmodified starting point of 228μA, down to 80μA. Most of that remaining power is due to the sleeping SD card, since the Pro Mini only draws about 5μA in deep sleep mode. Using only 1/2 of the 3000 mAh capacity of a typical AA Lithium pack would keep a logger that sleeps at 0.1mA alive for more than a year, and my rough estimate is that the RTC mod will get you at least twice that much time from a new Cr2032 cell – with a typical 5-15 minute sampling interval.      [NOTE: I’m using an EEVblog uCurrent here to display the μA sleep current on a DVM as milivolts. It’s an exceedingly useful tool that lets you read sleep currents into the nano-amp range without adding the burden voltage you’d see from putting your meter directly into the circuit ]

Even with one less cell powering the system, getting rid of the MIC5205 yields a 25-30% reduction in sleep current for a typical build. While this is very close to the reduction you get from changing to a more efficient regulator like the MCP1702, the other cool thing about this mod is that the processor on the Pro Mini can take a reading of it’s rail voltage by comparing it to the 1.1v internal band-gap reference. So all you need is a little bit of code, and you can keep track of your rail=battery level without a voltage divider, although for accuracy you should take a reading of the actual band-gap voltage using a utility like the CalVref sketch from openenergymonitor.

(NOTE: that Atmel provides no specs on the long term stability of the bandgap ref. and even OpenEnergy no longer uses the internal 1.1vref because v.regulators offer more long-term stability.  ALSO NOTE that genuine Sparkfun ProMini’s have an SJ1 jumper that lets you disconnect the reg simply by de-soldering a pad on top of the board , but clones rarely have that feature.) 

Unlike alkaline batteries, lithium cells have very little voltage droop with brief loads below 100mA, but it’s still a good idea to protect your SD card from potentially data corrupting brief low voltage spikes with a capacitor.  The formula for figuring out how much the voltage across a capacitor will drop is  ΔV = current(A)*time(sec)/C(farads) – but you need to decide how much your supply can drop to know how big to make the capacitor.

Adding a 47uF (or larger) on the microSD rails should keep the shortest transients under control, and once the system reg. has been removed running a jumper between Vcc & Raw recruits the orphan (10uF tantalum) capacitor from the input side of the (now removed) regulator.  Always check the supply voltage before the data saving begins and perform a low voltage shutdown when the lithium pack reaches 2875mv. (ie: at least 150mv above the SD’s 2.7v safe writing minimum). Generate a new data file every couple of weeks so only the last one is vulnerable during the write process. 

2x LITHIUM AA’s (mV left axis) vs Temp (°C right axis) supplying power to an unregulated build running the same code from GithubThe key observation is that the initial 50mv supply voltage variation recorded at 22°C increases  ~100mV at temps near -15°C. For Lithium chemistry batteries with flat discharge curves, the voltage-drop under load is often a better indicator of the remaining battery capacity than the cell voltage. (Readings taken AFTER SD CARD SAVE, Sampling every 1 min, overall sleep current 0.17mA   Note: the 200mv baseline drop on the cells is slightly exaggerated here because low temps increase the bandgap slightly) 

Of course everything has a price, and removing the regulator means you’ve not only lost your reverse voltage protection – you also need to think about how all the components in your system will respond to a decreasing supply voltage over time. Ratiometric analog circuits using the rail as Aref handle this well, but even if you want to use the 1.1v bandgap ref – you already know what the rail voltage is, so you can easily throw a compensation factor into the calculation.  The real problem is that when 2.7 – 3.6v is listed on the spec sheet for a digital sensor – that’s no guarantee the readings will be consistent when the supply voltage changes.  You could have very different error percentages at the high & low end and ambient temperature fluctuations could push your batteries through significant voltage changes every single day (lithium cells are more resistant to this than alkaline).  According to Murata the 8Mhz system clock will remain stable: “Unlike RC or LC circuits, ceramic resonators use mechanical resonance. This means it is not basically affected by external circuits or by the fluctuation of the supply voltage.” 

Testing is the only way to find out if your sensors can handle the variation, and if you don’t have time for that it might be worth keeping that voltage regulator on board despite the reduced lifespan. For field units, I usually replace the MIC5205 with a more efficient MCP1700 regulator because I want all the data consistency I can get.  Another thing to keep in mind when you are hoping for a really low-power build is leakage currents through leftover flux – it’s always worth the time to get your parts squeaky-clean during construction.

Addendum 2019-02-21:

A teacher friend asked us for a version that was less dependent on soldering because they didn’t have the budget for a classroom set of soldering stations. So we’ve worked out a 1 hour “simplified build” of this logger that uses crimped Dupont jumpers to reduce assembly time:

We’ve also added support to the starter code for using the indicator LED as a light sensor, but this requires that you ground the indicator LED’s common cathode through a digital pin (usually D3) , rather than directly to GND as shown in the tutorial above. Also note that the technique relies on the very tiny internal capacitance inside the LED (typically 10 to 15 pF) so you need to connect the LED  right to the screw terminals (ie not the breadboard).  Then you can gather three-channel light level data like this:

Readings from an RGB LED deployed outside in our back yard on an overcast day with two light snow fall events. The yellow line is from an LDR sensor in the same logger that was over-sampled to 16-bit. In this case the clouds & snow acted as a near perfect light diffuser, but in normal weather I’d have placed a thin white teflon sheet over the LED sensor to smooth out the readings. Adding an IR led to the logger lets you create a transmission-based NDVI variant that discriminates the amount of chlorophyll in plant leaves.

These readings are arbitrary time-based units that are completely dependent on your particular hardware combination and system voltage. If you go down the DIY sensor rabbit-hole, you might want to calibrate against the NOAA observations for your area, which includes hourly data for thousands of stations. The data includes temperature, dew point (from which you can compute relative humidity), wind speed & direction, and you can calculate solar position.

Addendum 2020-08-18:
We’ve found that the seal on some of the Plano boxes needs a little help, or current leakage via surface moisture shorts out the LED light sensor readings. In the worst cases leakage lets in enough water vapour to chew through your desiccant pack in less than a week. A little bead of silicone under the o-ring corrects that problem:

Gently pry the O-ring loose so we can add some sealant.

Bead only needs to be 3-4mm in diameter.

Close the housing & let the sealant set for a few days. The improved seal is especially visible at the corners

If you already have your logger assembled, try to find a better quality silicone sealant that does not off-gas acetic acid (smells like vinegar) which could harm the circuits. If you are preparing empty boxes before the logger assembly, then any regular bathroom sealant will do provided you give it about a week to finish curing. I usually choose silicone rated for outdoor applications as they have better resistance to breakdown from UV exposure.

Tutorial: Adding the SSD1306 OLED Screen to an Arduino Logger (without a library)

An SSD1306 OLED screen mounted on a climate station build.

This is the third installment in a series on adding output screens to Cave Pearl Data loggers. It builds on the Nokia 5110 LCD tutorial and the post describing how I store fonts in the Arduino’s internal EEprom to save program memory – so you might want to have a look at those two posts before diving in here.

While the Nokia 5110’s are a cheap, low-power option with great visibility in full sun, they reacted badly to pressure directly on the LCD surface.  Since this project deploys loggers in an underwater environment I went looking for something more robust and the SSD1306 OLED’s caught my attention. (@ ~$3.50 on eBay) These little screens are showing up in hacked toyscompasses, GPSanalog meters, ECG’s, and theres even a tiny oscilloscope project at Hackaday. But those applications typically use the u8g2 library which is fantastic for graphic output, but also quite memory intensive; what I need is a bare bones solution that uses the fewest system resources on a unit that’s already near memory limits. Though these 0.96 inch displays are quite small, 128×64 pixels lets you render several lines of readable text.

While the I2C variants of this screen are easy to use, the SPI version lets me re-purpose unused analog lines to drive this display without interfering with the sensor or SD card bus because it can be driven via shift-out on any pins that are available. Powering the screen from A0 brings the screen down to zero current while the logger is sleeping, and also lets me get rid of the Reset & Cable Select lines. The only thing to watch out for is that you bring all the control lines low when you cut power so that reverse bias doesn’t end up “back powering” the screen controller.

Connecting the OLED:                                {Click any image to see larger versions.}

The data sheet for the SSD1306 controller specifies that the reset input needs to be LOW, during initialization, after which the pin should be HIGH for normal operation. To achieve this low -> high  transition, I tie the Reset line to the middle of an RC bridge made from a 104 (0.1uF) capacitor and a 10k resistor. When you add the 25k inside the 328p used to pull A0 high, you get a 63.2% time constant of about 3.5ms.

Begin by tinning the pins, and bending them 90 degrees for alignment with the RC bridge which also connects to the CS pin.  Once that delayed rise circuit is soldered in place, also jumper the incoming GND line over to Cable Select. You would not do this if the display was on the normal hardware SPI bus, because it would exclude other devices on the SPI bus. But since we are using a separate set of wires for the display we can get away with this trick.

The connections for the SSD1306 OLED display are the same as the ones for the Nokia 5110: (D0=clock, DC=command, D1=data in)  Note that I’m not using the 3.3v rail from the pro-mini,  and YOU MUST BE USING A 3.3V ARDUINO FOR THIS WIRING TO WORK UNLESS YOUR OLED BOARD IS 5V TOLLERANT.  Some of the breakouts  from eBay are OK at 5v, and some are not – check THIS before you buy if you are using a 5V Arduino.  (Note that  most breakouts sold by Adafruit include regs & level shifters to handle both voltages.)

When all the incoming lines have been added to the board, thread them through the housing and verify that the screen is still working. The analog A0-A5 lines on an Arduino can be re-purposed as digital I/O so I usually break them out with a 6-pin Deans Micro Plug (incl. GND & Vcc)  In this case the screens Vcc line is being re-routed to pin-powering from A0 so the pro-mini’s rail voltage is not used.  Cut away or heat-shrink over the unused Vcc pass-through on the screen side of the connector (which is still visible & exposed in the photo on the right) as you don’t want it accidentally contacting something later on inside the housing.

After the operation test, cork the pass-through hole with a bead of plumbers epoxy putty  about the size of your fingertip. Wrap that putty so that it is on both sides of the wires before smoothing it down on the housing.  (The sensor cap shown below has four housing penetrations sealed by this method)  On the top of the sensor cap, wrap a grape-sized lump of well worked putty around the wires on the back of the screen. Then carefully press the screen down into the PVC well so that the putty compresses into a support pillar that holds the screen as near level as possible. The putty hardens in about 10 minutes and then you can pour the first layer of potting epoxy. Here I’ve used Loctite HYSOL E-60NC, with a 50ml applicator & MA6.3-21s mixing nozzles. The air space for the reflective back light forced me to use clear epoxy with the 5110 LCD screens, but since these OLED’s emit their own light, you can bring that black epoxy right to the edge of the display – covering the board & any ugly soldering… 🙂  Check the epoxy over the next couple of hours and pop any bubbles that rise to the surface with a pin. (unless you have a vacuum chamber)

Always TEST before potting!

Let that initial layer of epoxy cure for 24 hours, then drill a 7/32″ hole at a safe distance away from the screens edge. Mount an RGB indicator led inside the housing and seal it in place with plumbers putty. At this point you can simply add a second layer of clear epoxy to protect the screen, but in our experiments with the Nokia LCDs, seawater caused a serious fogging problem.  So I recommend a top surface of more chemically resistant material for that kind of application. Here I’ve used a 1/4″ thick plexiglass disk (~$0.35 each on eBay)
First apply a thin layer of clear epoxy over the screens surface so that it self-levels to thickness of about 1-2mm. Then hold the edge of the acrylic disk and carefully tilt it over the epoxy film with an even contact edge that moves across the disk slowly enough to let the air escape.  Don’t make that first layer of clear epoxy too thick or it will over-top the edge when the plexi settles into place and this will form blobs on the surface. Once the acrylic is in place, you can slowly add drops of epoxy on the side to bring the level up to match the edge.  Give the clear epoxy another 24 hours to cure.

The display draws more current as you increase the number of pixels turned on.  As a point of reference: the screen output shown above (generated from the code on Github ) draws 3.4 mA.  And I haven’t seen any nasty current surges that might exceed the pin limit when the display is first powered up.

The shore hardness of the plexiglass is not much higher than cured epoxy, but the optical clarity is considerably better. The photos in this post don’t capture it well, but this mounting method really shows off the razor-sharp output you get from an OLED, and it’s readable from just about any angle.  For surface loggers a 1/8″ disk should provide sufficient protection, but for the underwater units I will use 1/4″ thickness to resist the compression at depth. I won’t be able to test those underwater versions in the real world for a few months, but if the acrylic fails I will change to  a stiffer glass overlay.

A few might wonder why I added an indicator LED when the logger now has full display capability. There are plenty of situations where brief LED pips communicate the progression of duty cycle events that are too fast and too numerous for screen output. I also use the LED as a noise generator when I want to squeeze higher resolution from the ADC through oversampling.  These days I add an NTC thermistor to every build to capture ambient temperature.

The Code Example on Github uses a cascading method to break text strings up for single character rendering with : oledWriteString–>oledWriteCharacter–>oledWriteData  and I’ve co-opted that with a new split-character method to print larger numbers to the screen in a two-pass method.  The shift-out code for those functions is basically the same as that used for the Nokia 5110. I went over all that in some detail in the earlier posts so I wont re-fry those beans here. The key thing to keep in mind is that this new screen driving script uses EEPROM.read which assumes you’ve already loaded the font definition(s) into your Arduinos internal eeprom with this helper utility.  That utility loads a ‘reduced’ font set to leave 500 bytes of space for file header data in the EEprom as well. (so the 5×7 font is caps only, and large characters are #’s only).  If you don’t need that level of memory optimization in your build, you can switch back to simply storing the screen fonts in program memory;  just transfer the PROGMEM based string->character->data functions (and the font arrays) over from in the NOKIA 5110 code example.

The housekeeping functions that take care of  initializing the screen, clearing the memory, and setting the XY position are more complex for the OLED than those for the PCD8544 Nokia because the SSD1306 controller has more operating parameters.  But the overall approach transferred easily between the two controllers and I suspect this method could be re-used with most of the larger SPI OLED screens on the market (like the SH1106) provided they stay below the pin current limit on A0.

Time to go shopping!  🙂

Addendum 20181019:

A helpful commenter has informed me that it’s possible to try a similar approach with I2C screens because you can bit-bang I2C devices over any two spare wires.  Now that we’ve pulled off this isolation trick with SPI, I’ll look into bang’n as a way to shut down high current I2C sensors when they are not in use.  I’d want those off the regular I2C bus because it necessarily has a few “always on” devices that might not respond well to a lump of dead wood hanging off the same wires.

Addendum 20190423:

A year long experiment in OLED burn-in. Significant dimming of the most used pixels after 4 weeks, but the screens were still operational after one year.

Using Arduino’s Internal EEprom to Store Data & Screen Fonts

This tutorial is the second in a series on adding displays to expand the capability of the Arduino data loggers described in our SENSORS paper earlier this year. As more of those DIY units go into the field, it’s become important that serial #s & calibration constants are embedded inside the files produced by each logger.  One can always hard-code that information, but with multiple sensors and screens for live output, space is getting tight:

This prompted me to look at the ATmega328p’s internal EEprom as a potential solution. The EEprom can only store one byte per location, so saving numbers larger than 255 requires you to slice them up and store them in consecutive memory locations. That takes two locations for a the “high byte” and a “low byte” of an int, and four memory locations for longs & floats. That’s a little clunky but it mirrors the way you read & write high-bit registers on I2C sensors, so there are lots of code examples out there to follow.  Piece by piece approaches also require memory pointers for retrieval and re-assembly of your variables.

A more elegant method is to roll them into a single ‘struct’  and store that with a generic function, but even with read_block & write_block I’d still be tweaking the code for each logger, since they often have dramatically different sensor combinations.  I wanted a more generic “cut & paste” method that would handle file headers and variable boiler plate info ( contact emails, etc.  ) without me having to update a bunch of pointers.  The real clincher was realizing that the equation constants generated by my thermistor calibration procedure had too many significant figures to store in an Arduino float variable anyway.

A char array provided the simplest way to achieve the flexibility I was after, and I wrapped that up into a little “EEprom loader” utility:             (Note: Github link at the end of this post)

#include <EEPROM.h>
#define PADLENGTH 1024
char eepromString [PADLENGTH+1];    //+1 to leave room for null terminator

void setup(){
strcpy(eepromString," ");
strcat(eepromString, "\r\n");      // a carriage return in Excel
strcat(eepromString,"#198, The Cave Pearl Project");
strcat(eepromString, "\r\n");
strcat(eepromString,"Etime=(raw*iSec)/(86400)+\"1/1/1970\"");
// NOTE: \ is an escape which lets you put "special" characters into the string 
strcat(eepromString, "\r\n");
strcat(eepromString,"Tres=(SeriesOhms)/((((65536*3)-1)/Raw16bitRead)-1)");
strcat(eepromString, "\r\n");
strcat(eepromString,"1M/100k@A7(16bitP32@1.1v),A=,-0.0003613129530,B=,0.0003479768279,C =,-0.0000001938681482");
strcat(eepromString, "\r\n");                 
// following this pattern, simply add more lines as needed (up to max 1024 characters)

// This fills the remaining unused portion of eepromString with blank spaces:
int len = strlen(eepromString);  // strlen does not count the null terminator
memset(&eepromString[len],' ',PADLENGTH-len);

// Now write the entire array into the EEprom, one byte at a time:
for (int i = 0; i < 1024; i++){ 
EEPROM.update(i, eepromString[i]); 
}
}

void loop() {
// nuthin here...
}
 

This is just a bare-bones example I whipped up, and it’s worth noting that strcat will overflow if you try to add more characters than eepromString can hold.  You can check your count at sites like lettercount.com  or try using snprintf() as an alternative without that problem. Since this is a ‘run-once’ utility, I haven’t bothered to optimize it further.  Bracketing calibration numbers with a comma on each side makes them directly usable when the CSV data file is loaded into Excel later because they end up inside their own cell.  It’s a good idea not to avoid putting EEPROM.write codes inside the main loop, or could accidentally burn through the limited write cycles of your internal EEprom. EEPROM.update is the safer than EEPROM.write, because it first checks the content of each memory location, and only updates it if the new information to be stored is different.

With the data stored in the EEprom, it only takes a few lines to transfer that information to the SD card when a new file gets created:

char charbuffer[0]=" ";  //a one character buffer
file.open(FileName, O_WRITE | O_APPEND);
for (int j = 0; j < 1024; j++) {
 charbuffer[0] = EEPROM.read(j);
 file.write(charbuffer[0]);
 }
file.close(); 

The spaces used to pad out the array so that it fills all 1024 bytes of the EEprom do create an extra blank line in the file, but that’s a pretty harmless trade-off for this level of code simplicity.

What else can we store in the EEprom?

In the post covering how to drive a Nokia5110 LCD using shiftout, I went into some detail on the way the fonts for that screen were created and displayed. Three simple cascading functions (originally from Julian Ilett) let you send any string of ASCII characters to the screen.

void LcdWriteString(char *characters)
{
while(*characters) LcdWriteCharacter(*characters++);
} 
void LcdWriteCharacter(char character)
{
for(int i=0; i<5; i++){
LcdWriteData(pgm_read_byte(&ASCII[character - 0x20][i])); 
}
LcdWriteData(0x00);            //one row of spacer pixels between characters
} 
void LcdWriteData(byte dat)
{
digitalWrite(DCmodeSelect, HIGH);    // High for data 
digitalWrite(ChipEnable, LOW);  
shiftOut(DataIN, SerialCLK, MSBFIRST, dat);  // transmit serial data 
digitalWrite(ChipEnable, HIGH);
} 

I modified that code that slightly with reduced font-set arrays stored in PROGMEM and introduced a method for displaying larger numbers on screen by printing the upper and lower parts of each number in two separate passes.  PROGMEM requires pgm_read_byte to get the data out of the 2-D arrays for printing.

Now, with a little bit of juggling, a “loader” script can store that font data in the 328P’s internal EEprom by converting the two dimensional font array into a linear series of memory locations:

const byte ASCII[][5] PROGMEM =  
{
{0x00, 0x00, 0x00, 0x00, 0x00} // 20 
,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x08, 0x08, 0x08, 0x08, 0x08} // 0x2d (dec 45) (-) in row 13 of source array
,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
//...etc, a complete font is in the array, but I only store a 46 character "caps only"
// subset in the eeprom ranging from (-) at array row 13 to capital (Z) =array row 59
// this takes 235 bytes of EEprom memory storage (addresses 0-234)
} 

// move that sub-set of the font (13 to 59) from PROGMEM into the 328's internal EEprom
currentIntEEpromAddress=0;   // each letter is constructed from 5 byte-collumns of data
for(int i=13; i<59; i++){    // so each i value forces a 5-byte jump in EEprom address
for(int j=0; j<5; j++){      // while j value counts through each individual column
charbuffer=pgm_read_byte(&ASCII[i][j]);  // i&j used separately in the array
currentIntEEpromAddress=(((i-13)*5)+j);  // i&j combined for the EEprom address
EEPROM.update(currentIntEEpromAddress,charbuffer); //update to save unnecessary writes
}

Once the font has been transferred into the internal EEprom by the loader program, I only need to make two small changes to the original display functions so they pull that font from the EEprom. Note the calculation trick (character-0x2d) which uses the ASCII code for each character to calculate where the first of the five bytes is located for that character:

void LcdWriteCharacter(char character)
{
for(int j=0; j<5; j++){
LcdWriteData(EEPROM.read(((character -0x2d)*5)+j)); 
//we subtract 0x2d because the zeroth position in EE memory is (-) = ASCII(0x2d)
}
LcdWriteData(0x00);            
} 
// (character - 0x2d)*5 jumps 5 bytes at a time through the EEprom address space
// Add a fixed offset for other fonts stored at higher locations in the memory: 
// eg: LcdWriteData(EEPROM.read(235+((character -0x2d)*5)+j)); 
// the big#fonts are 11 byte-columns wide, so calc = (Offset+((character -0x2d)*11)+j)

This adds some delay, but because the Nokia 5110 is already dead-dog slow it’s not even noticeable.  A similar mod gets applied to the split print functions for the big number font, and moving both to the EEprom still leaves a very serviceable 500 characters for file header info.  The trick to stacking different kinds of information in the EEprom is figuring out what the resulting address offsets are so each reading function starts at the correct memory address. You skip over the memory locations holding the font data when transferring that file header text.

With fonts stored in EEprom, the remaining Nokia 5110 functions compile to just a little over 400 bytes of program storage and 10 bytes of dynamic (excluding EEPROM.h, which gets called by some of my other libraries even if the screen is not present)  That’s with three duplicate copies of each LCD function because I’ve used a set for the standard size font, and two more for printing the large numbers in upper & lower rows.  With a bit more optimization I could get that down to about 200 bytes, which I suspect is probably the smallest memory footprint achievable for adding live data output to my loggers.

I’ve posted a ‘EEprom loader utility’ which demonstrates the dual Font/Text approach at our Project’s GitHub repository  so people can modify it to suit their own projects. On loggers with a number of DS18b20 sensors, I’ll use a similar approach to store the sensor bus addresses, which I usually store in two dimensional arrays very similar to those shown here for screen fonts.

Using the Nokia 5110 LCD with an Arduino Data Logger

Here I’ve added a the 5110 LCD to a logger recording data from a BME280 & Tipping Bucket Rain gauge. If the BME  survives in our field environment, this will become a standard configuration for our climate stations. I’m not holding my breath though, as we’ve tested half a dozen RH sensors so far and none of them have gone the distance in high humidity environments that occasionally go condensing.

This year I want to tackle some projects that need live data out, so I’ve been sifting through the many display options available for Arduino. Unlike flashier projects, my goal was to find one that I could add to existing logger builds without sacrificing too much of the multi-year lifespan I had worked so hard to achieve. The low power winner by a fair margin was the Nokia 5110 Liquid-crystal Display  which you can pick up for around $2 from the usual sources. With the back-light off these displays pull between 100-400 μA, depending on the number of pixels turned on.

This screen uses a PCD8544 controller and the SPI protocol.  It will tolerate 5V, but it works best at 3.3V, which is perfect when you are driving it from an 8mhz ProMini. Each pixel on the display is represented by a single bit in the PCD8544’s RAM. Each byte in RAM correlates to a vertical column of 8 pixels. The X coordinate works on a per-pixel basis, and accepts values between 0 and 83. The Y coordinate accepts values of 0 – 5 which on this 48 pixel high screen, corresponds to 6 “rows of bytes” in the controller’s RAM. So bitmaps can only be displayed on a per row (& column) basis. The display is quite sluggish compared to competitors like the 0.96 I2C monochrome OLED and you have to handle any processing overhead on the Arduino.

Most hookup guides assume that you can spare six control lines to run the display, which is not the case when your logger already has three indicator LEDs, I2c devices, one wire sensors and a couple of voltage dividers on the go.  However if you are willing to add a few resistors and occasionally toggle the power, you can bring that down to three wires and a power pin.

So many libraries, so little optimization…

This screen’s been around for a very long time, so there’s are a huge number of easy to use, highly functional libraries for Arduino. But they tend to focus on things like speed or endless font options which are not important for most data logging applications. And these libs assume your project can afford to lose up to ⅓ of the available program & variable memory just driving the display. Most also require the hardware SPI lines, but our project needs those for SD cards, which are finicky enough without some pokey LCD gumming up the works: the 5110 maxes out at 4mbps, and this slows the bus significantly .

Those fat libs were non-starters for our project, and I had almost given up on this display when I found Ilett’s Ardutorial offering a bare-bones method more suitable for our resource limited data loggers. If you haven’t discovered Julians YouTube channel yet then you are in for a treat because if Andreas Spiess is the maker worlds answer to Werner Herzog, then Julian is surely their equivalent to Bob Ross.  I don’t know if he’s growing “Happy little trees” with his DIY hydroponics, but I can say that the gentle timbre of his “Gooood morning all” reduces stress faster than a warm cup of Tea.  And his “Arduino sandwiches” are brilliant examples of minimalist build technique.

Driving the Nokia 5110 with shiftout

Everything I’m presenting here builds on his tutorials, so grab a mug and give ’em a watch:

Tutorial #1 – Connecting and Initial Programming
Tutorial #2 – Getting Text on the Display
Tutorial #3 – Live Numerical Data

This software SPI method (originally from arduino.cc?) requires no library at all, and shiftout commands work with any combination of digital pins; saving those hardware SPI lines for more important jobs.

Initial setup is explained in video #1 using two functions

void LcdInit(void)
{
digitalWrite(RST, LOW);            // not needed with pin powering!
digitalWrite(RST, HIGH);           // see below for details
LcdWriteCmd(0x21);                 // extended commands 
LcdWriteCmd(0xB8);                 // set Vop(contrast) // you may need to tweak
LcdWriteCmd(0x04);                 // set temp coefficient 
LcdWriteCmd(0x14);                 // bias mode 1:40 // you may need to tweak this
LcdWriteCmd(0x20);                 // basic commands 
LcdWriteCmd(0x0C);                 // normal video
for(int i=0; i<504; i++) LcdWriteData(0x00);  // clear the sceen
} 
void LcdWriteCmd(byte cmd)
{
digitalWrite(DCmodeSelect, LOW);    // low for commands, high for data 
digitalWrite(ChipEnable, LOW);      // not need with pin-power
shiftOut(DataIN, SerialCLK, MSBFIRST, cmd);  // transmit serial data 
digitalWrite(ChipEnable, HIGH);     // not need with pin-power
} 

After that you need is a function to position the cursor and a font stored in a byte array (in this example called ASCII[][5])

void LcdXY(int x, int y)
{
LcdWriteCmd(0x80 | x);              // Column
LcdWriteCmd(0x40 | y);              // Row  
} 

Then three short cascading functions let you send a string of ascii characters to the display:

void LcdWriteString(char *characters)
{
while(*characters) LcdWriteCharacter(*characters++);
} 
void LcdWriteCharacter(char character)
{
for(int i=0; i<5; i++){
LcdWriteData(pgm_read_byte(&ASCII[character - 0x20][i])); 
}
LcdWriteData(0x00);            //one row of spacer pixels between characters
} 
void LcdWriteData(byte dat)
{
digitalWrite(DCmodeSelect, HIGH);    // High for data 
digitalWrite(ChipEnable, LOW);  
shiftOut(DataIN, SerialCLK, MSBFIRST, dat);  // transmit serial data 
digitalWrite(ChipEnable, HIGH);
} 

Julians original implementation included a 500 byte 5×7 font.h file (which you can find at several locations) and  I’ve rolled that font array into some code based on his work and posted it to the Cave Pearl Project’s repo .  You will find lots of other examples based on the shiftout method on Github, but for some reason many people insist in retooling that tiny bit of code into, you guessed it, even more libraries

You’ll also find plenty of other drop-in font definitions with Google, but for small 5×7’s, it doesn’t take that long to roll your own by clicking the boxes in an online font creator. and then copying the byte pattern into a bin-hex converter. This also gives you the option of creating custom icons by using a non-standard bitmap for some of the less frequently used ascii characters. Keep in mind that you don’t need to store the entire alphabet if you are only sending a few letters to the screen (like ‘T+P’ or ‘RH%’, etc …) extracting only the letters you need to a reduced font array could save a lot of memory.

So your reduced font array could look something like this:

const byte ASCII[][5] =
{
{0x7f, 0x09, 0x19, 0x29, 0x46}  // 52 R
,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P 
};  

If you do that you’ll need to send text to the screen character-by-character because the ASCII based [character – 0x20] calculation won’t work any more.

I tweaked Julians code in a couple of important ways. First, I added PROGMEM to move the font(s) into the program memory space. Second, I added a method to print large numbers to the screen by repeating the same WriteString->WriteCharacter->WriteData pattern two times: once for the “upper half” of the numbers, and then again for the “lower half” of the numbers after re-positioning the cursor to the next line.

To make this limited large-number font I first composed a black & white bitmap for each number with a graphic editor, and then loaded that .bmp file into the LCD assistant program as described in this instructables tutorial.  I started with a bitmap that was 11 pixels wide, by 16 pixels high (though you can use any arbitrary size you want – just remember to leave the blank spacer row at the bottom) and for this two-pass ‘sliced-letters’ method I set vertical & little endian encoding in LCD assistant. I then put the top 11 bytes in the Big11x16numberTops[] array & the lower 11 bytes for each number in the Big11x16numberBottoms[] array.

It takes two passes to print each large number to the screen:

LcdXY (0,2);              //top half of the double-size numbers
LcdWriteBigStringTops(dtostrf(voltage,5,2,string));  
LcdXY (0,3);              //bottom half of the numbers 
LcdWriteBigStringBottoms(dtostrf(voltage,5,2,string));

And some slightly modified functions that refer to the corresponding number-font array:

void LcdWriteBigStringTops(char *characters)
{
while(*characters) LcdWriteBigCharacterTops(*characters++); 
} 
void LcdLcdWriteBigCharacterTops(char character)
{
for(int i=0; i<11; i++){
if((character - 0x2d)>=0){
LcdWriteData(pgm_read_byte(&Big11x16numberTops[character - 0x2d][i]));
}
}
LcdWriteData(0x00);  //one row of spacer pixels inserted between characters  
} 

Those number printing functions could be eliminated with better use of pointers, but I liked having the readability afforded by a few extra lines of code.

Reducing the number of control lines

The stuff I posted on Github assumes you are using a standard 6-pin arrangement shown in most Nokia 5110 hookup guides you will find on the web. But once I had that wrangled, I realized that it would be possible to reduce the number pins needed to drive the display.  You will have to tweak that default example by commenting out the RS & CS commands if you implement the pin-power changes I’m suggesting here… 

I use Deans micro-plugs  for multi-wire applications like this. The unused pin here is the normal Vcc, with the A0 pin-power supply indicated with a dash on the red line.

The shiftout method can be used with any pins you want, and most of my builds have A0-A3 available. With those dedicated wires the PCD8544’s chip select (CS) line can be connected to GND telling the screen that it’s always the selected device. This would be bad if it was connected to the hardware SPI lines shared with the SD card, but since we are using re-purposed anlaog lines, there is no conflict. One minor drawback is that since we are now using all the analog lines (I use A6 & A7 too) we can’t read a floating pin for RandomSeed().

Getting rid of the RESET line is a little trickier. The data sheet says that the RS line must be low while power stabilizes and should then be pulled high within 100ms of power on. Several people create an auto-reset situation by connecting the screens reset to the Arduino’s reset line. Others make the low-high transition with an RC network across the supply for a delayed rising signal. This can even be driven by the DC line (which is low in command mode and high in data mode) 

But I had something else in mind, since I wanted to power the entire display from a digital pin because the power draw with the display off is still about 70uA. This accumulates into a significant amount of wasted power over a multi-year deployment.

Reducing Back-light Current

OR … a photocell divider embedded in that clear epoxy would let you enable the backlight dynamically – with the appropriate mosfet for the connection type.

If you use the back-light in the default configuration, the screen can potentially draw up to 80mA (4 white LEDs at 20mA each). The back-light pin is usually connected to a transistor, so you can PWM all 4 LEDs at once for variable lighting control, but the peak currents are still too high for direct pin-powering unless you add some kind of series resistor.  A 10k pot gives you a simpler method to adjust the screen brightness, but I found that a 3k3 series resistor brought the total display current down to ~1mA with decent readability ( & blue LEDs are brighter than white).  Adding an in-line slide switch provides a way to completely disable the back-light for long deployments.  With the entire display safely below Arduino’s pin-current limit, you can then power it by writing a driver pin high or low in output mode.

#define n5110PowerPin  A0          // power the 5110 screen from pin A0 (RED)
#define n5110modeSelect A1         // 6.1.9 D/C: mode select (BLUE)
#define n5110SData A2              // 6.1.7 SDIN: serial data line (WHITE) 
#define n5110SCLK A3 ;             // 6.1.8 SCLK: serial clock line (YELLOW)
// lines not needed any more: 
// #define n5110RST  Now -> 4.7k to power A0
// #define n5110ChipEnable  Now -> GND

This gives you a way to perform a hard reset any time you want provided you tie the screens RS line to that switched power with a 4k7 pullup resistor, and re-run the initialization sequence after restoring power.

Boards with pin vias on both sides make it easier to add the RST & CE connections. The orange wires shown here thread through the housing to a slide switch which disables the backlight connection for surface deployments. This example connects power to the backlight, but with other screens you might have to connect BACKLIGHT to GND.

Enabling the screen now looks like this in setup:

pinMode(n5110PowerPin, OUTPUT);
digitalWrite(n5110PowerPin, HIGH);
pinMode(n5110modeSelect, OUTPUT);
pinMode(n5110SData, OUTPUT);
pinMode(n5110SCLK, OUTPUT); 
LcdInit(); // shiftout takes control of Mode, Data & SCLK lines at this point

To turn off the screen you pull all the control lines low:

digitalWrite(n5110PowerPin, LOW);        
digitalWrite(n5110modeSelect, LOW);                
digitalWrite(n5110SData, LOW);                
digitalWrite(n5110SCLK, LOW);                         

All four control lines must be brought low when you de-power the display or you will get a 13mA leak current through the controller after vcc goes low. Only the power pin needs to be driven high to start the screen later in the main loop, but don’t forget to run the init each time you power up.

My tests so far have shown reliable operation of pin-powered 5110’s through more than 8000 ‘long-sleep’ power cycles. In applications where I want to display data on the screen on for long periods of time,  I still depower the screen during the new sensor readings. This lets me know when the logger is capturing data and forces a periodic re-synch with the bus. I don’t know how long these displays would run continuously without that step, but I’m sure the coms would eventually go AWOL without some kind of regular reset.

Potting the Nokia 5110 display

Contraction of the epoxy created pressure burns on the LCD when I did a single large pour to pot the screen.

No screen is much use on our project unless it can withstand some bumping around in the real world, and ideally we want one that is dive-able. For several years my go-to solution has been to pot surface mounted LED’s and sensors in Loctite E30CL. I like this epoxy because the slow cure usually sets clear because bubbles have time to rise to the surface without a vacuum treatment. My first attempts looked great the night of the pour, but I got a nasty surprise the following morning. You see I usually mount sensors in small ½-1 inch wells, but the 5110 required a ring more than 2” in diameter. The contraction of the epoxy in this 10mm deep well caused pressure marks on the edges of the screen, and a significant brown spot in the center of the display where the text became inverted.

Successive small pours worked better. Here the back-light reflects off of the edges of the epoxy that seeped under the screen before it finished setting. The display in this photo has a 3k3 series resistor in the backlight circuit.

The next attempt was much more successful, as I built up the epoxy a few mm at a time like the layers of an onion. As each layer hardened, it protected the screen from the contraction of the subsequent layers above.  The trick was to bring the first pour to the base of the pcb, and the second pour to “just barely” cover the surface of the screen. The epoxy penetrates about 1/3 of the way into the display housing but this does not interfere with readability as those edges are invisible under natural lighting conditions. That epoxy is actually under the LCD, in the air gap between the transparent glass LCD sandwich and the white reflector plastic which holds the thin LCD in place between the metal rim and the PCB.  I’ll try future pours at different angles to see if that lets the space under the LCD fill completely. Looking at the epoxy penetration, it’s clear that the black edges in pour #1 were places where the LCD was compressed on both sides, and the brown discoloration was from pressure on top with no support below. 

Seawater caused severe fogging of the potting epoxy after only three days in service. Originally a concession to my aging eyes, the large fonts really saved our bacon when this reaction occurred.

The results for the second batch looked good and the screens worked beautifully with full marine submersion for about two days. Then some kind of chemical reaction with the sea-water started fogging the epoxy, and by day three I was glad I’d created the large number fonts because the 5×7’s were completely unreadable.   Once we were back home, a bit of elbow grease & 800 grit removed the foggy surface rind, and a layer of conformal coating restored clarity. I think my next builds will add the coating to the epoxy surface at the start.

I also noted some screen discoloration from pressure at about 3m depth, indicating that even a thick layer of epoxy bows too much for a deeper deployment. I’ve ordered some 1/4“ plexiglass disks to provide a surface with a bit more chemical resistance, and will post an update on how that works after the next fieldwork trip. I’m hoping that provides a bit more pressure protection too, but the shore hardness of the epoxy is 85, and PMMA (plexiglass) is only a few steps above that at 90. I might try polycarbonate as well.

Other Fun stuff:

There is so much more to explore with this screen, including live graphing libraries, and display controls so I expect it will keep me amused for a while since I can add it to any of the current logger builds. Several are out in the wild now for long term tests, and I’m currently working on a script to move those fonts (and a few other things) into the 328p’s internal eeprom. If all goes well I’ll release that ultra low memory footprint version of the code shortly. 

Cheers for now.

Addendum 2018-08-24

After several builds using the this LCD screen I finally got around to storing those font arrays in the Arduino’s internal EEprom. Works a treat, and frees a good chunk of PROGMEM space with very little change to the core functions. With fonts in EEprom, the remaining Nokia 5110 functions compile to a little over 400 bytes of program storage and 10 bytes of dynamic. (not counting EEprom.h) And that’s with three copies of the output functions because of the simple 2-pass method I’m using to display the large numbers.  A small price to pay for live data output on our loggers!

Addendum 2018-10-17

Because of that pressure problem with the 5110 I decided to try out the 0.96″ OLED screens which sell for about $3 on eBay.  When the first batch arrived I was pleasantly surprised by how well they stood up to pressure on their surface. Then I found the SPI version of the SSD1306 OLED can be driven by essentially the same code as the PCD8544 (with the exception of the init & XY functions which are specific to each controller).

Adding the SSD1306 OLED Screen to an Arduino Logger (without a library)

I’m connecting the OLED with the same analog line connections used for the Nokia, but I’ve added a delayed-high RC bridge because the OLED is pickier about the reset input than the Nokias. In hindsight a similar method is probably a good idea for the Nokia screens as well, though you might need to experiment a bit with the resistor/cap values to get the timing right.

Tutorial: Adding Sensors ( & Modules ) to Your Arduino Data Logger

This in-cave micro-climate recorder had pressure & temperature sensors mounted in little wells of Loctite E30-CL epoxy. This sensor potting method is described in our Pro Mini build tutorials.  Weather sensing stations are the most popular type of Arduino-based Sensor project on the instructables.com website.

This post isn’t another How-To tutorial for a specific sensor because the Arduino community has already produced a considerable number of resources like that You’d be hard pressed to find any sensor in the DIY market that doesn’t give you a dozen cookbook recipes to follow after a simple Google search. In fact, you get so many results from “How to use SensorX with Arduino” that beginners are overwhelmed because few of those tutorials help people decide which type of sensor suits their skill level. This post attempts to put the range of different options you can use with a Cave Pearl data logger into a conceptual framework, with links to examples that illustrate the ideas in text.

One thing to note before you start is that many modern sensors will only accept 3.3v inputs, so UNO based projects need to check if the sensor they want to use is 5v tolerant. Most sensors from vendors like Adafruit put regulators on their breakout boards to handle this 3.3v-5v translation, but you may have to place level shifters between some of the more advanced digital sensors and an UNO based logger. Occasionally you run into the opposite situation where the sensor requires 5v (or more) forcing Pro Mini based systems to do the same thing.

Also note: The first four videos from Tom & Jeff’s  sensor series (  Survey1&2, Datasheets & Interfacing ) make an excellent accompaniment to the material here.


Analog Sensors:

Some substances react to energy input by changing their physical or electrical properties. Arduinos can only read voltages, so to record these changes in the physical world some kind of circuit is needed to convert those properties into a voltage. Sensors that output continuously varying voltages in response to natural phenomenon are called analog sensors. Arduino pins A0 to A7 are analog input pins, and the ADC inside the microprocessor converts those voltages into a numerical value between 0 and 1023. It’s worth keeping in mind that those numbers are somewhat arbitrary depending on the reference voltage, and the behavior of your sensing circuit – so it’s up to you to figure out how to convert the raw ADC readings back into understandable units of the phenomenon you were trying to measure (like degrees Celsius for temperature, or m/second of wind speed, etc.)

A typical photoresistor divider from Sparkfun’s Voltage Divider Tutorial It’s worth noting that many LDRs go from 100 Ohm to over 1 MOhm. For a specific range of conditions, a common rule of thumb is: R-fixed = square root of (R-sensor min × R-sensor max)

The most common analog sensors are those that change their resistance in response to temperature (thermistors), light (photo resistors) or pressure (& it’s force / stretch / bend variants)  If a sensor varies in resistance, you can turn that into a voltage by adding a fixed resistor to create a voltage divider circuit.  The non-sensing resistor in the divider is usually chosen with a value near the midpoint of the sensing devices range.  For example, a photoresistor might vary between 1kΩ in the light and about 10kΩ in the dark, so a suitable resistor to pair it with would be ~5kΩ.  For analog sensors that change by really small amounts, more sensitive Wheatstone bridge arrangements combine 2 or 4 sensors in the same circuit to expand the delta, but it’s the same basic idea: you are converting a change in resistance into a change in voltage.

Divider methods are referred to as ratiometric because the output voltage from the circuit is some fraction of the supply voltage determined by the resistances of the components. If the input voltage is doubled, the output voltage is doubled, so these circuits work fine on 5v UNO and on a 3.3v Pro Mini. By default the Arduino ADC takes a reading by comparing it to the same rail voltage supplying the resistive divider, and sensor nerds like me get all excited about this because it means that variation in your power supply will have little effect on the readings. You can squeeze more sensitivity per bit out of the Arduino’s humble 10-bit ADC by changing to a lower internal reference voltage. However once the Aref is different from your supply, rail noise shows up on the divider output unless you squelch it out with a smoothing capacitor. (related method:  Capacitance Meter ) If your resistive sensor varies over a wide range, another common technique to increase sensitivity is to use a series string of resistors, and taking each junction to ground to  change the ratio of the voltage divider dynamically.

Some light sensors get used in conjunction with a emitter for reflectance and ranging applications. You can create a reasonably good color sensor by combining an RGB LED emitter with a simple photoresistor. And many red, yellow and green LEDs have a little known property: with reverse bias, they behave like a photo diode where the reverse current is proportional to the external light falling on them. So they can also be used to sense light because from a physics point of view, a rectifier diode, a light emitting diode and a photo-diode are basically the same device. While LEDs don’t produce the same signal strength as photodiodes designed for the job, they can be an inexpensive way to build spectrally selective detectors.  LEDs detect a much narrower band of light than they emit, having a peak sensitivity at a wavelength about 50nm shorter than their peak output wavelength.  Forrest Mims built some cool filterless photometers with LED sensors long before the mainstream media started waxing philosophical about ‘citizen science’.  (Also see: jpiat’s Li-Fi )

Most analog sensors are simple devices, but there are more complicated versions providing modified analog output, where some extra circuitry has been added to convert the highly non-linear response you get from typical resistance based sensors into the kind of straight y=m(x) relationship you get from a TMP36. This greatly simplifies the math required to convert your analog voltage readings into the real-world property you were actually trying to measure. Some analog sensors (like thermocouples) generate tiny voltages, but those signals may be so small that they need to be amplified before the Arduinos ADC can read them, so these analog sensors may also be sold with supporting electronic boards to boost the output.

Sensors can be mounted  inside a housing with a couple of layers of 3M Scotch Outdoor Mounting Tape. Sensors mounted this way have stayed in place for many years of deployment. The adhesive will sag somewhat under gravity if you expose your loggers to temps >55C.

At the top of the analog sensor food chain, there are complex Micro Electro Mechanical (MEMS) devices like accelerometers. In these sensors, silicon has been machined into very tiny physical devices made from springs, coils and flat sheets. These micro-cantilevers form capacitors that react to movement by changing a voltage and they are usually arranged in sets of three on x,y,&z axes. This means you need to read three separate input pins to capture a complete reading from the device. Since the Cave Pearl data loggers use pins A4 & A5 for communications with the RTC module, and A0 to track the main battery voltage, a complex analog sensor like the ADXL335 can use up all of the remaining analog inputs on the logger unless you build it with an Arduino that makes inputs A6 & A7 available. (the Pro Mini does, the UNO does not)  The limited number of analog input pins can motivate people to switch over to digital-bus sensors, though multiplexers provide another possible solution to the problem.

If you start with the project’s basic UNO logger script , adding a new analog sensor requires only three lines of code. Add

int AnalogSensorReading = analogRead(A0);  
// change A0 to match the input pin you connect the divider to

at the top of the main loop. Then add that new sensor data to the concatenated dataString which is saved to the SD card at the end of the main loop:

dataString += ", "; //comma separates new data from that already in the string
dataString = dataString + String(AnalogSensorReading);

That’s it. This simplicity is why analog sensors are usually the first ones people encounter when they are learning the ropes. Of course there are some advanced tricks you can play to supercharge Arduino’s humble 10-bit ADC, and you’ll find more useful tips over at Nick Gammon’s ADC tutorial.

Digital Sensors:

A bullet-proof de-bouncer from www.ganssle.com.    Compare this to the 5-key de-bouncing circuit from the IBM 705

Unlike analog sensors, digital sensors only output two voltages: High & Low. Usually the high voltage is the same as your power rail, and the low voltage is your system ground. In some ways that makes digital sensors easier to use, but there are some devils hiding in the details, and digital sensors cover the entire range from crude noob level devices to Gordian knots with more computational horsepower than the Arduino itself. Even the most complicated digital sensor usually has an analog sensor hiding somewhere at its core.

I group digital sensors into three conceptual categories:

Flippers,   Thumpers,  &   Thinkers

This is based on what kind of output they produce, rather than the complexity of their electronic circuits. And it’s not unusual for more advanced IC-based digital sensors to be as easy to use as the flippers & thumpers, because some kind soul has released a library that takes care of the gnarly low-level details.

1) Flippers

The humble push-button can be thought of as a crude pressure sensor that can be in only two states: open or closed. Add a couple of passive components for debouncing, and reed switches become the digital sensor of choice for event counting applications like the tipping-bucket rain gauges you find in weather stations.  IR break-beam switches are another common implementation with on/off output.

When you first look into digital sensors there seems to be a bewildering array of different ‘breakout boards’ and ‘sensor modules’ for the Arduino. These are often sold in bundles of twenty, thirty or even sixty different pieces. Once you get a closer look at them, you notice that many these cheap sensor modules look similar to each other:

That’s because most of those boards are simply a voltage divider connected to one leg of a five cent comparator circuit, with a twenty cent trimming pot setting the voltage on the comparatos other input:

These boards switch their high/low output when the sensor circuit voltage crosses the threshold set by the trimpot divider; and this changes the analog sensor voltage divider output into an environmentally responsive threshold alarm. It’s such a generic circuit, and you could connect other resistive sensor dividers and the board wouldn’t even notice. If you use these modules with the Cave Pearl loggers, look for boards that also break out that 4th analog pin so you can also read the sensor dividers output directly with the ADC if you want to.

Integrating simple on/off digital sensors to your logger code would use almost the same pattern as the analog sensor reading:

pinMode(PinNumber, INPUT);  // Declaring the pin as an digital Input
int DigitalSensorReading = digitalRead (PinNumber);

dataString += ", ";         //comma that separates new data
dataString = dataString + String(DigitalSensorReading);

These PIR sensors are usually 5v, but you can modify them for 3.3v operation.

Those eBay boards are somewhat redundant, since the Arduino has a built-in analog comparator that can do this job with pins D6 (reference) & D7 (sensor divider) .  However there are many high/low output sensors with more complicated circuits that are not as easily replicated.  Proximity sensors can have complex internal circuitry and perhaps the most common of these more-advanced-but-still-simple sensors would be the passive infrared (PIR) motion sensors that seem to occupy every corner of the modern world.  Adafruit has a fantastic tutorial on how to use them with an Arduino, which also demonstrates how the boolean HIGH or LOW value you get back from digitalRead() can be used with if statements to select different courses of action:

Reading = digitalRead (PinNumber);

if(Reading == HIGH)
  {   Serial.println("input is HIGH");   }

if(Reading == LOW)
  {   Serial.println("input is LOW");   }

All the I/O pins on an Arduino can be used as digital inputs  (including the analog lines) and the cool thing about that is the circuitry hidden behind those pins inside the microprocessor. The  Schmitt trigger on each pin has read-high vs read-low threshold voltages. This lets you replicate what those cheap eBay modules do by replacing the fixed resistor in your analog voltage divider with variable one, and then connecting the output of that divider to a digital input pin. Inferring resistance (or capacitance) by timing threshold crossovers on a digital I/O pin lets you make high resolution analog readings with digital pins because micro-controllers count time far more precisely than ADC’s measure voltage.

2) Thumpers:

Flippers change state slowly by microcontroller standards, and since they can be read with a single digitalRead() command, they won’t get you much cred at the local hacker-space. To get into the digital world’s caffeine-driven middle class you have to start working with Thumpers. These are sensors which convey information by varying the amount of time the sensor outputs a high voltage at a given frequency (called pulse-width modulation or PWM) OR by changing their output frequency with a fixed 50/50 split between on&off time (this is called frequency modulation or FM) .

This kind of output was common long before the Arduino existed because putting an analog sensor into the oscillator circuit feeding a 555 timer chip changes the pulses coming out the other end in proportion to the sensors resistance / capacitance / etc. You’d be hard pressed to find any environmental sensor that can’t be constructed with a couple of op-amps and a 555 (See: the conductivity sensing post for examples).

Three common methods for reading pulsed signals with an Arduino are:

  1. The pulseIn() Function
  2. External Interrupts
  3. Pin Change Interrupts

The output of the pulseIn() function is the time in microseconds that it took for the pin to go (or be) LOW, then go HIGH, then go LOW. This is the method of choice for PWM thumpers, and it is extremely easy to use provided the incoming signal is a clean square wave.
Unfortunately, it does not handle frequency modulation very well at the high end, because it’s susceptible to errors in timing when detecting the start and end of really short pulses.

Note: the RCWL-1601 is the 3.3v version of this board which is code compatible with the 5v HC-SR04. The 3.3v compatible board is also sold as the HSR04-P.

Range finding sensors often output PWM signals, and the most popular of those is the HC-SR04 which is used for collision avoidance by just about every Arduino-based robot on the planet. Self-balancing robots are one of the maker movements “killer apps”, and it doesn’t hurt that the SR04 transceivers just happen to look like a pair of eyes. There’s currently a bit of a turf war between the SR04 and slightly more expensive IR rangefinders. Ultrasonic energy is absorbed by soft materials, and SR04’s are susceptible to interference & multi-path issues in environments where there are lots of flat rigid surfaces. Infrared sensors have a much more focused beam so you get better results finding small objects…like the other robot you’re currently doing battle with.  (For more precise work you can go upscale to the VL53L0X Time of Flight distance sensors, and if money is no object, you can take that all the way to LIDAR.  To get the highest level range-finding merit badge of them all: MaxBotix Sonar sensors let you play the game under water…)

A code-side implementation for the HC-SR04 could be as simple as this:

digitalWrite(triggerPin, HIGH);       // send out (transmit) the pings
delayMicroseconds(10);                // give the sensor 10 ms to settle
digitalWrite(triggerPin, LOW);        // stop the outgoing pings
duration = pulseIn(echoPin, HIGH);    // listen for the echo and return time. 
Distance2reflectingSurface = (duration/2) / 29.1;
// Divide by 2 since the sound ping travels out & back = twice the distance
// Speed of sound in air = 340 meters per second or ~29 microseconds per centimeter
// Then divide the duration by 29 cm = distance in centimeters.

External interrupts handle both PWM and FM efficiently with the limitation that there are only two hardware interrupt lines on a typical Arduino. The Cave Pearl loggers are already using D2 for the RTC wakeup alarms, and that leaves only D3 available for hardware methods calling attachInterrupt().

It’s worth noting that there is also a near IR (940nm) sibling in the TSL family: the TSL245 though with IR sensors it can be tricky to extract temperature dependencies.

The TSL235R light-to-frequency sensor outputs a square wave (50% duty cycle) with a frequency proportional to light intensity. The TSL235 is self-contained, well calibrated, and very linear over the ultraviolet-to-visible light range of 320 nm to 700 nm. Calibration in manufacturing is something that most companies will try to avoid, and when you include the fact that this sensor works from 2.7-5.5v, you have a $3 sensor that’s nearly perfect for use with Arduino-based data loggers. Rob Tillaart has posted a simple bit of code that counts the interrupt pulses per second from this FM sensor over at the Arduino playground. It should be easy to integrate these functions into the Cave Pearl base code, and to modify it to work with any other FM output sensor. Data from light sensors usually requires post processing with somewhat complicated luminous efficiency calculations, but if you Google around you’ll find plenty of Arduino tutorials on those steps (also see: Insolation Models).

Only D2 & D3 support external interrupt signals by default, but with a little bit of extra code interrupt signals can be received on any of the Arduinos I/O pins.  Interrupts triggered from pins other than D2 & D3 are referred to as Pin Change Interrupts. Pin change interrupts are grouped into 3 ‘ports’ on the MCU. This means there are only 3 interrupt subroutines to handle input from all 20 pins. This makes the code somewhat more complicated than Rob Tillarts example, as it now needs to determine which pin triggered the ISR. That extra complication usually motivates people to use something like the PinChangeInt library for situations with a limited number of input pins.  Anemometers often use interrupt-based approaches because they work with output that’s so variable that it can’t really be classified as PWM or FM.

There are many great frequency counting libraries but it’s important to note the difference between ones which count the number of pulses during a fixed “gate interval” time, and those measuring the period of a single high frequency pulse.  Rob Tillart’s code uses the counting method, and this works well for relatively high frequencies, because many cycles are counted during the gate interval and this reduces error. At lower frequencies, very few cycles are counted, and the precision suffers, so measuring the elapsed time during a single cycle is a better option at low frequencies.

This image is from PJRC’s FreqCount Library page, which goes into more detail on the FM sensing process. It’s worth noting some of the other useful sensor libraries that Paul Stoffregen has released including: Onewire library for the ever popular DS18B20 temperature sensor, SerialFlash to simplify SPI memory builds, and their project blog is a font of other highly interesting things.

According to PJRC: Frequency Counting: works best for 1 kHz to 8 MHz and Period Measuring: works best for 0.1 Hz to 1 kHz.  There is some wiggle room there, and you should check your sensors data sheet to make sure your method matches the output range.

If you’d rather skip the libraries, you can get closer to the bare metal with the advanced timer over-flow methods described at www.fiz-ix.com and at Nick’s Timers & Counters page. Nick’s page describes a method to measure frequency with the input capture unit on pin D8. While that’s some pretty advanced code, it allows you to measure pulsed inputs to a resolution approaching the frequency of your system clock.

3) Thinkers

This Grove I2C hub connects several the sensors to the bus, so only one jumper set needs to be patched down to the logger platform. The mounting shown here was done with plumbers putty, which hardens quickly, and adheres well to most plastic enclosures.

Modern chip-based sensors offer high resolutions and complex signal processing capabilities that can be hard to replicate on the Arduino.  Most of these digital sensors send data using serial communication protocols over a common set of “bus” wires that are physically connected to all of the sensors. Serial protocols can be intimidatingly complex for beginners, but you rarely need to worry about the details because most of the vendors in the Arduino landscape release libraries to simplify the use of the sensors they sell. These libraries make it quite easy to work with complex sensors, and they are one of the reasons that companies like Adafruit and Sparkfun have such a dedicated following in the maker movement.

Newer versions of the Arduino IDE have a Library Manager which provides access to a large list of libraries with a one-click install. Sensors that have been used for a few years by the community often have a library available through the manager. However for new sensors, you usually have to download a library and manually place it in your

Username>Documents>Arduino>Libraries folder.

You can Learn more about installing Arduino libraries at:
Sparkfun :Installing an Arduino Library,    All About Arduino Libraries at Adafruit 
and  Installing Additional Arduino Libraries at Arduino.cc.

Note that these little bits of library code can be located in several different places on your hard drive but it’s best to keep the ones you add in your sketchbook folder because the Arduino Software (IDE) upgrades itself by first erasing everything in the program root directory: including any libraries that were stored there. Libraries in your personal document folders are not deleted during the Arduino Software (IDE) update process.

Here I’ve added a resistor which pulls the CS pin high to tell this ADXL345 accelerometer to communicate with the I2C protocol rather than SPI. The value of that pull-up resistor is not critical, so they can range from a 200Ω to 10kΩ.

The digital sensor protocols you are most likely to see used with an Arduino are SPI and I2C. It’s fairly common for chip-based sensors to support BOTH protocols and for those you usually add a pull-up or pull-down resistor to tell the chip which one to use.  SPI is preferred when fast communication is needed to move large amounts of data, but this is rarely the case for environmental monitoring. More importantly, the Arduino SD card libraries expect the SPI bus to be operating in Mode0. Adding a sensor to the Cave Pearl Logger which changes the SPI bus to one of the other three operating modes would prevent data from being saved until the bus was reset to Mode0. I have yet to find an SPI-only sensor that doesn’t have an I2C equivalent on the market.

 

I²C sensors are often the best choice for Cave Pearl Data Loggers.

The DS3231 RTC breakout module used on the Cave Pearl logger has a cascade port at one end, making a perfect attachment point for other I2C devices

The I²C bus or TWI (Two Wire Interface) allows a single master (the Arduino) to share communication lines with more than 100 slave devices (the sensors). Cave Pearls use an DS3231 RTC for timekeeping and the I²C breakout board carrying it provides 4.7k pullups resistors on the SDA and SCL communication lines. Each new I²C sensor gets connected to the same wires as the RTC board. If you have a good library to go with your sensor, about the only thing that might prevent it from working is a bus address conflict. Because I²C devices are all connected to the same wires, the Arduino needs a way to talk to only one device at a time. It does this using the I²C address of each sensor. (kind of like a phone number)

The first thing to do with a new sensor after connecting it to your Arduino, is run a bus scanner which queries every possible address to see if any devices are responding. If two devices are trying to use the same address, only one of them will show up in the scan, and sometimes neither of them will. Code for this basic utility for this can be found at the Arduino playground.

Running that bus scanner on a Cave Pearl data logger before any sensors are attached should produce:

This output screen tells us that the RTC breakout board is functioning and the I²C communications are working. It also tells us that the I²C “device addresses” are 0x57 ( this is the EEprom on that module ) and 0x68 (the DS3231 RTC).  Adafruit has compiled a list of typical I2C addresses for different sensors and scanning through that list for the two we are already using on the logger finds some potential conflicts:

0x57
MB85RC I2C FRAM (0x50 – 0x57)
MAX3010x Pulse & Oximetry sensor (0x57)  (uh-oh… this sensor will not work with our logger!)

0x68
This address is popular with real time clocks – almost all of them use 0x68!
AMG8833 IR Thermal Camera Breakout (0x68 or 0x69)
DS1307 RTC (0x68 only)
PCF8523 RTC (0x68 only)
DS3231 RTC (0x68 only)
MPU-9250 9-DoF IMU (0x68 or 0x69)
MPU-60X0 Accel+Gyro (0x68 or 0x69)
ITG3200 Gyro (0x68 or 0x69)

Some I²C devices have only one fixed address and but most offer a small range of different addresses that you can set by connecting different pins on the module to power or to ground. This will let you resolve an address conflict, but be make sure to make corresponding changes in your code if you change a sensor address away from it’s default. Most sensor libraries will have a modifiable parameter for the device address that is used to initialize the sensor. If you have a sensor with a fixed address, you will only be able to hook up one of those sensors to the logger at a time unless you add an I2C multiplexer to resolve the address conflict.

Once you’ve confirmed the sensors show up on a scan of the I²C bus, the next steps depend on the complexity of your sensor. I²C sensors that only do one thing can often be read with a minimal amounts of code after the #include <Wire.h> statement embeds the TWI library that’s built-in to the IDE . You often see this with a basic temperature sensors like the TC74

//All I2C coms start with a handshake transaction with the device @ address
Wire.beginTransmission(address);
Wire.write(0);  //Sends a bit asking for register 0, the data register of the TC74
Wire.endTransmission(); // nothing is sent over the wires until wire.end is executed

//then you request the temperature data from the TC74 sensor
Wire.requestFrom(address, 1);  //this requests 1 byte from the specified address
int celsius= Wire.read();

For sensors that do more complicated things there can be many more steps, especially during sensor initialization when you might have to configure the bit-depth of the readings, the sampling speed of the sensor, and a host of other options. I’ve posted an extensive tutorial about this for tech-savvy users (see: How to configure I2C sensors ) but for beginners the best approach to adding a new I²C sensor is

1) Find a suitable tutorial by typing “How to use SensorX with Arduino” in Google or by reviewing the tutorials available at: Hookup Guides at Sparkfun, the Sensor tutorials at Adafruit, or search for code examples and links at the sensors forum.

2) Download the associated sensor library and install it into your Documents>Arduino>Libraries folder

3) Add #include <SensorLibrary.h> to the start of your code

4) Initialize the sensor in startup following the code examples for your tutorial located on GitHub

5) Read the sensor in the main loop

Most libraries are written to provide InitializeTheSensor() and ReadTheSensor() functions that so steps 4) & 5) often end up adding only couple of lines to your code.

As a simple example look at the MCP9808 temperature sensor from Adafruit:

The Tutorial   &   The example code on Github

That script is quite small because the library condensed a lot of I2C handshaking down to

tempsensor.begin();  // initializes the sensor
tempsensor.readTempC();   // reads the sensor

For an example of a library driving a more complex sensor, look at the BMP180 pressure sensor from Sparkfun

Hookup guide   &  The example code on Github

There’s an important step at the start of the code:

#include <SFE_BMP180.h>
#include <Wire.h>
SFE_BMP180 pressure;    // creates an SFE_BMP180 object, called pressure
#define ALTITUDE 1655.0 // Altitude of SparkFun's HQ in Boulder, CO. in meters

In setup, theobjectname. appears before each call to library functions:

pressure.begin()       //initializes the sensor in setup

And then in the main loop, the sensor uses a four step process to complete one reading.

status = pressure.startTemperature();
delay(time);
status = pressure.getTemperature(T); 
// the temperature must be read before the pressure!

status = pressure.startPressure(3);  // with oversampling set to 3
delay(time);
status = pressure.getPressure(P,T);

Multi-step read procedures like that are quite common, because it takes time to capture high resolution readings, and in this case the temperature has to be sent as a correction factor for the pressure reading.

Then there are two more functions in the example program worth noting:

p0 = pressure.sealevel(P,ALTITUDE);
a = pressure.altitude(P,p0);

The pressure sensor returns absolute pressure, and Sparkfun have provided extra code in their library to do calculations which convert that number into sea level equivalent & altitude equivalent numbers.  That Sparkfun code example is pretty typical of what you get with libraries for more complex sensors, and it should not be too hard to just open two IDE windows to copy and paste the required pieces of code from the Adafruit & Sparkfun examples into the basic Cave Pearl Logger script