SPI library on Teency 3.2

Status
Not open for further replies.

Lorenzo

Well-known member
Hi everybody,

I am pretty new in Teency world and I need a little help with my project.

I am trying to read data from an encoder on Teency 3.2 by means of a Dual Encoder Breakout
https://www.superdroidrobots.com/shop/item.aspx/dual-ls7366r-quadrature-encoder-buffer/1523/

I am using the sample code I have downloaded from here:

https://github.com/SuperDroidRobots/Encoder-Buffer-Breakout

but Teency 3.2 does not read any value.

The wires are connected as reported here:
https://www.pjrc.com/teensy/td_libs_SPI.html

that is:

MISO pin 12
MOSI pin 11
SCK pin 13
SS pin 10

I am thinking the library has blocked the pins in any way.
Any suggestions?

Thank you very much in advance!

Lorenzo
 
Don't know what you're doing, but the T3.2, 3.5 and 3.6 have 2 built in quadrature encoders with 16-bit counters attached, so no need for the external chip.
 
I would like to read data via SPI from Dual Encoder Breakout to which the encoder is connected.
How can I read the encoders directly from Teency 3.2?
Thank you
 
You need to connect your SS pins from the breakout board to ports 7 & 8, not 10.

Code:
// Slave Select pins for encoders 1 and 2
// Feel free to reallocate these pins to best suit your circuit
const int slaveSelectEnc1 = 7;
const int slaveSelectEnc2 = 8;

That above is a snippet from the github you linked to. Cable up Encoder 1 to pin 7 and Encoder2 to pin 8 on the Teensy.
Then the code should work. Key word is "should". I didn't review the entire code, but it looks standard.
 
I have tried but it does not work.
Is there a way to read data from the encoders directly from Teency 3.2?
 
Would you provide what you have tried? Sample code would be great. Based on what I’ve seen, there is no reason why it wouldn’t work if cabled correctly.

I recommend providing a picture of it cabled up, and the code you have tried uploading. After that myself or someone on the forum would be more than happy to give advice.
 
Ls7366r

Here's some code that I successfully used some time ago to read a 50,000 count encoder with a single LSI LS7366R with a Teensy 3.2.

For my application, I only had one encoder so I tied the SS pin on the LS7366 to ground. You'll need to define the slave select pins and duplicate the code to read the second encoder.

Code:
#include <SPI.h>

#define CLR B00000000
#define RD B01000000
#define WR B10000000
#define LOAD B11000000

#define MDR0 B00001000
#define MDR1 B00010000
#define DTR B00011000
#define CNTR B00100000
#define OTR B00101000
#define STR B00110000

// filter factor 1
// async index
// no index
// free-running
// 4x quadrature
#define MDR0_CONF B00000011

// no flag
// enabled
// 32 bits
#define MDR1_CONF B00000000

SPISettings settings(16000000, MSBFIRST, SPI_MODE1); 

void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT);
  SPI.setSCK(14);      //redefine SCK from Pin 13 to Pin 14 for Teensy3.2
  //SPI.setMOSI(7); //alternate Teensy 3X MOSI pin,  pin 11 is default
  //SPI.setMISO(8); //alternate Teensy 3X MISO pin,  pin 12 is default
  SPI.begin();
  pinMode(SS, OUTPUT);
  
  SPI.beginTransaction(settings);
  digitalWrite(SS, LOW);
  SPI.transfer(WR | MDR0);
  SPI.transfer(MDR0_CONF);
  digitalWrite(SS, HIGH);
  
  digitalWrite(SS, LOW);
  SPI.transfer(WR | MDR1);
  SPI.transfer(MDR1_CONF);
  digitalWrite(SS, HIGH);
  
  digitalWrite(SS, LOW);
  SPI.transfer(CLR | CNTR);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

long count = 0;

