Apologies to anyone who has read a lot of this already, I just couldn’t work out how to turn an existing blog into a Project14 entry.  If you have read any of those posts, then much of this information will be familiar but there is new detail in this Project14 entry:

  • Up to date description of the modules and workings as it has evolved since my early day thinking.
  • Description of software available to drive the board and form the basis for any test application you may wish to write.
  • Videos that walkthrough the board and show various tests.
  • A set of commands that are included in test scripts that fully drive each board feature, under serial monitor input, that can be used as simple applications.


Background Information

For background information on the idea, component selection and prototyping please see the following posts.  The ICB has evolved since the older blog posts were made and this write up is more up to date.



To sum up the ICB in a couple of short sentences, this test instrument provides a set of regulated power rails, and driving and test signals to help prototype and test circuits that are connected to it.  It can also be used to control built modules (that can interface to it.)  I had thought that the control board would be encased with downstream ‘controlled’ circuitry but I’ve since revised that approach as I describe below, and thus it is now intended as a standalone module for a set of complementary modules (such as a DC load module) that can be plugged together as needed for the task at hand.  The block diagram below may help you visualise this a little better.

Modularisation of the ICB and ideas for driven modules.  The interconnects will be pluggable cables as needed, e.g. 25183422518342 and 17738641773864 with ribbon cable, or maybe one ended with breadboard hookup wire.


The idea for this project arose from a desire to create a DC Electronic Load.  I’d already had a reasonably successful attempt at a power supply and wanted to build something complementary.  As I started to think about and research creating the DC Load, it struck me that much of the control circuity could be modularised to create something that would work generically for many test instruments and also for driving power and signals into test circuits.


So I separated out the control elements and expanded them with other features that I felt would be useful for this sort of test instrument.  I also set myself additional requirements:

  • Provide protection for the expensive components that would form part of the design: MCU, LCD and any connected PC.  This actually stemmed from work that Jan Cumps and Peter “The Breadboard” Oakes did with their electronic load and provisioning isolation protection.
  • Modularise it to the extent that it could be constructed over time or even with only the minimal amount of features actually wanted (including the isolation.)
  • Make it easy to build, i.e. no tiny components that required extensive magnification and hands as steady as granite mountains.
  • Make it cheap to build, not just by allowing features to be excluded, but give choice over the MCU and LCD/UI to interface with it.


As part of modularity and keeping it cheap, I further separated the power elements that would drive this board: this means the ICB consists of a Power Board and a Control Board.  This allowed me to keep the size of PCBs designed within the threshold for prototype manufacturer by the Chinese manufacturer I use (JLCPCB.)  It also gives choice in providing power which could be achieved with a bench PSU if required.

The ICB consisting of A Power Board and Control Board, fully populated


Walkthrough of the ICB

The fully populate boards with external components connected.  Note 1: these links can be removed to facilitate easier testing as I show when I cover that topic later.  It allows the connected MCU to be safely powered through its USB port without 'fighting' against an alternate power source.


The video below walks through the features of the board and shows the action of the power source switching.  I'm not very good with videos I'm afraid so be easy with me!



Power Board - Provisioning Power

The control board, as fully featured, requires the following regulated power rails: +12V, +5V, -5V and an isolated +5V.  These rails can be sourced from a 15V 0.75A AC/DC converter (wall wart) or a bench PSU set to limit at those voltage/amperage levels; without an LCD the control board consumes 84mA (with Arduino Mega connected) but addition of an LCD could increase current requirements to as much as 0.5V.

KiCad schematic of the power board.  All components are fully described with datasheets, supplier and manufacturer part numbers apart from the most generic capacitor and resistor components.


J1 and J2 are power source connectors.  J1 is for a centre positive 2.1mm DC jack and J2 for a +ve and -ve connector from an external PSU.  The DC jack takes priority when plugged in and protection is provided to J2 through diode D4.  As designed, the power board is expecting 15V as the source but up to 18V could be used although it would require changes and considerations as noted on the schematic; in any case ensure that the source is capable of supplying at least 750mA to allow some overhead and flexibility for a fully featured build.  Because there will be some manual plugging and unplugging as well as source switching, a TVS is provisioned at D2 to protect against any over voltage from bouncing and ESD.  SW1 is a simple SPST to switch power into the circuit and C4 provides some bulk capacitance for ripple on the supply (particularly when a wall wart is used.)


