Posts

Running multiple slave devices on Arduino SPI bus – data formats

Bit reversal code

Bit reversal code

This is Part 3 of 3-part series of articles. Part 1 talks about ways of tweaking SPI code while Part 2 talks about hardware modifications.

After finishing hardware modifications for my three-SPI-device setup I started coding and hit a snag. Any device would happily work by its own, WiFi and SD were also happy together, however, adding NFC Shield to the mix would disable other two. If I moved NFC initialization to the beginnig, other two devices would work but NFC would not. At the same time, if a device was just present on a bus and not initialized, other two devices were not affected. It became clear that initialization itself was the source of error.

Seeedstudio NFC Shield uses NXP PN532 transmission module. This module supports several communication interfaces, namely SPI, I2C, and HSU. In SPI mode the data format is ‘LSB first’, i.e., transmission starts from bit 0. Such format is uncommon; all other SPI shields I’m aware of – Ethernet, WiFi, USB Host, etc., are using ‘MSB first’ format – the transmission starts with bit 7.

A quick look into NFC library source code revealed the following line in PN532::begin() function:

pn532_SPI.setBitOrder(LSBFIRST);

This line sets the data format. In Atmega microcontrollers the default SPI data format is ‘MSB first’ – all other SPI devices don’t have to set it during initalization. Initial revision of PN532 code ( written by Adafruit ) was using software SPI and awkward bit order was dealt with in write() and read() functions. When Seeedstudio modified the code to work with hardware SPI, they just switched SPI to ‘LSB first’ format without much thinking, breaking compatibility with the rest of the world. Surely, when I commented out this line, NFC initialization stopped breaking WiFi. Predictably, NFC also stopped working.

