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 of this post is to identify tests that I will run to determine if the Healthy pH Shield works.
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 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.
|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.
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).
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.
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.
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),
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:
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):
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:
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:
Here is the traffic I get when I try to read CONFIG1:
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:
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);
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.