The 12V rail is produced from a LM7812 - my preferred choice is the TI UA7812 as I seemed to have less trouble (actually, no trouble) with oscillation on the output.  This rail is directed at the Control Board but is also used as a source for the +5V and -5V rails in order to prevent too much of a voltage drop on the regulators for those rails and thus problems with power and heat.


The +5V rail is produced from a LM7805 (again, preference for a TI part, UA7805.)


The -5V rail starts with a TC7662B charge pump which inverts the incoming 12V into -12V before passing into a LM7905 to create the regulated -5V.


For the isolated +5Vdd rail, the incoming 15V is passed through a DC/DC isolated switching supply.  The output of this is a regulated +5V capable of providing 600mA of current, sufficient to power most MCUs with LCDs.  There are many pin compatible alternatives some of which will provide more current.  By using such an isolated supply it ensures that the expensive components attached to the control board are protected against serious over voltages back-feeding through the board.  I’ve also made provision in the circuit for a MCP1826S 3.3V/1A LDO so that a MCU requiring that voltage can be used: all components on the Isolated side of the control board will operate at either 3.3V or 5.0V without change.  Note that the Control Board can be supplied with +5V OR +3.3V but not both - to emphasise this it only has a 2-port connector on it.


The values of capacitors, ferrite beads and inductors were deduced from datasheets and prototyping.  Most of those on the schematic were settled on after trying different values to determine the impact and final choice gave the best balance of power quality on the output rails with standard sizes and availability.  All regulators are protected with a reverse voltage diode.


Power Board PCB

The KiCad PCB design


This is a 2-layer board, 100mmx50mm, with power/signal routing on the top layer, and ground routing on the bottom layer.  All parts are through-hole and while it is compact, it’s very easy to populate.  The pads labelled “TPxx” are designed as test points.   The output connectors J3, J4 and J6 are aligned directly opposite their counterparts on the Control Board PCB to make it easy to connect up (or more importantly, to make it harder to misconnect.)


The TP are also useful as ‘hack points’ which can be used to route alternate power around.  For example, let’s say you have no need to provide a fan (at 12V) so don’t need that power rail and leave it totally unpopulated.  You could power this board from a 9V wall wart and route a wire from the left pin of R1 to TP1 pin 2 (labelled +12V) and L2 pin 2 to power the +5V and -5V rails.  The isolated DC/DC converter at U6 is capable of operating at 9V.  This would give you an unregulated 9V on J3 pin 3 which may still be sufficient for a Fan if you chose to add one later - I haven't checked!


Control Board - Provisioning Driving and Test Signals

The Control Board contains the functional features to create a useful set of signals and application functionality to create test applications that can drive plugged modules or test circuits on breadboards.  Specifically, the board provides the following features, in no particular order, all of which are optional:

  • 4 DAC Channels: 16-bit buffered channels with 0V to 5V range
  • 4 ADC Channels: 16-bit buffered channels with 0V to 2.048V range to be used for signal measurement
  • Real Time Clock/Calendar (RTCC): battery backed clock with 2 alarms, 1Kbit EEPROM and multi-function pin to generate square waves at 4 frequencies: 32.768kHz, 8.192kHz, 4.096kHz and 1Hz.
  • 1Mbit EEPROM: to store configuration or other data as required.
  • Fan Control: MOSFET driven fan controller
  • 4.096V Reference Voltage: trimmable reference voltage.
  • USB/UART controller: to allow for serial (e.g. SCPI) interaction with the board from a PC.
  • Off-Board control including an application power switch and rotary encoder: for testing and interaction.
  • Board I/O: to link to downstream circuits and modules.

It may be easier to envisage with this block diagram:

Control Board features and interactions

KiCad schematic of the Control Board.  All components are fully described with datasheets, supplier and manufacturer part numbers apart from the most generic capacitor and resistor components.

That's a little difficult to see in detail so I will describe each feature separately.


Digital to Analog Converter

The DAC is the Analog Devices AD5696R, a 16-bit, 4 buffered channel IC.  It has low error specifications, particularly with the use of its internal voltage reference which I have gained to 5V - note that this has better specifications than the 4.096V Voltage Reference on the board.  DAC channels route directly to the Board I/O module.


