User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Wirring pi and SPI communication

Mon Dec 24, 2018 7:59 pm

I'm trying to rewrite the Python functions for the pi plates (https://pi-plates.com/) I can probe at the SPI pins and see what is happening with working python code. The working python code seems to use CE1 for the chip select. When I try to recreate the SPI calls using the wiringpi libraries it uses CE0 for chip select.

Code: Select all

com = wiringPiSPISetup(0, 250000);
...
    wiringPiSPIDataRW(com, arg, 4);
There must be a way to change what pin is used for chip select as the python code is doing it. Is it possible for C code to use CE1 as a ship select using SPI communication?

Thanks

User avatar
joan
Posts: 14181
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wirring pi and SPI communication

Mon Dec 24, 2018 8:16 pm

What does the 0 mean in wiringPiSPISetup?

User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Re: Wirring pi and SPI communication

Mon Dec 24, 2018 8:22 pm

There seem to be 2 completely different SPI's. SPI0 and SPI0. So 0 indicates I'm using SPI0

User avatar
joan
Posts: 14181
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wirring pi and SPI communication

Mon Dec 24, 2018 8:36 pm

wiringPi only supports the main SPI device so that is not correct. Have you checked the documentation?

User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Re: Wirring pi and SPI communication

Mon Dec 24, 2018 8:47 pm

Yes you are correct

Code: Select all

com = wiringPiSPISetup(1, 250000); 
doesn't use the SPI1, but it also doesn't seem to change the chip select from CE0 to CE1, in fact when I probe around I don't see anything.

