As I wait for a purple package from OshPark containing the Dev-Rev2 Healthy pH PCBs, I’m getting ready for diagnostic testing of the Healthy pH Shield.  I should have defined these tests prior to board layout.  It is a great way to see if the circuit functionality and test points exist to get to what the goal of the Shield – reading the pH value – actually is!  For example, instead of randomly putting in test points where I think it is a good idea to do so, I’m putting them in because they are a requirement to run a test.  Another benefit of doing this first is not duplicating test points or having unnecessary test points.

The Goal

The goal of this post is to identify tests that I will run to determine if the Healthy pH Shield works.

Additional Material

The SPI test that I plan to run on Dev-Rev2 can be found at the Healthy pH Dev-Rev2 GitHub repository.  This post revolves around the SPIDiagTests.cpp file.  Hopefully I commented it enough!

Thanks to Those That Went Before

  • Jon Black wrote a menuing system for the Arduino that supports multiple layers of menus.  Each menu can have multiple items.  His code (available at this github repository) made it extremely easy to add a structure to running the tests through the serial monitor.  That folks like Jon make their code available is a testimonial to his talents as well as one of the (many) benefits of using the Arduino platform.  Thank you Jon.
  • Chris Gammell for all that I have learned about electronics from him as well as walking us through the MCP3901’s SPI interface during the Contextual Electronics course.  I had been intimidated by going into the MCP3901 data sheet and reading/writing over SPI. Chris walked us through this and now I feel confident to be able to read/write to any device that supports SPI by reading the data sheet.

The Tests

The tests I want to define and run should tell me what doesn’t work in the shortest amount of time.  Tools to be used include a DMM, Oscilloscope,Logic analyzer, and Arduino Sketches.  

Tabel of Tests

The first thing I did was to create a spreadsheet identifying the diagnostic tests I will run.  

Schematic Name Tool Test Expected
Arduino shield sees Ard 5V&3.5V Power relative to Ard GND DMM Shield stacked on Ard. pos probe in Ard pwr pins of shield. neg probe in Ard GND ~5V and ~ 3.5V reading
  RGB LED works Sketch Sketch turns on RGB LED to a few colors RGB LED lights up when sketch turns on a color
WallWart Power from WallWart relative to AGND – before diode scope Shield plugged into WallWart (6-12V). pos Probe in TP20 (pre-volt reg) neg in TP10 or TP19 voltage in jumping around value of the (6-12V) wall wart
  Power from WallWart relative to AGND – after diode scope pos Probe in TP 9 neg in TP10 or TP 19 same as above.
  Regulated power V+_WallWart Scope pos Probe in TP8 neg in TP10 or TP19 smooth 5V
SPI SPI Read config Sketch,logic analyzer Sketch r/w config data config bytes match expected values from MPC3901 data sheet
Temperature AC signal relative to AGND Scope pos Probe in TP11 neg probe in TP10 or TP19  
  SPI Read thermistor Sketch Sketch reads data channel for therm and translates to C and F temp readings around 60 – 80˚F
pH pH Probe GND (VGND) relative to AGND DMM pos Probe in TP18 neg probe in TP10 or TP19 https://bitknitting.wordpress.com/2014/08/30/exploring-floating-ground-for-the-healthy-ec-shield-circuit/
  pH probe non-inverting input signal relative to VGND scope ph probe connected to TB. pH probe submersed in ph 7 calibration solution pos Probe in TP17 neg probe in TP18 https://bitknitting.wordpress.com/2014/08/30/exploring-floating-ground-for-the-healthy-ec-shield-circuit/
  output from pH Op Amp relative to VGND scope (pH probe same as above) pos Probe in TP1 neg probe in TP18 same signal as above (buffer applied)
  SPI Read pH Sketch (pH probe same as above) Sketch reads data channel for pH and translates to a pH value Something within range of pH 7.
Pumps 5V from Ard relative to GND DMM pos probe in TP14 neg probe in Ard GND smooth 5V
  Down Pump HIGH relative to GND Sketch,scope pH Down pump hooked up to TB and ready to pump. Sketch sends analogWrite() to pump the pH DOWN…pos probe in TP12 neg probe in Ard GND I’m thinking I should see a digital 1 in the scope
  When down pump HIGH relative to GND, current flows Sketch, scope using the same setup and sketch as above, pos probe goes into TP15 neg probe goes to Ard GND  
  repeat two tests above for Up Pump      
  Turn on/off down pump Sketch using the same setup and sketch as above, validate that the pump turns on and off pumps for the amount of seconds specified by sketch
  Turn on/off up pump      