The RESET pin works in conjunction with the RSTSEL pin.  RSTSEL drives the power-on reset function and, as configured, all channels will start up to zero scale; when pulled LOW, RESET will actually reset the DAC outputs to the level determined by RSTSEL.  This pin is available to the off-board control to manage.  When the board powers up, RESET will be held LOW automatically by the output from the Digital Isolator - as mentioned earlier, this will prevent the DAC from powering up properly - so before actually using the DAC, this pin must be pulled high and a delay incurred for the IC to correctly power up to its zero scale level (the delay is sufficiently allowed for by the power up time of any connected MCU.)  The pin can be subsequently be pulled LOW and then HIGH to reset the DAC.


Internally, the DAC has two registers for each channel.  Values to output on the channel are written into the Input Register.  This register is then copied to the DAC register and the output generated.  When that copy occurs is controlled by the LDAC pin (Load DAC): only when it is pulled LOW will the copy occur and the output adjust to its new level.  If constantly held low, all output is 'instantaneous', i.e. a write into the Input Register is copied to the DAC register immediately. When LDAC is high, that copy does not occur.  This will allow each channel to be updated (serially, through an I2C command) and then all channel outputs changed simultaneously by pulling LDAC low.  This allows for synchronisation of output.  Channels can be masked from LDAC operation so it's possible to use this pin over a subset of channels.  This pin is available to the off-board control to manage.  It's also possible to directly bypass LDAC and write to the Input Register and transfer straight to the DAC register in one operation.


I have a functional Arduino library and script that can be used to operate the DAC and form the basis of an application you may wish to write.  In the linked post, I describe the results of characterising the DAC channels for accuracy and that shows that all channels are accurate to around 500uV which is excellent in my opinion.


Analog to Digital Converter

The ADC I've chosen is the MCP3428 from Microchip, a 16-bit, 4 channel Delta-Sigma IC; it can actually output a conversion at 12-bit and 14-bit resolutions with increasing samples per second.   It’s also possible to apply a gain to the incoming voltage with a programmable gain amplifier such that low voltages can be boosted for accuracy: the boosted voltage will not exceed the 2.048V limit though.  It uses its own internal Voltage Reference limiting inputs to +0V to +2.048V - I may have missed a trick and not provisioned at least one of the channels as differential (-2.048V to +2.048V), but the IO on the board was getting very crowded.  Perhaps a future revision will include this, particularly as I now know how well the board works in practice and I can make room.


Each incoming ADC connection is straight from the Board I/O module and is buffered through a rail-to-rail OpAmp, a TI OPA4192, with a Low Pass Filter between the OpAmp and the ADC input, as recommended in the datasheet.   I've also provided input protection to the ADC (OpAmp) in the form of fast switching, low current leak diodes, BAV199, that will route any high +ve or -ve voltage away from the OpAmp.  The maximum input limit is 5V and voltages above that are routed to the +5V rail.


I have a functional Arduino library and script that can be used to operate the ADC and form the basis of an application you may wish to write.  In the linked post, I describe the results of characterising the ADC channels for accuracy and that shows that all channels are accurate to around a few uV which is excellent in my opinion, particularly as most readings are likely to be in the mV and above range.


Real Time Clock Calendar

The RTCC is the MCP79410 from Microchip, a second-accurate, leap year compensated, clock/calendar IC: sub-second accurate RTCC ICs seem expensive and probably not necessary for this type of application.  As well as keeping track of time, it provides for two alarms and a Multi-Function Pin.  The alarms can be set independently and as well as storing notification of a raised alarm in a retrievable register can also change the MFP state (HIGH or LOW as desired.)  Alarms can be masked to fire on seconds, minutes, hours etc. and do not fire on a specifically set time.  The MFP pin is available to the Off-Board Control so can be monitored through an interrupt-enabled pin to flag the alarm as soon as it raises (I have a test script demonstrating this.)  The MFP pin can also be used to output a square wave at 4 frequencies: 32.768kHz, 8.192kHz, 4.096kHz and 1Hz.  Finally, the MFP pin can be used to output a HIGH or LOW signal but there is a priority of operation order: Square wave output overrides Alarm signalling which overrides general output.  The MFP routes to the Board I/O so is available to downstream circuits and can be used, for example, for timing or switching control.


It is possible to digitally trim (calibrate) the RTCC by either monitoring a square wave on the MFP pin with highly accurate frequency generator or by monitoring time drift over a significant period of time - both ways are described in the datasheet.  Having done this myself, the RTCC was still accurate to under a second after a month of operation.


