New interface module: the Yocto-SPI

New interface module: the Yocto-SPI

There is a newcomer in the family of Yoctopuce interface modules: the Yocto-SPI. This small module can communicate with sensors and other devices that use a SPI communication protocol.






SPI is a standard way of transferring data between a host and peripherals. A SPI bus normally has at least 5 wires:

  1. the electrical ground (GND)
  2. a serial clock (SCK) for ticking at each time a bit is sent
  3. a serial data output (SDO) for transmitting bits
  4. a serial data input (SDI) for receiving bits
  5. a slave select (SS) to signal the start and end of messages

A sixth line is often present to provide power to the remote device. It is mostly used within circuit boards (to interface flash memory, etc), but a some sensors and devices use it as well because it easily allows to chain multiple devices on the same bus.

The Yocto-SPI is very convenient solution to interface an SPI device from a laptop, a tablet or a computer. It has all six wires described above, and can be configured to use 3.3V or 5V signaling levels and to provide 3.3V or 5V on the power line. Like any other Yoctopuce device, it does not require to install any driver and does not create a virtual COM port. Instead, you can use the high-level API functions provided in our library to talk to the device directly from your program.

The new Yocto-SPI
The new Yocto-SPI


Extra features


In addition to working as an simple interface, the Yocto-SPI can also be configured to automatically send specific commands on the SPI bus and read the received data. This can be used for instance to automatically query a sensor at periodic interval, and publish the value using a GenericSensor interface. Hence, it possible to autonomously save the received measures on the built-in data logger, and to transmit them on the network. For instance, if you connect it to a YoctoHub-GSM-3G-EU, you can automatically post the measured data to a Cloud server of your choice, from anywhere in the world with a cellular network.

Demo


Here is a small demo of the Yocto-SPI, used to drive a simple SPI device. We found some nice inexpensive 8-digits 7-segment displays on embedded-lab.com. They are available in 4 colors, and can be daisy-chained. Let see how complicate it is to drive them from an existing application using a Yocto-SPI.

The 7-segment display from embedded-lab.com
The 7-segment display from embedded-lab.com


As a starting point, we took the demo application from our C# library named YSensorGraph, which reads a temperature sensor and displays a live graph with the measured values. In the method newSensorValue(), which is called for each new temperature reading, we have added a call to a new method that will display the value on the 7-segment display.

The first thing we do in this method is to check if we have a SPI interface connected, and exit otherwise. We could check for a specific SPI device name if we had many, but we'll keep it like this for this time.

YSpiPort spiPort = YSpiPort.FirstSpiPort();
if (spiPort == null) return;


Then we configure the SPI parameters: bit rate, SPI mode, bit order, etc. Those parameters can be found in the datasheet of the device to be interfaced.

spiPort.set_spiMode("250000,3,msb");
spiPort.set_ssPolarity(YSpiPort.SSPOLARITY_ACTIVE_LOW);
spiPort.set_protocol("Frame:2ms");


Then we send a few SPI commands to the display so that it starts displaying the way we want. In particular, for each digit we can choose if we want the data we send to be interpreted as number (and automatically converted to the right segments ON/OFF), or if we want to send a bitmap describing individually which segment must be ON or OFF. Each command is made of two bytes: the command identifier, and the argument. For instance, command 0a is "set brightness" and 05 is the brightness level.

// Write display setup commands
spiPort.writeHex("0c01"); // Exit from shutdown state
spiPort.writeHex("09f8"); // BCD for digits 4 to 8
spiPort.writeHex("0b07"); // Enable digits 0-7 (=8 in total)
spiPort.writeHex("0a05"); // Set brightness


Here is the output we'd like to get
Here is the output we'd like to get


On the 3 rightmost digits, we want to display a space, followed by the °C unit. For these three digits, we use a bitmap value to select which segment must be turned on. For instance, to display a space we set all bits to zero, hence we send the byte 00.

spiPort.writeHex("014e"); // Digit 1: Display 'C'
spiPort.writeHex("0263"); // Digit 2: Display degree sign
spiPort.writeHex("0300"); // Digit 3: Display ' '


For displaying the measure on the remaining 5 digits, we need to compute the decimal representation. This is done by dividing repeatedly by ten, to extract digits one by one. The sign must be handled separately since we must show it just before the leftmost digit. Note also that the decimal point is added by setting the highest bit on the corresponding digit.

// Display the measure in digits 4 to 8
int rounded = (int)Math.Round(Math.Abs(value) * 100);
int decPoint = 2;
bool needSign = (value < 0);
for (int i = 4; i <= 8; i++)
{
    int digit = rounded % 10;           // take next digit value
    if (decPoint == 0) digit |= 0x80;   // add decimal point
    if (decPoint < 0 && digit == 0) {  
        if (needSign) {
            digit = 0xa;        // minus sign
            needSign = false;   // display it only once
        } else {
            digit = 0xf;        // blank
        }
    }
    spiPort.writeArray(new List<int> { i, digit });
    decPoint--;
    rounded /= 10;
}



That was it. As usual, what makes the code complex is not really talking to Yoctopuce devices, but the application-specific bits and bytes...

  

Add a comment No comment yet Back to blog












Yoctopuce, get your stuff connected.