The test in yellow will be my starting point when running the diagnostics (and where I must eventually end up!)  I do not expect reading the pH will pass on the first try.  Most likely one or more of the circuits was not designed correctly.  Once I figure out what doesn’t work (and why), I’ll update the Healthy pH Shield design and layout to fix what I have found doesn’t work.  That effort will be the start of Dev-Rev3.

Analog Tests

The analog tests rely on readings from either a DMM or Oscilloscope and the test points.  Viewing test points from the schematic (versus the layout/pcbnew in kicad) gives a better feeling for what is being tested (and hopefully why).

Digital Tests

My work in progress is under the firmware directory of the Healthy pH Shield GitHub repository (link).  I am using Xcode 5 for my IDE.  In order to do this, I use embedXCode (link).  The Arduino IDE is fine when I want to write a sketch that has a few functions.  XCode is terrific as the firmware gets more complex.  I find menuing/UI to be tedious without a framework, so I use Jon Black’s Arduino menuing system (GitHub link).

Once I set up the menu framework for the diagnostic test harness, I started coding the tests for transmitting data over the SPI bus.


The SPI bus is well documented within the MCP3901 data sheet (link).  The test harness will read the current settings contained in the CONFIG1 and CONFIG2 registers, change some of the values, read the modified contents, then reset the registers to their default values.


Prototype Testing

breadboard proto side view MCP3901     pins On SSOP-20

 Previously I soldered an MCP3901 with a 20-SSOP footprint  onto a SSOP-to-DIP adapter I had bought from Sparkfun (link)… I had put this on a breadboard with the crystal and caps which are needed by the clock.  

Crystal on MCP3901 schematic

Now this is frustrating!  It used to work (honest really….) and now I transmit the right command over MOSI, but do not receive what I expect from MISO. 

Setting up the SPI pins

First thing I did was review the wiring of the SPI pins going to<->from the Arduino<->MCP3901.

from Table 3-1 of the MCP3901 data sheet (link),

SPI pins from Table 3-1

pin 20 = SDI, pin 19 = SDO, pin 18 = SCK, and pin 17 – CS.  These are the pins I will need to test the part of the test harness that reads and writes to the CONFIG1 and CONFIG2 registers of the MCP3901.

Sadly, I can’t remember which Arduino pins are defined for SPI, so once again I go to a handy-dandy picture:
picture of Arduino SPI pins

Now I can wire the Arduino and MCP3901 together.

Checking SPI traffic

What command ‘is really’ being transmitted on the MOSI line?  The best way to see this is using a Logic Analyzer.  I really like Saleae’s logic analyzer (which I discussed earlier in this post).  After hooking up the logic analyzer, I send a control byte (see the MCP3901 data sheet, section 6.2):

MCP3901 Control Byte

All the info needed to figure out how I came up with a control byte value of 0X15 for reading CONFIG1 and 0x17 for reading CONFIG2 is contained in the MCP3901 data sheet.  I expected to get the default values defined in section 7.6 of the data sheet:

Config Values

Based on the table above – for CONFIG1, I’d expect 0001 0000  (0x10).  For CONFIG 2, I’d expect 0000 1100 (0X0C)

Results from Logic Analyzer

At first I was not able to get any values from the Logic Analyzer.  It turns out I needed to slow down the clock, so added:


before SPI.begin().

Here is the traffic I get when I try to read CONFIG1:

SPI Output FF Miso

CS looks right (pulled down while data is transmitted for this device), clock looks great, MOSI looks right…but…sigh…0XFF for MISO.

And GUESS WHAT – ARGH!!! I did not have pin 11 (digital GND pin) attached.  OK, I get confused easily… and now….my YIPPEE! moment…here is a screen shot of MISO for Config2:

Config 2 SPI Works

One thing that seems weird to me (but then again, it took me a l-o-n-g time to figure out about pin 11 🙂 ) was sending to SPI.Transfer().  In order to get the 0X0C, I had to:


    char register_value = SPI.transfer(0XFF);

Given that this is a transfer (read and write at the same time), I was expecting:

char register_value = SPI.transfer(SPIReadControlByte);

to work…hmmm….


Whew!  Well that was exciting…a breadboard prototype using the MCP3901 and required crystal.  Now I can finish writing Arduino tests for the MCP3901.

SPI Write Test 

The test will change the ADC width bit from the default of 16 bit to 24 bit by setting the CH0 and CH1 width bits of CONFIG2 to 1.  Thus, the value in the CONFIG2 registry goes from 0x10 (0001 0000) to 0x1C  (0001 1100) (see register 7-6 in the data sheet ).                                                                                        



Thanks very much for reading this far.  Please find many things to smile about.