Luckily for me, the SPI is pretty basic protocol and bit order setting in SPI controller doesn’t mean much. It really doesn’t matter how the bit order is set; if we need ‘MSB first’ for the majority of the devices we can initialize SPI in a normal way and then modify write() and read() functions for ‘LSB first’ device to serve it reversed bytes. This is exactly what I did. Below is modified version of Seeedstudio PN532 library (also presented on a title screenshot) – lines 6 and 16 perform bit reversing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/************** low level SPI ********/
/*Function:Transmit a byte to PN532 through the SPI interface. */
inline void PN532::write(uint8_t _data) 
{
  /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */
  _data  = ((_data * 0x0802LU & 0x22110LU) | (_data * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
 
  pn532_SPI.transfer(_data);
}
 
/*Function:Receive a byte from PN532 through the SPI interface */
inline uint8_t PN532::read(void) 
{
  uint8_t data_ = pn532_SPI.transfer(0);
  /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */
  data_  = ((data_ * 0x0802LU & 0x22110LU) | (data_ * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
 
  return data_;
}

After making these modifications, commenting out the ‘LSB first’ setting in the PN532:begin() and also modifying WiFi code to stay away from pin 9 (see this article for discussion) all three devices are happily working together without conflicts. The library mod for PN532 can be left there permanently – the chip will never know that it is communicating with “misconfigured” SPI host. I’m hoping Seeedstudio will fix their code eventually; in the mean time, if you have SPI compatibility issues, simply make code modifications presented in this article.

Enjoy,
Oleg.

Running multiple slave devices on Arduino SPI bus – hardware modifications.

WiFi and NFC shield stack

WiFi and NFC shield stack

This is Part 2 of 3-part series of articles. Part 1 talks about ways of tweaking SPI code while Part 3 explains how to deal with incompatible data formats.

Add-on boards AKA “shields” greatly expand the capabilities of standard Arduino platform. Typically, a shield adds a specific peripheral interface; if you need several peripherals you may need to use several shields. The biggest problem in this approach is shield compatibility. Shield developers don’t care much about interoperability and sometimes making several shields work together is difficult. In the previous article on the topic I described a project where USB Host and WiFi shields were made to share the same SPI bus. I have been recently tasked with similar project which required rather heavy hardware modifications. This article shows the necessary steps to build a system consisting of Arduino board, official WiFi Shield and Seeedstudio NFC Shield.

Here is the hardware configuration. Both shields come with stackable headers so they can be plugged into each other. Both shields use ICSP for SPI but connectors are non-stackable so at least one of the shields must have its ICSP connector replaced with the stackable variant ( I sell them). Also, both shields use pin 10 for CS so this pin needs to be re-assigned on one of the shields.

NFC shield has offset female connectors therefore if another shield is placed on top of it ICSP connector won’t mate. It means that stackable ICSP connector shall be placed on WiFi shield. At the same time, since NFC Shield does have a second row of contacts re-assigning pin 10 on this board is easy.

Before we start cutting traces and desoldering connectors, let’s establish a baseline or “a known good state”. I simply grabbed an example from NFC shield library distro called readMifareMemory, compiled, loaded and ran it. I was able to read the card and now I know that my NFC shield is functional.

One other note – both shields are assembled using lead-free solder which has higher melting point. Don’t forget to set the temperature of your soldering iron accordingly – between 700F and 750F.

Continue reading Running multiple slave devices on Arduino SPI bus – hardware modifications.

Running multiple slave devices on Arduino SPI bus

Stack of shields

Stack of shields

This is Part 1 of 3-part series of articles. Part 2 talks about hardware modifications while Part 3 explains how to deal with incompatible data formats.

Serial Peripheral Interface AKA SPI bus is a popular way to communicate peripheral IO controllers to a micro over short distances and many microcontrollers have SPI interface built-in, including Arduino. Consequently, many Arduino shields use SPI to communicate to Arduino; USB Host shield is one of them. When more than one such shield is connected to Arduino, several SPI slave devices start sharing SPI bus. SPI is designed to allow bus sharing and if correct signals are present at correct moments all devices get along just fine. In practice, however, nothing usually works as desired, shields are interfering and fixing it requires hardware and software modifications. I was recently tasked with connecting 3 SPI slave devices to Arduino and this article shows how I did it.

A reader is expected to be familiar with SPI bus in general and Arduino implementation in particular. In addition, Tronixstuff has SPI tutorial, which is a little bit more user-friendly.

1. The problem

Arduino shields with SPI interface generally have 2 sources of interference – 1 on hardware level and one in software.

SPI bus consists of 3 shared data lines – SCK, MISO and MOSI, plus one “Slave Select” AKA SS line per each device. All transfers are initiated by the host and proceed in both directions simultaneously. Only one device, the one whose SS line is asserted low, is participating in the transfer by driving its MISO line – all other devices are expected to have their MISO line in a third state.

Due to peculiarities in Atmega SPI implementation, designers of Arduino shields prefer using default SS line, which is assigned to pin 10 on standard-sized Arduino boards. If two shields are driven by the same SS, they will have their MISO line active at the same time. Best-case consequence of it is only one of the shields in the stack being able to communicate, worst-case is destroyed MISO line transmitters. Therefore, the first step in any multi-shield SPI project is to make sure each shield uses its own SS line and never expect this to be the case in default configuration.


Continue reading Running multiple slave devices on Arduino SPI bus

Updated USB Host library uploaded to gitHub

No SPI

No SPI

New version of USB Host library has been uploaded to gitHub. I managed to find a couple of bugs and solve some compatibility issues. The biggest change, however, has been made on the very lowest level of the library – SPI transfers between Arduino and MAX3421E registers.

From the beginning, USB Host firmware relied on Arduino Playground SPI library. Starting from version 0018 of Arduino IDE, this library became part of the distro. Two versions after that, Arduino team decided to re-write SPI library, among other things changing function names. As a result, USB Host code became incompatible with “stock” SPI library. To remedy the situation, I incorporated SPI routines directly into MAX3421E support code. The new code is independent of Arduino SPI library and builds correctly on “old” (i.e. 0017) and “new” (0021) versions of Arduino IDE. In addition to that, new code accounts for SPI pinout difference between Arduino variants and works on both Atmega 328 and Atmega 1280/2560 based boards. ( Note: the current rev1.x USB Host Shield still needs to be modified to work with Megas )

The new library can be downloaded from USB Host Shield gitHub repository. If you are upgrading existing installation of the library, please make a backup copy before downoading! I checked it against all code examples and USB devices in my possession and everything works without a hitch. However, code written with tight timing may stop working because of speed difference since new SPI routines are slightly faster.

As you can see in the title picture ( click on it to enlarge ), the line #include "Spi.h" is no longer needed. In next several days I’m going to update all USB examples on this site to match the new code. If you have any any problems with the library, please let me know!

Oleg.

Troubleshooting Arduino USB Host Shield

USB Host Shield in a test fixture

USB Host Shield in a test fixture

[EDIT]This article covers revision 1 of the shield. Current revision (2.0.x) is slightly different and works under different software. The following test routine shall be used to test the board and generate test signals.[/EDIT]

Making electronic devices requires close interaction with parts – reversing supply polarity, overloading inputs, and inadvertently shorting pins with test leads. Consequently, occasional destroying of parts is natural and shall be anticipated. I have been in correspondence with several electronics enthusiasts helping them getting their shields fixed and since their problems look similar to what I see when doing post-manufacturing quality control I decided to share my testing procedure along with some pictures.

In the past, it was customary to include schematic with every electronic device documentation. Complex devices, such as oscilloscopes, spectrum analyzers and other test instruments used to have service manuals containing detailed calibration and repair procedures. At some point, service manuals and schematics disappeared from the documentation for various reasons – equipment users were left to deal with manufacturer’s support or rely on their own reverse engineering skills. With open source movement and general understanding that sharing information is beneficial, manufacturers resumed publishing schematic diagrams of their creations. This article presents next logical step – a service manual for Arduino USB Host Shield, sort of.

Much of the testing is performed using board test sketch, available from examples section on github. Two files are necessary – board_test.pde and board_test.h containing diagnostic messages. The sketch tests 4 major parts of the circuit – SPI interface, general purpose input/output pins (GPIO), quartz crystal oscillator, and finally USB SIE. The main loop is written so that any test can be turned off if necessary by commenting out a single line. GPIO lines are checked using a loopback adapter – a thing that connects GPIN0 to GPOUT0, GPIN1 to GPOUT1, and so on. This test is made optional – if you don’t connect GPIO lines as described, the test will print an error message and continue with the next test. Also, GPIO test is placed between short and long SPI tests. The reason for this is that due to MAX3421E internal organization both short SPI test (reading REVISION register) and GPIO read/write doesn’t require working crystal oscillator, whereas long SPI test (reading/writing any other register) will fail and stop if crystal is defective. Therefore, when I see short SPI and GPIO tests passed and long SPI test fail I know that it’s actually a crystal which is dead, not SPI.

In addition to board test program, you will need a multimeter with thin sharp test leads to measure voltage and resistance between board elements. Some of them are quite small so a magnifier is also handy. Certain steps of the test procedure call for time-base instrument. Modern digital mixed-signal oscilloscope is the best choice, however, since very few people can afford one, a method of visualizing SPI traffic with plain analog oscilloscope will also be demonstrated. Logic analyzer is handy, but optional. For testing USB transactions you will also need some sort of device connected to shield’s USB connector. I usually use USB flash drive as a test device.

The article as well as board test program is written for worst-case scenario, i.e., shield which was built from scratch or came from major rework like MAX3421E replacement due to applying 5 volts to 3.3V pin. The test program works the same way with all four configurations, however, manual tests are shown only for “Simple” configuration, i.e. one with level translators and receiving both 3.3V and 5V from Arduino Duemilanove or similar (no DC-DC converters). Testing other configurations is slightly different and will be noted in the text. Also, “Minimal” configuration calls for specific type of test device – I use digital camera.


Continue reading Troubleshooting Arduino USB Host Shield

Interfacing LCD via SPI.

HD44780 LCD display

HD44780 LCD display

Introduction.

As time goes by, microcontrollers become more powerful, cheaper, and smaller. A typical micro of the past could have had 40 pins and no internal memory. On the contrary, modern J-series PICs are made with 96K program memory and 28 pins. We can drive a lot of peripherals with that amount of memory, however we are getting short on pins.

In this article I will show how to drive a parallel interface peripheral serially. A HD44780-compatible LCD module is good candidate – it is popular, inexpensive, and slow, so you won’t be losing any speed while converting parallel to serial. And you could even save some money using a micro with fewer pins.


Continue reading Interfacing LCD via SPI.