The RTCC has 1Kbits of EEPROM available to store data as well as 64 bits of SRAM.  The latter is volatile and stored data lost when power is removed.  However, I have provisioned a backup battery which maintains both the time and SRAM contents when main power is removed.  Alarms and MFP output is non-operational on battery power.)


I have a functional Arduino library and script that can be used to operate the RTCC and form the basis of an application you may wish to write.


As an aside, the testing really showed how poor the Arduino clock is.  I initially tried testing the RTCC drift over 1 hour using the Arduino clock to measure the elapsed time.  It reported 5 seconds out after 1 hour which is so great it's not trimmable in the RTCC!  Doing the same test using the NIST website showed zero drift over 8 hours, with the on board battery backup for the majority of that time.  I guess the Arduino clock is accurate enough for most circumstances but using the RTCC will be significantly more accurate, especially if the alarm is used to trigger elapsed time notifications.




I am using a CAT24M01W, a popular 1Mbit EEPROM.  It’s intended purpose is to store data, e.g. configuration values, lookup tables etc.  There’s not really much to say really: it stores bytes in pages and has sequential write/read properties.  The library I have created (actually, modified from sources available on the internet) does not allow for page overflow overwriting of values so inadvertent data loss won’t occur.  If you were thinking that a write would progress across page boundaries, you'd be wrong: it actually wraps around to the start of the page - so if you were to write 9 values to address 0 of a page, you'd find that your 9th byte would be in address 0 and your first byte would be lost.


I have a functional Arduino library and script that can be used to operate the EEPROM and form the basis of an application you may wish to write.


Fan Control

I've made some assumptions here:

  • 12V supply required
  • up to 0.5A current drawn
  • two wire
  • Activation driven by the MCU

There are 388 (as of writing) on the UK.Farnell website and a wide range of operating current that meet these assumptions so they seem reasonable.


The 12V supply is fed out to the connecter and the diode is there to deal with any back EMF.  A MOSFET is used to actually control the turning on/off of the fan by changing the voltage on the gate HIGH (on) or LOW (off).  The Off-board Control has access to the FAN pin to achieve this.  I envisage a scenario where a thermocouple routes a voltage to one of the ADC pins which is used to automate the activation/deactivation of the fan with a suitable hysteresis.


4.096V Voltage Reference

I’m using the venerable TI REF5040 to generate a 4.096V Voltage Reference.  The additional components are used for noise reduction as described in the datasheet with the exception of RV1.  Here, I’m used a trimmer so that the output can be adjusted by up to around 15mV to take account of any load or voltage drop over traces and wires.  Nothing on the Control Board uses this reference so it’s purely for the use of downstream circuits and modules.


I2C and Digital Isolators

The dotted red line is the isolation barrier and I term the left side, Side A, and the right side, Side B.  I have two isolators to cover what I need and the I2C isolator is self-explanatory.  The digital isolator uses a modulated RF carrier rather than light like an Opto Coupler - note not all SI8661 chips are created equal so if you look for an alternate make sure you take care of channel directions and load current.  The channels are fixed direction but I only need one input direct from Side B of the board - the MFP alarm signal from the RTCC.  On Side A, the global labels connect direct to the Off-Board Control Module; Side B global labels connect direct to the relevant IC or module:

  • LDAC_A|B: This is a control signal for the DAC that synchronises the output of channels (Load DAC).  By pulling high, the Input Register for channels can be updated with a new output value without actually changing the DAC Register value, which drives the output value; when it is pulled low the new values are transferred to the DAC Register and output simultaneously.
  • PWRSIG_A|B: A passthrough to the Board I/O Module of the current state of the application power button - High is Power On; Low is Power Off.  That’s the intention but it could be used to signal anything.
  • FAN_A|B: A signal to the Fan Module to turn the fan on (High) or off (Low).
  • RESET_A|B: A reset signal for the DAC that sets all the outputs to the power up value - zero in the case of this board.
  • RTCC_MFP_A|B: A signal from the RTCC module indicating that an alarm has triggered; actually it passes the state of the MFP pin so could be the square wave, alarm or general output.


At startup, the digital isolator will default to output LOW on both sides:

  • LDACs: any DAC output change in this state will change immediately.
  • RESET: the DAC will not power up correctly.  It will require a positive action on behalf of the Software Library to resolve this but it isn't an error as described in the description of the DAC above.
  • PWRSIG: indicates application power is off.
  • FAN: Fan is off
  • RTCC_MFP: No alarm is triggered.