void loop() {
  SPI.beginTransaction(settings);
  digitalWrite(SS, LOW);
  byte b = SPI.transfer((byte) RD | CNTR);
  count = SPI.transfer(0x00);
  count <<= 8;
  count |= SPI.transfer(0x00);
  count <<= 8;
  count |= SPI.transfer(0x00);
  count <<= 8;
  count |= SPI.transfer(0x00);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
  Serial.print(count);
  Serial.println();
  digitalWrite(13,!digitalRead(13));
  delayMicroseconds(100000);
}
 
Last edited:
Scratch that comment about SS being tied to ground.
I found the board, and it's wired like this:

Code:
LS7366R      Teensy
4 SS          10  SS
5 SCK         14  ALT SCK
6 MISO        11  MOSI
7 MOSI        12  MISO
              13  LED

You may need to add a line like
const int SS = 10;
in the header of the program
 
Thank you for your suggestions.

This is the code I have uploaded:

Code:
#include <SPI.h>

#define CLR B00000000
#define RD B01000000
#define WR B10000000
#define LOAD B11000000

#define MDR0 B00001000
#define MDR1 B00010000
#define DTR B00011000
#define CNTR B00100000
#define OTR B00101000
#define STR B00110000

// filter factor 1
// async index
// no index
// free-running
// 4x quadrature
#define MDR0_CONF B00000011

// no flag
// enabled
// 32 bits
#define MDR1_CONF B00000000

//const int SS = 10;
#define SS 10  

//SPISettings settings(16000000, MSBFIRST, SPI_MODE1); 
SPISettings settings(200000, MSBFIRST, SPI_MODE1); 

void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT);
  SPI.setSCK(14);      //redefine SCK from Pin 13 to Pin 14 for Teensy3.2
  //SPI.setMOSI(7); //alternate Teensy 3X MOSI pin,  pin 11 is default
  //SPI.setMISO(8); //alternate Teensy 3X MISO pin,  pin 12 is default
  SPI.begin();
  pinMode(SS, OUTPUT);
  
  SPI.beginTransaction(settings);
  digitalWrite(SS, LOW);
  SPI.transfer(WR | MDR0);
  SPI.transfer(MDR0_CONF);
  digitalWrite(SS, HIGH);
  
  digitalWrite(SS, LOW);
  SPI.transfer(WR | MDR1);
  SPI.transfer(MDR1_CONF);
  digitalWrite(SS, HIGH);
  
  digitalWrite(SS, LOW);
  SPI.transfer(CLR | CNTR);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

long count = 0;

void loop() {
  SPI.beginTransaction(settings);
  digitalWrite(SS, LOW);
  byte b = SPI.transfer((byte) RD | CNTR);
  count = SPI.transfer(0x00);
  count <<= 8;
  count |= SPI.transfer(0x00);
  count <<= 8;
  count |= SPI.transfer(0x00);
  count <<= 8;
  count |= SPI.transfer(0x00);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
  Serial.print(count);
  Serial.println();
  digitalWrite(13,!digitalRead(13));
  delayMicroseconds(100000);
}

And here there are the pictures of the schematic.

IMG_3037.jpgIMG_3038.jpgIMG_3039.jpgIMG_3040.jpg


Encoder wires are:

green V
purple GND
yellow Channel A
blue Channel B

My Encoder is a 2000 counts one:

https://prototypes.haydonkerk.com/ecatalog/brush-dc-motors/en/brush-dc-motors-GM9236S015-R1-SP

I still read only 0 from the SPI.
 
Last edited:
Don't know what you're doing, but the T3.2, 3.5 and 3.6 have 2 built in quadrature encoders with 16-bit counters attached, so no need for the external chip.

@grease_lighting

Could you please exlpain me how to read data from encoder directly from Teency 3.2? Thank you so much
 
Lorenzo,

It looks like your yellow sck wire is hooked to pin 13 on the Teensy, but the code is defining it as alternate SPI SCK pin 14.
Try to move the Yellow wire to pin 14.
Also can you please post a photo of the bottom side of your perf board, and details about the encoder that you are using.

