Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 50

Thread: SPI Returns Zero with IMU Sensor on Teensy 3.2

  1. #1
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90

    SPI Returns Zero with IMU Sensor on Teensy 3.2

    I'm attempting to open SPI communication with my IMU Sensor (LSM6DS3 breakout) from Sparkfun (https://www.sparkfun.com/products/13339). It's worked with the Arduino-Due, but I'm having trouble with the Teensy 3.2. My program keeps returning zeros when I ping the WHO_AM_I address. Code below demos the issue. I appreciate your help.

    Code:
    #include <SPI.h>  // include the SPI library:
    
    #define   READ    0x80 
    #define   WRITE   0x00
    #define   SSX     20
    
    SPISettings SETA(100000, MSBFIRST, SPI_MODE3); 
    
    
    void setup()
    {
        uint8_t   address;
        uint16_t  out1, out2, out3;
    
        // INITIALIZE PINS
        delayMicroseconds(3000000);
        Serial.begin(115200); 
    
    
        // INITIALIZE SPI
        pinMode (SSX, OUTPUT);
        SPI.setMOSI(7);
        SPI.setMISO(8);
        SPI.setSCK(14);
        SPI.begin(); 
    
        delayMicroseconds(1000);
    
        // SPI COMMUNICATION
        SPI.beginTransaction(SETA);    
        digitalWrite(SSX,LOW);
        
        address = 0x0F;                // WHO-AM-I BYTE
        out1 = SPI.transfer(address);    
        out2 = SPI.transfer(READ);    
        out3 = SPI.transfer(0x00);  
             
        digitalWrite(SSX,HIGH); 
    
        
        Serial.println("Who Am I:");
        Serial.println(out1);
        Serial.println(out2);
        Serial.println(out3);    
    }
    
    
    void loop()
    { 
    }

  2. #2
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    Also tried removing the statements: SPI.setMOSI, SPI.setMISO and SPI.setSCK, but no luck.

    Is the SPI library fully functional for the Teensy 3.2?

  3. #3
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,915
    SPI certainly can work since it's driving my project at the moment. Though I think you have data in and data out swapped over. If this is on a bread board would suggest using the default pins to start with, which among other things means you can see SPI activity as the on board LED goes active. If the pins aren't the problem would also suggest checking
    https://www.pjrc.com/teensy/td_libs_SPI.html
    and making sure nothing in the example is breaking anything in the transaction method they use.

  4. #4
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,568
    Quote Originally Posted by GremlinWrangler View Post
    and making sure nothing in the example is breaking anything in the transaction method they use.
    in particular, transaction method handles chip select, and should not be done by hand.

  5. #5
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    Quote Originally Posted by GremlinWrangler View Post
    Though I think you have data in and data out swapped over.
    My code sets the pins specified in table displayed here: https://www.pjrc.com/teensy/td_libs_SPI.html . Are those not the default?

    As far as the chip-select pin, what is the default for that? I use pin 20 because the example code listed in the html above uses it.

    The onboard amber LED does go off.

    Quote Originally Posted by WMXZ
    in particular, transaction method handles chip select, and should not be done by hand.
    What is meant by "should not be done by hand"?

  6. #6
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,568
    Quote Originally Posted by randomvibe View Post
    My code sets the pins specified in table displayed here: https://www.pjrc.com/teensy/td_libs_SPI.html . Are those not the default?

    As far as the chip-select pin, what is the default for that? I use pin 20 because the example code listed in the html above uses it.

    The onboard amber LED does go off.


    What is meant by "should not be done by hand"?
    Code:
     digitalWrite(SSX,LOW);
    ....
     digitalWrite(SSX,HIGH);

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,473
    I've only looked breifly, but I don't see SPI.endTransaction() in your program.

    You need to pair every beginTransaction with endTransaction.

  8. #8
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    Quote Originally Posted by PaulStoffregen View Post
    I've only looked breifly, but I don't see SPI.endTransaction() in your program. You need to pair every beginTransaction with endTransaction.
    I tried that too, but no luck. The Teensy's onboard LED does light.

    My latest code is shown below. It was implemented on the Arduino 1.6.8 IDE using Teensyduino v1.28. It compiles fine and displays the serial commands, but the SPI.transfer lines return zeros. The WHO_AM_I register should return 69h. What am I missing here?

    Code:
    #include <SPI.h>  // include the SPI library:
    
    #define   READ    0x80 
    #define   WRITE   0x00
    #define   MOSIX   7
    #define   MISOX   8
    #define   SCKX    14
    #define   SSX     20
    
    SPISettings SETA(1000000, MSBFIRST, SPI_MODE3); 
    
    
    void setup()
    {
        uint8_t   address;
        uint16_t  out1, out2, out3;
    
    
        // INITIALIZE PINS
        delayMicroseconds(6000000);
        Serial.begin(115200); 
        Serial.println("Hello:");
    
    
        // INITIALIZE SPI
        pinMode (SSX, OUTPUT);
        digitalWrite(SSX,HIGH);
     
        SPI.begin(); 
        SPI.setMOSI(MOSIX);
        SPI.setMISO(MISOX);
        SPI.setSCK(SCKX);
    
        delayMicroseconds(1000000);
    
        // SPI COMMUNICATION
        SPI.beginTransaction(SETA);    
        digitalWrite(SSX,LOW);
        
        address = 0x0F;  // WHO-AM-I BYTE
        
        delayMicroseconds(1);
        out1 = SPI.transfer(address);    
        delayMicroseconds(1);
        out2 = SPI.transfer(READ);    
        delayMicroseconds(1);
        out3 = SPI.transfer(0x00);  
                
        digitalWrite(SSX,HIGH); 
    
        SPI.endTransaction();
    
      
        Serial.println("Who Am I:");
        Serial.println(out1);
        Serial.println(out2);
        Serial.println(out3);
    }
    
    
    void loop()
    { 
    }

  9. #9
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,915
    My suggestion at the moment if it's possible is to recheck your wiring and if possible post a photo of the setup. Do you have access to an osciliscope? My suggested next step would be to probe the pins on the break out board and confirm it's getting all the signals etc elctrically.

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,473
    Quote Originally Posted by randomvibe View Post
    What am I missing here?
    Looks like it ought to work, at least the code. Maybe a wiring mistake? Can you post some good photos showing how you've actually connected everything?

  11. #11
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,473
    Might also be worthwhile trying I2C instead of SPI. Even if you *really* want SPI, using I2C could at least confirm if all the hardware actually works.

  12. #12
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    Photos enclosed. PJRC board is A Teensy 3.2. The IMU is a LSM9DS0 chip on a Sparkfun breakout board (https://www.sparkfun.com/products/13339). The IMU board and wire harness (3 feet in length) were SPI and I2C tested on an Arduino-Due, so the wiring works. The order of the pins from left-to-right are: GND, VDD, MOSI, SCL, MISO, and CS (https://learn.sparkfun.com/tutorials...483.1464756633).

    I also tried the spi4teensy3 library, but no luck. Documentation is very limited, so I'm not sure of the implementation.

    What else can I try?
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	IMG_0303.jpg 
Views:	101 
Size:	96.4 KB 
ID:	7267   Click image for larger version. 

Name:	IMG_0305.jpg 
Views:	42 
Size:	89.5 KB 
ID:	7268  

    Click image for larger version. 

Name:	IMG_0306.jpg 
Views:	102 
Size:	101.3 KB 
ID:	7269  

  13. #13
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,335
    Sorry, I may be completely off, but looking at your photos, it looks like you are running AGND (Analog ground) to the sensor. Have you tried running one of the GND pins instead? Not sure how much of a difference it would make.

  14. #14
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    I think I found the problem. It might be my wire harness. Will check it tonight.

  15. #15
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,473
    Quote Originally Posted by randomvibe View Post
    Code:
        SPI.begin(); 
        SPI.setMOSI(MOSIX);
        SPI.setMISO(MISOX);
        SPI.setSCK(SCKX);
    You need to configure the SPI pins before SPI.begin(), like this:

    Code:
        SPI.setMOSI(MOSIX);
        SPI.setMISO(MISOX);
        SPI.setSCK(SCKX);
        SPI.begin();
    KurtE also has a good point about the ground pin. Use normal ground, not analog ground.

    Sparkfun also has a library with several examples for this product. The library has specific code for Teensy 3.1, so presumably it's been tested and is known to work on Teensy. If all else fails, at least for testing, perhaps use the normal SPI pins and give Sparkfun's library a try. Even if you can't use it for various reasons, running their known good code rather than code you've written from scratch could help you get up and running. From there, perhaps adapt to what you need?

  16. #16
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    The Sparkfun library for SPI did not work, at least on the Arduino-Due. I2C did work out-of-the-box. I had to write my own code for SPI, and eventually it worked.

    Back to the Teensy, I'll use the normal ground. But I think I found the problem: it's my wire harness. The two ends are not identical. The breadboard end is ordered to match another project. I'll check it tonight. Thanks for your help.

  17. #17
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,473
    Quote Originally Posted by randomvibe View Post
    The Sparkfun library for SPI did not work, at least on the Arduino-Due.
    But did you even try Sparkfun's library with Teensy?

    Since it has a #define and comment specifically mentioning Teensy 3.1, odds are very good it will "just work" on your Teensy 3.2, even though it's incompatible with Arduino Due.

    In fact, there are a *LOT* of libraries and programs that work on Teensy but not on Arduino Due. Teensy has quite a lot of work in the core library for compatibility with code written for Arduino Uno. Due does not. So testing with Due is a very poor way to evaluate what you should do with Teensy.

  18. #18
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,936
    On close inspection it may be that White_Orange and White_Brown are swapped.

    Using the Lib noted in p#17 would be the right start.

    Also - to answer above p#5 question - the pins in use are the ALTERNATE pins, not the default in the table you linked to.

  19. #19
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    Quote Originally Posted by defragster View Post
    On close inspection it may be that White_Orange and White_Brown are swapped.
    The photo makes it appear that way, but I checked it closely, and the wire harness is okay after all.

    I changed the SPI pins from the "alternates" to the "default", but no luck. I put the SPI.set* commands before the SPI.begin() call, but no luck. Added a longer delayMicroseconds() delay, but no luck.

    Then success at last. I changed the SPISettings SPI mode from SPI_MODE3 to SPI_MODE0, and the WHO_AM_I call returned the correct byte. The hint came from examining the Sparkfun library. Apparently, SPI_MODE has different meanings between Teensy and Due. I recommend adding a bit more documentation in: https://www.pjrc.com/teensy/td_libs_SPI.html

    Here's my working code:

    Code:
    #include <SPI.h>  // include the SPI library:
    
    #define   READ    0x80 
    #define   WRITE   0x00
    #define   MOSIX   11
    #define   MISOX   12
    #define   SCKX    13
    #define   SSX     10
    
    SPISettings SETA(1000000, MSBFIRST, SPI_MODE0); 
    
    
    void setup()
    {
        uint8_t   address;
        uint16_t  out1, out2;
    
    
        // INITIALIZE PINS
        delayMicroseconds(6000000);
        Serial.begin(115200); 
        Serial.println("Hello:");
    
    
        // INITIALIZE SPI
        pinMode(SSX, OUTPUT);
        digitalWrite(SSX,HIGH);
     
        SPI.setMOSI(MOSIX);
        SPI.setMISO(MISOX);
        SPI.setSCK(SCKX);
        SPI.begin(); 
    
    
        // SPI COMMUNICATION
        SPI.beginTransaction(SETA);
          
        digitalWrite(SSX,LOW);
        
        address = 0x0F;  // WHO-AM-I BYTE
        
        delayMicroseconds(1);
        out1 = SPI.transfer(address | READ);    
        out2 = SPI.transfer(0x00);  
                
        digitalWrite(SSX,HIGH); 
    
        SPI.endTransaction();
    
      
        Serial.println("Who Am I:");
        Serial.println(out2);
    }
    
    
    void loop()
    { 
    }
    My goal is to stream back accel and gyro readings at a prescribed time step while the IMU is stationary. On the Arduino-Due, I get ticks in the readings well beyond the noise floor of the measurements. I'm not sure if it's the IMU chip or the Due. We'll see what happens with the Teensy.
    Last edited by randomvibe; 06-02-2016 at 07:49 AM.

  20. #20
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    The SPI functionality works fine when reading and writing to a handful of registers to initialize the IMU device. But when I stream the accel & gyro readings every 0.01 seconds, I pick up a lot of dropouts. By dropouts I mean the SPI readings return nearly zero counts or 2^16 counts (IMU resolution is 16 bits). I noticed when I move the CAT5 cable away from my wireless keyboard, the situation improves. Or if I bend the CAT5 wires at the ends, the readings change drastically. My CAT5 cable is approximately 3 feet long. Is a different cable recommended here? Is I2C more robust in this situation? Thanks.

  21. #21
    Senior Member
    Join Date
    Nov 2015
    Location
    Wales
    Posts
    579
    If you wish to use SPI for this either reduce it's speed or use shielded CAT5 cables. I'd recommend doing both

    At 3 feet you probably want to start considering a different communication protocol

    I2C I'd consider to suffer from the same issues. It is by default slower though

  22. #22
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    Maybe I'll go with a shielded CAT6 cable then.

    To reduce noise and EMI interference with my device, the 3 foot cable, and a Teensy 3.2, what is the best approach for pairing up the SPI lines (CLK, MOSI, MISO, SS)? Is it best to pair up MOSI with MISO, and CLK with Ground? Or MOSI with Ground, MISO with VCC, CLK with SS? What about pull-up resistors for this situation? Thanks.

  23. #23
    Senior Member
    Join Date
    Nov 2015
    Location
    Wales
    Posts
    579
    Isolate the CLK with a GND line. MOSI and MISO can go together as they probably won't be transmitting at the same time. SS can go wherever unless it toggles a lot which it normally doesn't.
    Ground all unused cables at both ends

  24. #24
    Member randomvibe's Avatar
    Join Date
    Mar 2016
    Location
    CA
    Posts
    90
    Quote Originally Posted by Xenoamor View Post
    Isolate the CLK with a GND line. MOSI and MISO can go together as they probably won't be transmitting at the same time. SS can go wherever unless it toggles a lot which it normally doesn't.
    Ground all unused cables at both ends
    Are pull-ups required for Teensy 3.2 SPI? I2C requires 4.7K resistors, but is the same true for SPI?

  25. #25
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,936
    Only pullups I've seen are on the CS lines to make sure no sharing devices 'float' into an active transmission for another device. I just saw this myself having a touch display where I didn't start the software on the Touch part of the display unit and the T_CS pin wasn't held high so it corrupted the display data on the shared data lines.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •