Introduction: Reconfigurable Schematics: How to Make Electronics More Reusable

About: The iolinker chip functions as a dynamically configurable IO matrix. Its main functionality, besides IO extension, is to dynamically set up a matrix of GPIO connections, that allow direct pass-through of high-…

Imagine you built a prototype PCB. The schematic may have been your best guess, the software for your microcontroller unfinished or untested. Software changes on microcontrollers often require hardware changes as well, due to hardened (pin specific) chip functions and the like. You'll waste hours trying to fix it, sometimes maybe even throw away a bad prototype and manufacture a new one.

Imagine you updated the software later on, or replaced parts of the hardware, but now the digital signals aren't routed ideally. You may be tempted to get new electronics, again.

Okay. Many of you may not care, hobbyists do prototyping with jumper cables!

Do you sometimes spend hours changing jumper cables back and forth, fiddling around endlessly with clips falling off? Then you finally reach a point where things work alright, but not perfect; you change the jumper cables around again, fix the software and it stops functioning entirely. "Shit! How was this wired up with the previous software version?"

Never happened to you? I used to build robots and we wanted lots of flexibility, but not lots of mess. How do you go about that?

You guessed it, I wanna present a solution to you. FPGAs.

"That takes months!"

Guess again, we did you a favor. The low cost iolinker FPGA board comes preprogrammed to act as an extension for your microcontroller, that allows you a) to extend your IOs, and b) to link pins, which essentially means you ask for them to be "connected to each other", wait, uh, a few microseconds, and it's done.

You could reprogram the FPGA, but you don't have to. Simply hook it up, use our open source library and get started in minutes. Here's how.

Step 1: Parts to Get


Either get

a) A 3.3V Arduino. That may be Arduino Due or Arduino Pro Mini 3.3V, for example.


b) an Arduino Uno / Leonardo / another 5V Arduino and a bidirectional level converter with at least 2 channels. Such as this one: -- but there are many, very cheap.


c) a 3.3V USB TTL cable, a Raspberry Pi or another embedded device with UART port.

The Arduino Pro Mini is pictured, for it's a really cheap and nice product that you can grab as a 3.3V version, saving yourself the level shifting trouble.

Also, for these instructions, you need an iolinker JI111-81L-B board from

Step 2: Wire Up Power and Serial Ports

a) For a 3.3V microcontroller (3.3V Arduino, Raspberry Pi, etc.)


* COM3 -> Serial RX

* COM2 -> Serial TX

* 5V power supply to both boards

* GND to both boards

On the Arduino Pro Mini, take care to connect the 5V to the RAW pin.

b) For a 5V microcontroller: (Arduino, etc.)


* COM3 (low voltage side) -> level shifter -> RX

* COM2 (low voltage side) -> level shifter -> TX

* 3.3V from the iolinker board to the low voltage input of the level shifter

* 5V from the Arduino to the high voltage input of the level shifter

* GND from the iolinker board to the level shifter

* GND from the Arduino board to the level shifter

* 5V and GND to both boards

Check out for an example of how to connect a bidirectional level shifter for serial level shifting.

c) The 3.3V USB TTL cable...

...fits directly onto the X4 connector, just make sure the black wire is on the side of the GND pin.

Any other 3.3V or 5V UART device can be connected the same way as described in a) and b).

Step 3: Add Libraries

For Arduino:

Download the library from

Open up the Arduino application and click Sketch -> Import Library... -> Add Library...

Then select the file.

Click Sketch -> Import Library... -> IOLinker (at the bottom). Also import the SPI and the Wire library.



IOLinker iolinker;


before your first function, to initialize the IOLinker class.

For PC and Raspberry Pi:

Install WiringPi ( and run "sudo apt-get install g++-4.8 git" in a terminal.

Then run "git clone; cd iolinker; make unittest test".

If everything worked, you're being congratulated with "0 tests failed.". Congratulations, you're ready to go!

The instructions that follow will be for Arduino, but:

  • On PC, modify the iolinker_pcserial.cpp file using the same methods that will be described in the rest of the tutorial. Compile and run with "make clean pcserial; ./iolinker_pcserial".
  • On a Raspberry, modify the iolinker_pi.cpp file using the same methods that will be described in the rest of the tutorial. Compile and run with "make -f Makefile.pi clean pi; ./iolinker_pi".


Depending on your exact hardware the library at may need slight adaptation. Sorry guys. Write me what you're using or if you need help.

Step 4: Set Up Connection





while (!Serial) {

; // wait for serial port to connect. Needed for Leonardo only


iolinker.beginStream(Serial); // Connect to iolinker chip via UART

iolinker.targetAddress(0); // Address of the chip to connect to


in your setup function, to initialize the connection via UART. For Arduino Leonardo, use Serial1 instead! On Arduino Mega and Due, you can choose any of the serial port Serial, Serial1, Serial2 and Serial3. (As long as you wired up to the right one..)

PC / Raspberry:

Connect using


iolinker.beginSerial("/dev/ttyAMA0"); // or ttyUSB0 or the like


But, better, simply build off the source file iolinker_pcserial.cpp or iolinker_pi.cpp -- they already are complete and working.

Step 5: Extend IOs and Link Pins!

In your setup() and loop() routines, you can now use the iolinker functions to configure its IO pins.

To set a pin as an input and read its value use


iolinker.setPinType(IOLinker::IOLINKER_INPUT, 0); // P1 is an input

if (iolinker.readInput(0)) {

// Pin is high

// something

} else {

// Pin is low

// something



Note that the pin number '0' refers to the first pin, which is labeled as "P1" on the board. Similarly, the last pin is '48' (P49).

To set a pin as an output use


iolinker.setPinType(IOLinker::IOLINKER_OUTPUT, 1); // P2 is an output

iolinker.setPinType(IOLinker::IOLINKER_OUTPUT, 2); // P3 is an output

iolinker.setOutput(true, 1); // P2 is high

iolinker.setOutput(false, 2); // P3 is low


You can also output PWM signals directly on the first 10 GPIOs of the iolinker chip:


iolinker.setPinType(IOLinker::IOLINKER_OUTPUT, 3); // P4 is an output

iolinker.setOutput(true, 3); // P4 is high

iolinker.pwm(64, 3); // Set P4 to a 50% pulse pause ratio


Why is the value 64? The pulse pause ratio is encoded as a 7 bit value, i.e. it goes from 0 to 127. The max ratio disables PWM -- for it equals the "always on" state. 64 is on about half the time. If you were to connect an LED, it would light up at half brightness. So to turn PWM back off, use iolinker.pwm(127, 3);

To link two pins, proceed like so:


iolinker.setPinType(IOLinker::IOLINKER_INPUT, 4); // P5 is an input

iolinker.setPinType(IOLinker::IOLINKER_OUTPUT, 5); // P6 is an output, 5); // Forward signals from input P5 to output P6


Use iolinker.clearPinFunctions(5); to unset the pin link and reuse the pins for something else.

If you want to be even faster...

there's a small little software online at that generates that source for you. You can simply copy and paste :)

See the GitHub repository at for more functions and on how to do the same thing on a PC or Raspberry Pi.

Step 6: You're Done!

With what you just learned you can

* Extend the IOs of your microcontroller

* Rewire digital signals between your microcontroller and other hardware -- the wiring saved and changeable in your software!

* E.g. connect many UARTs to the iolinker board and cycle through them, depending on whom you wanna talk with.

* Do self testing: First verify high/low values in your schematic before you connect chips with each other.

If you have suggestions, feedback or questions, please let me know.

Step 7: Need Even More IOs?

You can connect up to 127 iolinker boards in parallel!

In your code, you can choose which one to address using the




method. Any commands that follow will be executed by the appropriate board. There's a limitation, though:

Pin links are only possible within the same board, not across several boards.

To choose which board has what address, you need to modify the resistors IN1 to IN7.

(Technical details: The resistors pull down to GND. High equals a 1 bit, low a 0 bit, IN1 is the least significant bit.)

With all resistors in place, the slave address is 0. Remove the IN1 resistor to make the slave address 1. Remove the IN2 resistor to set the slave address to 2. Remove both and the address is 3.

Green Electronics Contest 2016

Participated in the
Green Electronics Contest 2016

Arduino Contest 2016

Participated in the
Arduino Contest 2016