Bob Wozniak
 
See my post here: https://forum.pjrc.com/threads/39435-Flex-timer-problem?highlight=FTM and search in this forum for 'FTM' or 'FLEX TIMER'. Also look in the K20 reference manual (large pdf) linked to on the PJRC website.

The PORT statements configure pins 3&4 to be quadrature inputs to the flex timer #1. There are other register loads to configure, clear or preset the counter. Applying a clock to input PHA and direction level to PHB, one makes the counter go up or down in value. It may be read with the FTM1_CNT statement. There are some misc register bits to invert the count direction information.
 
Lorenzo,

It looks like your yellow sck wire is hooked to pin 13 on the Teensy, but the code is defining it as alternate SPI SCK pin 14.
Try to move the Yellow wire to pin 14.
Also can you please post a photo of the bottom side of your perf board, and details about the encoder that you are using.

Bob Wozniak

Yes, thank you. I have correct the pins 14 and 10 but it still doesn't work.

IMG_3041.jpg
IMG_3042.jpg
IMG_3043.jpg

The encoder datasheet can be found here:

https://prototypes.haydonkerk.com/ecatalog/brush-dc-motors/en/brush-dc-motors-GM9236S015-R1-SP
 
Last edited:
Using the flex timer resources does not place any computational load onto the Teensy. It's all done with hardware inside the K20/K64/K66 chip. Only resource that it uses are a few pins.
 
@Wozzy

Should I modify something in my code if I am using a 2000 counts encoder? Thank you

@grease_lighting

Is there any example on how to use the flex timer? Thank you
 
Would you provide what you have tried? Sample code would be great. Based on what I’ve seen, there is no reason why it wouldn’t work if cabled correctly.

I recommend providing a picture of it cabled up, and the code you have tried uploading. After that myself or someone on the forum would be more than happy to give advice.

I have powered it with 3.3 V but it still does not work.
This is my code and a picture of the connections:


Code:
//=========================HEADER=============================================================
/*
   Dual LS7366 Quadrature Counter Test Code
   AUTHOR: Jason Traud
   DATE: June 22, 2013
   
   This is a simple test program to read encoder counts
   collected by the LS7366 breakout board. The counts are
   then displayed in the Arduino's serial monitor at a 
   baud rate of 9600
   
   Hardware: Arduino Uno R3
   Powered 
   
   LS7366 Breakout    -------------   Arduino
   -----------------                    -------
            MOSI   -------------------   SDO (D11)
            MISO   -------------------   SDI (D12)
            SCK    -------------------   SCK (D13)
            SS1    -------------------   SS1 (D7)
            SS2    -------------------   SS2 (D8)
            GND    -------------------   GND
            VDD    -------------------   VCC (5.0V)
			
   License: CCAv3.0 Attribution-ShareAlike (http://creativecommons.org/licenses/by-sa/3.0/)
   You're free to use this code for any venture. Attribution is greatly appreciated. 

//============================================================================================
*/

// Inclde the standard Arduino SPI Library, please ensure the SPI pins are
// connected properly for your Arduino version
#include <SPI.h>

// Slave Select pins for encoders 1 and 2
// Feel free to reallocate these pins to best suit your circuit
const int slaveSelectEnc1 = 11;
const int slaveSelectEnc2 = 12;

// These hold the current encoder count.
signed long encoder1count = 0;
signed long encoder2count = 0;