So, apart from RESET, this is fine.  There's no way around this start up behaviour if I want the ability to control the device RESET as the LOW output from the digital isolator will override any pull up resistor.


There is one spare digital isolator pin that can be ‘hacked’ to suit any purpose not currently catered for.


USB/UART Controller

I added the ability to drive the connected MCU through a USB/UART connection so that it can be controlled from a PC using, for example, SCPI commands.  I selected the MCP2221A from Microchip for this purpose as it can run from a 5.0V or 3.3V supply.  Jumpers JP1 and JP2 are used to ensure that the right voltage is selected:

  • 5.0V: JP1 pins 2 and 3 connected; JP2 pins 1 and 2 connected
  • 3.3V: JP1 pins 1 and 2 connected; JP2 pins 2 and 3 connected

Under USB Host power provision, the IC is only powered when it is connected to a PC.  The IC will act as an I2C master which is why those pins are not connected - we don’t need two of them!  Additionally, the GPIO pins aren’t used as I saw no use for them on the isolated side of the board.


Be aware that when a USB host is connected and the jumpers configured for 5.0V supply, then the TX pin will supply around 2.2V.  This is sufficient to wake the ATMega processor on an Arduino and route through to VDD; it’s not sufficient to fully power the Arduino though so there should be no issue.


Off-Board Control (including application switch and encoder)

Off-board controls are all on 'Side A' of the isolation, with power provided by the DC/DC isolator.  I want to be able to drive this from any suitable MCU so I'm not providing header connectors for any specific device.  Additionally, as mentioned under the Power Board, it is possible to provide 5.0V or 3.3V to side A as determined by the MCU power requirement.  I’m actually using an Arduino Mega 2560 because I want the extra RAM to prototype various firmware and application builds but this should work just as well with an Arduino Uno or even a Nano (although I’ve not checked all the connections.)


I have also made provision for a momentary switch to act as an Application Power Button to signal any downstream circuit that power should be switched.  Using a momentary button means I won't need to have any complicated syncing routing between any touch button on a screen and the button state which would be needed if it was a latching type.  Of course, the button could be used for any purpose, that’s just the one I envisage.  A rotary encoder will provide an alternate input mechanism for selecting options or entering control values.  These are manual controls that could supplement a touch interface - one I will be developing with the touch LCD I have to hand.


The schematic highlights the pin connections I have chosen for the Mega but you could choose any that are convenient for your application.  There are 3 spare connectors which can be ‘hacked’ to provide a connection to anything you like - wire into the relevant TP hole.  The schematic says pin 13 is reserved for future use but I haven't envisaged anything for it yet.


Board I/O

This isn’t really a feature as such, but these are the signals that route off the board to the downstream circuit or modules.  Things to be aware of:

  • The I2C signals use a 4.7K pull-up resistor.  There isn’t a lot of capacitance on the lines from the existing ICs (check the datasheets) but you should be aware of how much you are adding as it may affect the operation if you add too many I2C components.
  • The ADC signals should be limited to 2.048V.  The ADC can take 5.0V without problem, and there is some over voltage protection ahead of the OpAmp that buffers the signals to the ADC, but you should be aware of the impact of pushing in over 5.0V.
  • The DAC will output 0V to 5.0V and has a current load of +-5mA.
  • The +5V, -5V and +12V are, in theory, capable of outputting up to 1A of current but you need to be aware of power usage and temperature gain.  There is a 3V drop on the 12V regulator (assuming 15V power in) and a 7V drop on the +-5V regulators so take that into account when running down stream circuits.


Control Board PCB

The KiCad PCB design

This is a 4-layer board, 100mmx100mm, with power/signal routing on the top and bottom layers, and ground planes on layers 2 and 3.  There is a mix of through hole and SMD parts (mainly the latter) but they should all be easy enough to solder.  The most awkward is likely to be the AD5696R DAC but use a small tip, plenty of flux, take it steady and you should be fine.  Fit the through hole parts last.  The pads labelled “TPxx” are intended as test points.   The connectors J21, J22 and J24 are aligned directly opposite their counterparts on the PowerBoard PCB to make it easy to connect up (or more importantly, to make it harder to misconnect.)


As on the Power Board, the TP holes are also useful ‘hack points’ which can be used to route alternate signals around.



I have provided C++ library code for each feature on the board that needs it, providing the full functionality that is accessible over the I2C connection.  Props to the original authors are given (no point in re-inventing the wheel) and I extended their code as necessary so that all the functions are available.  These can be compiled into any test application that you care to write.  I’ve tried to provide decent commenting to help you work out how they work and how to call the relevant functions.  I have also created a test script for each feature that utilises a simple command structure that can be entered in the serial monitor to drive each feature.  The test video below for the RTCC is a good example of this in action.  These scripts can form the basis for your own test application but could, indeed, be used as-is.  If you add the USB/UART feature to the board, then the commands can be entered via Putty or TeraTerm (or any serial program you wish) rather than the Arduino IDE serial monitor - just make sure the test script is using the right Serial channel.  On one serial channel boards, try SoftwareSerial to provide an extra one.


The libraries and test scripts are added to this post as an attachment.  In the testing section below I show the commands available for each feature.


Testing the ICB

I’ve provided a number of videos, for which I apologise in advance as I’m not that great with videos, that show the board under test.  Testing of the EEPROM and RTCC shows the Arduino accepting commands over the Serial port.  Similar scripts are available for the DAC and ADC but I demonstrate/test them via a SCPI interface using LabView NXG instead to show the flexibility available to you.  All the test scripts are attached to this post below and whilst written for an Arduino are simple and readily adaptable.


Testing the ADC

I'm using LabView NXG and SCPI to control a PSU, DMM and the ICB to generate and read voltages.


Testing the DAC

Similarly, I'm using LabView NXG and SCPI to control a DMM and the ICB to generate and read voltages.


Testing the Application Power Switch and Fan

Here, I demonstrate that the Power Switch is useful not just for 'indicating power state'.


Testing the Rotary Encoder

A simple test to show the encoder working.


Testing the RTCC and then EEPROM

In this demonstration, I show a simple command set used to drive the functionality of these two features; similar scripts with command sets are available for the ADC and DAC.



Other Tests

In this post, as linked elsewhere, I actually test the DAC and ADC further by characterising their response over a wide range.  Both operate linearly over their full range and inline with their datasheet specifications.  Both could be easily adjusted via look-up tables held in the EEPROM if better than 500uV accuracy is needed.  Check out how well they work!


Command Sets

For interest, here are the commands that can be used to drive each of the features which use I2C; some are a lot simpler than others.  These commands can be entered through a serial monitor and a response will be returned by the test script.  Ultimately these will be superseded by formalised SCPI commands.



e.g S1C162: start channel 1 converting in continuous mode using a resolution of 16-bits and a gain of x2.

e.g RV: read a voltage from channel 1 (assuming the first command was entered!)

 * TP8_Adc: Testing the MCP3428 ADC
 * Author: Andrew Johnson
 * Datasheet:
 * July 2021
 * Commands:
 * S<C><M><R><G>: Start a conversion on Channel C, Mode M, Resolution R and Gain G.
 * R<C|V>:        Read a Code or Voltage from the channel currently converting.
 * Channels: 1, 2, 3, 4
 * Mode: O - One shot; C - Continuous
 * Resoution: 12, 14, 16
 * Gain: 1, 2, 4, 8



e.g. WVYNYN,2.5: Load the input register for channels 1 and 3 to output 2.5V.  No output occurs unless LDAC is LOW

e.g. UYNYN: load the DAC registers for channels 1 and 3 from their input register.

e.g. DVYNYN,2.5: Load the input registers AND DAC registers for channels 1 and 3 to output 2.5V.  Output is immediate irrespective of LDAC state.

 * TP7_Dac: Testing the AD5696R DAC
 * Author: Andrew Johnson
 * Datasheet:
 * July 2021
 * Commands:
 * W[C|V]<????>,<c | v>:  Writes either the output code (C) or voltage (V) to the input registers for the DACS 
 *                        specified (?) - use Y or N to activate a particular DAC input register.  If LDAC is 
 *                        low, then the output will change immediately; the LDAC mask may override this.
 * U<????>:               Updates the ouput DAC channel from the input register for the specified DAC (?) - use Y or N.                
 * D[C|V]<????>,<c | v>:  Same as command 'W' and 'U' combined - i.e. outputs immediately.
 * P<N|L|H|O><????>:      Set specified DAC's power level to Normal, Low, High or Open.
 * P<pppp>:               Sets the power level for each DAC individually.  4xp must be provided as one of N, L, H, O.
 * M<????>:               Sets the LDAC mask for each DAC as specified.  User Y (use LDAC), N (ignore LDAC)
 * L<H | L | P>:          Sets the LDAC hardware pin HIGH, LOW or PULSE.  Pulse will switch a HIGH state to a LOW state
 *                        then back to HIGH - if already LOW, no pulse will occur.
 * C[P]:                  Clear all DAC values (reset to startup state).  If P is given, the hardware reset pin is pulsed 
 *                        LOW/HIGH instead of sending the DAC command.
 * I[Y|N]:                Sets the internal voltage reference on (Y) or off (N)                        
 * R<ppp>,<bbb>,[count]:  Reads at least 1 byte from address denoted by page number (ppp) and byte number (bbb).  
 *                        If count is provided, reads count bytes.  If the combination of address n and count would 
 *                        incur a read beyond the EEPROM size (i.e. final read address > 127) then it will fail and 
 *                        nothing read.