The wiring pi documentation (http://wiringpi.com/reference/spi-library/) call that field 'channel'
int wiringPiSPISetup (int channel, int speed) ;
This is the way to initialise a channel (The Pi has 2 channels; 0 and 1). The speed parameter is an integer in the range 500,000 through 32,000,000 and represents the SPI clock speed in Hz.
The returned value is the Linux file-descriptor for the device, or -1 on error. If an error has happened, you may use the standard errno global variable to see why
Thanks so much for the help. If I get this working I will post my work so C users can use the PiPlates

User avatar
joan
Posts: 14181
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wirring pi and SPI communication

Mon Dec 24, 2018 8:53 pm

You want channel 1. That is the term wiringPi uses to indicate chip select 1.

User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Re: Wirring pi and SPI communication

Mon Dec 24, 2018 9:37 pm

So I have unplugged the pi plate and directly plugged in a logic analyzer (https://www.sparkfun.com/products/13929). If I use:

Code: Select all

com = wiringPiSPISetup(0, 250000);
...
wiringPiSPIDataRW(com, arg, 4);
I see data as expected (clock, chip select at CE0, and MOSI)

but if I change to:

Code: Select all

com = wiringPiSPISetup(1, 250000);
I don't see any data flow on any pins, no clock or MOSI
do I need to turn something on to let it use CE1?

User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 4:24 pm

I get the same behavior using a pi zero

User avatar
joan
Posts: 14181
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 4:44 pm

Have you a complete short example which can be compiled and run and which demonstrates the problem?

User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 5:40 pm

I made a torn down program with the same behavior

Code: Select all

// PlateDemo.c
// This program is for testing the raspberry pi SPI control
// more specificity the setting up which chip select pin to use (CE0 or CE1)
#include <stdio.h>          /// IO functions
#include <time.h>           /// Used for delay function

#include <wiringPi.h>       /// for GPIO control
#include <wiringPiSPI.h>    /// For SPI control

#define SendCount 4

int main(void)
{
    int k;
    char Send[SendCount];
    int SPIComPort;

    wiringPiSetupGpio();                        // Set up wiring pi

    SPIComPort = wiringPiSPISetup(0, 250000);   // Set up SPI com works with 0 not with 1 (250000 is clock speed)
    printf("Com: %i\n", SPIComPort);            // Show the com number to show its not -1

    // Loop around writing to the SPI com line
    for(k=0;k<6;++k)
    {
        Send[0] = Send[1] = Send[2] = Send[3] = k;      // Just put some random data in the output
        wiringPiSPIDataRW(SPIComPort, Send, SendCount); // Write the data
        delay(1000);                                    // Dwell for a little while
    }

    printf("Complete\n");
    return 0;
}
I compile it with this:

Code: Select all

gcc -c ./PlateDemo.c -o ./PlateDemo.o ; g++  -o ./PlateDemo ./PlateDemo.o -lwiringPi ; sudo ./PlateDemo

When I change the 0 to a 1 in wiringPiSPISetup I no longer detect any SPI functionality.

User avatar
joan
Posts: 14181
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 6:34 pm

I had a quick look and it does not appear to work.

Perhaps raise an issue with wiringPi?

User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 7:42 pm

Thanks for confirming.

User avatar
gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 7:53 pm

The wiringPi SPI code is just dumbed-down wrappers round the standard Linux kernel SPI code. They really are just one or 2 liners for those who don't know how to read the documentation.

Read the source code to see what's happening, but in essence it's:

Code: Select all

  snprintf (spiDev, 31, "/dev/spidev0.%d", channel) ;

  if ((fd = open (spiDev, O_RDWR)) < 0)
    return wiringPiFailure (WPI_ALMOST, "Unable to open SPI device: %s\n", strerror (errno)) ;
so all it's doing is opening the /dev/spidev0.0 or /dev/spidev0.1 devices. After that, it's all up to the kernel and nothing to do with wiringPi.

Unless, of-course, something has changed in the 6 years since I wrote that code, but hey ho what do I know. Other GPIO libraries are available.

-Gordon
--
Gordons projects: https://projects.drogon.net/

User avatar
joan
Posts: 14181
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 8:25 pm

The following Python works on slave select 1.

Code: Select all

#!/usr/bin/env python

import spidev

conn = spidev.SpiDev(0, 1)
conn.max_speed_hz = 20000
cmd = 0xaa
reply_bytes = conn.xfer([cmd, 0x55])

print(reply_bytes)
spidev is also a wrapper around the Linux SPI routines.

fbe
Posts: 494
Joined: Thu Aug 17, 2017 9:08 pm

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 8:33 pm

You should not use the return value from wiringPiSPISetup as channel in wiringPiSPIDataRW.

User avatar
scootergarrett
Posts: 46
Joined: Sat Apr 19, 2014 2:36 pm

Re: Wirring pi and SPI communication

Wed Dec 26, 2018 8:56 pm

fbe I think you got it.
when I use

Code: Select all

SPIComPort = wiringPiSPISetup(1, 250000);
with

Code: Select all

wiringPiSPIDataRW(1, Send, SendCount);
its behaving as I would expect. Now that I take 2 seconds and look that the first argument in wiringPiSPIDataRW is 'channel'. Its intresting that it was working with:

Code: Select all

SPIComPort = wiringPiSPISetup(1, 250000);
but that may have been coincidence

Thanks all, sorry for bothering you gordon.

Now time to put the PiPlate back on.

AnneRanch
Posts: 91
Joined: Fri Oct 19, 2018 1:48 pm

Re: Wirring pi and SPI communication

Mon Dec 31, 2018 7:52 pm

From my recent encounter with coding SPI ( in C++) I strongly recommend NOT to use abbreviations / labels from hardware or software.
SPI in "non standard" standard and one has to be aware of that.


In this thread the "problem" is in selecting the "channel" from single SPI HARDWARE interface as available on RPi.
The RPI ( master SPI) hardware "destination' is CE 0 / CE 1 , which is commonly called "SS" as in "slave select" on some slave SPI hardware , or "CS" as in "chip select".
If one asks Linux for SPI devices using "system("ls -l /dev/spi*");" one gets spidev0.0 and spidev0.1 and it best to be coded /passed to (C++) functions as such.

It all depends how the "channel" parameter is actually defined in your function.

Return to “C/C++”