void initEncoders() {
  
  // Set slave selects as outputs
  pinMode(slaveSelectEnc1, OUTPUT);
  pinMode(slaveSelectEnc2, OUTPUT);
  
  // Raise select pins
  // Communication begins when you drop the individual select signsl
  digitalWrite(slaveSelectEnc1,HIGH);
  digitalWrite(slaveSelectEnc2,HIGH);


  SPI.begin();
  
  // Initialize encoder 1
  //    Clock division factor: 0
  //    Negative index input
  //    free-running count mode
  //    x4 quatrature count mode (four counts per quadrature cycle)
  // NOTE: For more information on commands, see datasheet
  digitalWrite(slaveSelectEnc1,LOW);        // Begin SPI conversation
  SPI.transfer(0x88);                       // Write to MDR0
  SPI.transfer(0x03);                       // Configure to 4 byte mode
  digitalWrite(slaveSelectEnc1,HIGH);       // Terminate SPI conversation 

  // Initialize encoder 2
  //    Clock division factor: 0
  //    Negative index input
  //    free-running count mode
  //    x4 quatrature count mode (four counts per quadrature cycle)
  // NOTE: For more information on commands, see datasheet
  digitalWrite(slaveSelectEnc2,LOW);        // Begin SPI conversation
  SPI.transfer(0x88);                       // Write to MDR0
  SPI.transfer(0x03);                       // Configure to 4 byte mode
  digitalWrite(slaveSelectEnc2,HIGH);       // Terminate SPI conversation 
}

long readEncoder(int encoder) {
  
  // Initialize temporary variables for SPI read
  unsigned int count_1, count_2, count_3, count_4;
  long count_value;  
  
  // Read encoder 1
  if (encoder == 1) {
    digitalWrite(slaveSelectEnc1,LOW);      // Begin SPI conversation
    SPI.transfer(0x60);                     // Request count
    count_1 = SPI.transfer(0x00);           // Read highest order byte
    count_2 = SPI.transfer(0x00);           
    count_3 = SPI.transfer(0x00);           
    count_4 = SPI.transfer(0x00);           // Read lowest order byte
    digitalWrite(slaveSelectEnc1,HIGH);     // Terminate SPI conversation 
  }
  
  // Read encoder 2
  else if (encoder == 2) {
    digitalWrite(slaveSelectEnc2,LOW);      // Begin SPI conversation
    SPI.transfer(0x60);                      // Request count
    count_1 = SPI.transfer(0x00);           // Read highest order byte
    count_2 = SPI.transfer(0x00);           
    count_3 = SPI.transfer(0x00);           
    count_4 = SPI.transfer(0x00);           // Read lowest order byte
    digitalWrite(slaveSelectEnc2,HIGH);     // Terminate SPI conversation 
  }
  
  // Calculate encoder count
  count_value = (count_1 << 8) + count_2;
  count_value = (count_value << 8) + count_3;
  count_value = (count_value << 8) + count_4;
  
  return count_value;
}

void clearEncoderCount() {
    
  // Set encoder1's data register to 0
  digitalWrite(slaveSelectEnc1,LOW);      // Begin SPI conversation  
  // Write to DTR
  SPI.transfer(0x98);    
  // Load data
  SPI.transfer(0x00);  // Highest order byte
  SPI.transfer(0x00);           
  SPI.transfer(0x00);           
  SPI.transfer(0x00);  // lowest order byte
  digitalWrite(slaveSelectEnc1,HIGH);     // Terminate SPI conversation 
  
  delayMicroseconds(100);  // provides some breathing room between SPI conversations
  
  // Set encoder1's current data register to center
  digitalWrite(slaveSelectEnc1,LOW);      // Begin SPI conversation  
  SPI.transfer(0xE0);    
  digitalWrite(slaveSelectEnc1,HIGH);     // Terminate SPI conversation   
  
  // Set encoder2's data register to 0
  digitalWrite(slaveSelectEnc2,LOW);      // Begin SPI conversation  
  // Write to DTR
  SPI.transfer(0x98);    
  // Load data
  SPI.transfer(0x00);  // Highest order byte
  SPI.transfer(0x00);           
  SPI.transfer(0x00);           
  SPI.transfer(0x00);  // lowest order byte
  digitalWrite(slaveSelectEnc2,HIGH);     // Terminate SPI conversation 
  
  delayMicroseconds(100);  // provides some breathing room between SPI conversations
  
  // Set encoder2's current data register to center
  digitalWrite(slaveSelectEnc2,LOW);      // Begin SPI conversation  
  SPI.transfer(0xE0);    
  digitalWrite(slaveSelectEnc2,HIGH);     // Terminate SPI conversation 
}


void setup() {
 Serial.begin(9600);      // Serial com for data output
 
 initEncoders();       Serial.println("Encoders Initialized...");  
 clearEncoderCount();  Serial.println("Encoders Cleared...");
}

void loop() 
{
 delay(100);
 // Retrieve current encoder counters
 encoder1count = readEncoder(1); 
 encoder2count = readEncoder(2);
 Serial.print("Enc1: "); Serial.print(encoder1count); Serial.print(" Enc2: "); Serial.println(encoder2count); 
}


IMG_3050.jpg


ps. I have run the same code on an Arduino UNO and there I can read the encoder. Why it does not work on Teency 3.2?
 
Lorenzo,

I setup a breadboard with a Teensy 3.2, LS6377R and and Encoder.
I ran the code from Posts 7, 9, 20. All of them worked correctly.

For the code in post #20, I only changed the SS pin numbers to 9 & 10, and A also jumpered those two pins together to simulate 2 LS6377Rs.

Here are photos of my setup and a screen capture showing the output.
2018-02-01 19_31_42-Clipboard.jpg
IMG_20180201_192627.jpg
IMG_20180201_192554.jpg

So since we know the software is good.

Can you please answer a few questions.
When you switch between the working Arduino and the nonworking Teensy, are you only changing the microcontroller wires, and not the wiring between the encoder and the LS7366R board?
If so than this shows that the Board is getting the encoder signals correctly and that the encoder is powered correctly.
How are you providing power to this circuit?
Can you please show a photo of the bottom of the Perf-Board that the Teensy is attached to?
What version of Arduino and Teensyduino are you using? (FYI, I compiled it today on Arduino 1.8.5 and Teensyduino 1.40)
Are you able to successfully compile and run the blinky program on your Teensy?

Edit: It's actually a Teensy 3.1, not a Teensy 3.2 that I'm using
 
Last edited:
I do not see how this part of your code could work on Arduino Uno or Teensy 3.2. These are the pins for MOSI and MISO, so you can't also use them for the chip select signals!

// Slave Select pins for encoders 1 and 2
// Feel free to reallocate these pins to best suit your circuit
const int slaveSelectEnc1 = 11;
const int slaveSelectEnc2 = 12;

Well, it could maybe work on Teensy 3.2 if you carefully used SPI.setMOSI() and SPI.setMISO() to reassign those signals to other pins, before you use SPI.begin(). The MOSI and MISO pins can't be reassigned on regular Arduino, so I'm pretty sure this code could not work at all with Arduino Uno.

In your photo, I see green and gray wires connected from Teensy pins 11 and 12 to the MOSI and MISO pins on that blue circuit board. I also see red and orange wires connected on Teensy pins 7 and 8 to the S1 and S2 pins on that blue board.

The tan color board you used for wiring has numbers on it too, which are meaningless. But I see the orange and red wires are positioned close to the numbers 11 and 12 on the tan board. If there any chance you mistakenly typed 11 and 12 into your program, based on those white numbers of the tan board, rather than the actual pin numbers 7 & 8 Teensy uses (on the pinout reference card that came with your Teensy)?
 
I think the code is only for C, right? I have not found a version for Teency microcontroller.

(shakes head) I don't think anyone here is going to write the code for you. We will provide tips & hints. The .cpp is the <CODE> you need to program the Teensy in the Arduino environment There are also some header .h (driver) files that you include in your code. I realize the link to my post on the FTM as encoder was not explicit, but there was code you could use to explore how it works as a quadrature encoder. I provided a few hints in that post too. We are all hackers here who take what others have done before us and shape it into what we need. No body here would give you Perl code to run on a Teensy. I also note you are using a T3.1 which may have yet another manual to peruse to determine how the FTM functions on a T3.1. Paul has done an excellent job in keeping the nomenclature used in the manual to be part of the commands to make it easier for all of us to use Teensy.
 
Lorenzo,

I setup a breadboard with a Teensy 3.2, LS6377R and and Encoder.
I ran the code from Posts 7, 9, 20. All of them worked correctly.

For the code in post #20, I only changed the SS pin numbers to 9 & 10, and A also jumpered those two pins together to simulate 2 LS6377Rs.

Here are photos of my setup and a screen capture showing the output.
View attachment 12817
View attachment 12818
View attachment 12819

So since we know the software is good.

Can you please answer a few questions.
When you switch between the working Arduino and the nonworking Teensy, are you only changing the microcontroller wires, and not the wiring between the encoder and the LS7366R board?
If so than this shows that the Board is getting the encoder signals correctly and that the encoder is powered correctly.
How are you providing power to this circuit?
Can you please show a photo of the bottom of the Perf-Board that the Teensy is attached to?
What version of Arduino and Teensyduino are you using? (FYI, I compiled it today on Arduino 1.8.5 and Teensyduino 1.40)
Are you able to successfully compile and run the blinky program on your Teensy?

Edit: It's actually a Teensy 3.1, not a Teensy 3.2 that I'm using


Thank you very much Wozzy!

Here the answers:

1) When I switch from Arduino to Teency I only change the microcontroller wires, so the blue board works properly.

2) With Arduino Uno I powered the circuit with Arduino 5V, on Teency with Teency 3.3 V, as you have done in your pictures.
I have also tryed to power the encoder board with an external power supply at 5 V (connecting the GND to Teency GND and the 5V to Teency Vin).

3) The picture of the bottom of the board:
IMG_3052.jpg

4) I am using Arduino 1.8.5 and Teensyduino 1.41.

5) The blink programm works on my Teency 3.2.


Thank you very much again.
 
Last edited:
I do not see how this part of your code could work on Arduino Uno or Teensy 3.2. These are the pins for MOSI and MISO, so you can't also use them for the chip select signals!



Well, it could maybe work on Teensy 3.2 if you carefully used SPI.setMOSI() and SPI.setMISO() to reassign those signals to other pins, before you use SPI.begin(). The MOSI and MISO pins can't be reassigned on regular Arduino, so I'm pretty sure this code could not work at all with Arduino Uno.

In your photo, I see green and gray wires connected from Teensy pins 11 and 12 to the MOSI and MISO pins on that blue circuit board. I also see red and orange wires connected on Teensy pins 7 and 8 to the S1 and S2 pins on that blue board.

The tan color board you used for wiring has numbers on it too, which are meaningless. But I see the orange and red wires are positioned close to the numbers 11 and 12 on the tan board. If there any chance you mistakenly typed 11 and 12 into your program, based on those white numbers of the tan board, rather than the actual pin numbers 7 & 8 Teensy uses (on the pinout reference card that came with your Teensy)?

Thank you Paul.
The code works on my Arduino with the following connections:

LS7366 Breakout ------------- Arduino
----------------- -------
MOSI ------------------- SDO (D11)
MISO ------------------- SDI (D12)
SCK ------------------- SCK (D13)
SS1 ------------------- SS1 (D7)
SS2 ------------------- SS2 (D8)
GND ------------------- GND
VDD ------------------- VCC (5.0V)

On Teency I have tryed to modify these pins:
Code:
const int slaveSelectEnc1 = 7;
const int slaveSelectEnc2 = 8;

as well as the MISO, MOSI and SCK as described here:

https://www.pjrc.com/teensy/td_libs_SPI.html
 
Status
Not open for further replies.
Back
Top