e.g. T912538504: Set the datetime on the clock to the unix epoch value 912538504 (this may not be a valid Unix Epoch, it's just an example!!)

e.g. O10: alter the current datetime by +10 seconds

e.g. O-15: alter the current datetime by -15 seconds

e.g. AS0912538504: Sets alarm 0 with the unix epoch time.  Note that alarms don't operate on a specific time, they operate on a specific seconds, minute, hour etc.  Alarms must be enabled after setting to work.

e.g. AI0M0H: Enables alarm 0 to generate an interrupt when the clock seconds match the alarm seconds raising the MFP pin HIGH.  Note that the arduino code sets up the interrupt waiting on the state transition of the MFP pin and automatically takes care of whether you select HIGH or LOW for MFP.

e.g. AE0M8: Disables alarm 0.

e.g. AR0?: Displays information about alarm 0 and displays whether or not it is enabled.

 * TP5_Rtcc: Testing the MCP79410 RTCC.
 * Author: Andrew Johnson
 * Attribution:  Arduino library by Steve Marple.
 *              Heavily based on work by Steve.  Adjusted for the specific need of just the MCP79410
 * Datasheet:
 * June 2021
 * Use to get a unix time.
 * Commands:
 * T<Unix Time>:  Set time, e.g. T1624817220 sets the time to 2021-06-27 18:07:00 GMT
 * C<Unix Time>:  displays the clock error against the given time.
 * M<D|n>:        sets the square wave frequency to the give mode,n. "M0" (1Hz); "M1" (4096Hz); 
 *                "M2" (8192Hz) or "M3" (32768Hz).  M4 set the output to 64Hz compensated wave to 
 *                allow a calibration value to be determined.  If D is used, the square wave is 
 *                disabled.
 * X<[?|n]>:      runs a calibration test (?) or sets the calibration value between -127 and +127.
 * ?:             displays whether or not the clock is running
 * O<n>:          adjust clock by n seconds
 * P[Y|N]:        displays whether or not power has failed (power fail flag set).  Clear the 
 *                flag if Y.
 * F[H|L]:        Sets the MFP to High or Low; square wave and alarms are disabled.
 * H:             Halts the clock.
 * S:             Starts the clock.
 * A[S|E|I|R]<n>[<Unix Time> | <Mm>[H|L] | [?]]: Operates the alarm: 
 *                AS<n><Unix Time>: Sets alarm n with the time.
 *                AE<n><Mm>[H|L]: Enables alarm n to match on mode n with polarity High or Low.
 *                  This script will test for alarm raised and print in the serial monitor when the 
 *                  RTCC flags it.
 *                  M0: match seconds
 *                  M1: match minutes
 *                  M2: match hours
 *                  M3: match day
 *                  M4: match date
 *                  M5: DON'T USE
 *                  M6: DONT'T USE
 *                  M7: match datetime
 *                  M8: disable alarm.
 *                AI<n><Mm>[H|L]: Enables alarm n to interrupt through the MFP pin, matching on mode n 
 *                  with polarity High or Low.  The script will attach the MFP pin to a digital interrupt 
 *                  to automaticall report as MFP goes high or low.  See tables 5.9 and 5.10 on p28 of the datasheet.
 *                AR<n>[?]: Reads the alarm.  If ? is used, displays whether the alarm is enabled or not.
 * W<nnn>,<b>[b 1..7]:  Writes 1 to 8 bytes to address n of the EEPROM.  Writes are constrained to page boundaries and
 *                      will not wrap.  If the bytes to write extend beyond a page boundary, the write will fail and 
 *                      nothing will be written. Address must be 3 digits followed by a comma.
 * R<nnn>,[count]:  Reads at least 1 byte from address n of the EEPROM.  If count is provided, reads count bytes.
 *                  If the combination of address n and count would incur a read beyond the EEPROM size (i.e. final
 *                  read address > 127) then it will fail and nothing read.



e.g.W000,250,ABCDE: Write 5 bytes, ABCDE, to address 250 in page 0.

e.g.R000,250: Read 1 byte from address 250 in page 0.

 * TP6_Eeprom: Testing the CAT24M01 EEPROM
 * Author: Andrew Johnson
 * Attribution:  This solution is based heavily on the 
 * work done by CascoLogix.
 * Datasheet:
 * July 2021
 * Commands:
 * W<ppp>,<bbb>,[b 1..8]: Writes 1 to 8 bytes to the address denoted by page number (ppp) and byte number (bbb).  
 *                        Writes are constrained to page boundaries (256 bytes max) and
 *                        will not wrap.  If the bytes to write extend beyond a page boundary, the write will fail 
 *                        and nothing will be written. Address elements must be 3 digits followed by a comma.
 * R<ppp>,<bbb>,[count]:  Reads at least 1 byte from address denoted by page number (ppp) and byte number (bbb).  
 *                        If count is provided, reads count bytes.  If the combination of address n and count would 
 *                        incur a read beyond the EEPROM size (i.e. final read address > 127) then it will fail and 
 *                        nothing read.



e.g. F: turns the fan on.

Really, this is just a test script that the UART connection is working and I've chosen these two commands.  By ensuring that any of the other scripts are using the UART serial monitor, you can send that script's commands to the ICB.

 * TP9_Uart: Testing the Uart connector
 * Author: Andrew Johnson
 * Datasheet:
 * July 2021
 * Commands:
 * F: Toggle fan on/off
 * Any other characters are echoed back along with the string's reverse representation


Does it work?

Remarkably, yes it does, at least to the extent that I've tested it so far.  The fan control MOSFET was faulty and needed replacing with an alternative I had to hand.  The output capacitor on the voltage reference was incorrectly wired and needed a 0Ohm resistor to replace the 1K resistor populated on R25 (now fixed in the PCB design.)  The RTCC maintains excellent time through its backup battery; the fan powers up/down under software control; I2C signals are clean and required no fiddling with pull-up resistor values.  The UART connector allows me to drive the Arduino (and thus the on-board components) from my PC through LabView NXG (or a serial terminal such as Putty or TeraTerm) - something used extensively for characterisation of the DAC and ADC channels.  Speaking of which, the results from the characterisation of the DAC and ADC are excellent and show linear behaviour with accurate readings - I've linked to that post elsewhere in this blog.


What’s Next?

The ICB is complete enough to be used for a lot of circuit testing and to design and build your own connectable modules, but I’m not finished with it yet and it’s going to evolve over a number of iterations:

  • Encasing: My original intention was to use this to control a DC load and I would encase all PCBs in one unit.  However, my thinking has evolved and my intention now is to encase the ICB on its own and provide plugs for the Board I/O module.  This means that additional modules can be plugged in to provide different functionality as needed at any one point in time.  This means it will be just as easy to plug in a breadboard as it will be an encased DC load.
  • Firmware: the command set I have at the moment works well and can be used for driving the ICB over a serial interface.  I want to be able to formalise an API to firmware so that it becomes much simpler to create applications on top of it.
  • Example UI: I also want to create a UI using a touch LCD I have to hand to show what can be achieved.  This will likely be hand-in-hand with developing a pluggable module.
  • SCPI Command Set: as part of developing the firmware, I will be creating and documenting a set of SCPI commands, conformant to the SCPI specification, so that it can be ‘formally’ driven.  These would then supersede the non-standard command set I’ve currently developed.


I hope you’ve found this informative and the idea of the ICB a useful piece of test equipment to help you test designs and prototypes of your own.  I’ve attached copies of the test scripts (including libraries), gerbers that can be uploaded to any PCB manufacturer (I have some spare if interested) and a BOM.  I've included the BOM as a spreadsheet because there are a number of fields worth including and Farnell can't supply everything; if anyone wants it as a CSV or other format, let me know.